├── .env.example ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .gitpod.yml ├── .husky ├── pre-commit └── pre-push ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .vscode └── launch.json ├── LICENSE ├── README.md ├── netlify.toml ├── package-lock.json ├── package.json ├── playwright.config.ts ├── postcss.config.cjs ├── src ├── app.css ├── app.d.ts ├── app.html ├── lib │ ├── components │ │ ├── index │ │ │ ├── community-recommendations.svelte │ │ │ ├── developer-experience.svelte │ │ │ ├── founding-members.svelte │ │ │ ├── fragments │ │ │ │ ├── devx-blog.svelte │ │ │ │ ├── devx-conf.svelte │ │ │ │ ├── devx-pod.svelte │ │ │ │ ├── how-to-join-item.svelte │ │ │ │ ├── how-to-join.svelte │ │ │ │ └── join-now.svelte │ │ │ ├── hero.svelte │ │ │ ├── learn-more.svelte │ │ │ ├── sign-up.svelte │ │ │ └── what-is-this-community.svelte │ │ ├── layout │ │ │ ├── container.svelte │ │ │ ├── footer-dots.svelte │ │ │ ├── footer.svelte │ │ │ ├── mobile-nav │ │ │ │ ├── index.svelte │ │ │ │ └── toggle.svelte │ │ │ ├── nav.svelte │ │ │ └── theme-switcher.svelte │ │ ├── library │ │ │ ├── animated-line.svelte │ │ │ ├── animated-text.svelte │ │ │ ├── annotation.svelte │ │ │ ├── big-dot.svelte │ │ │ ├── content-section.svelte │ │ │ ├── dot.svelte │ │ │ ├── full-bleed.svelte │ │ │ ├── gradient-card-no-hover.svelte │ │ │ ├── gradient-card.svelte │ │ │ ├── gradient-content-card.svelte │ │ │ ├── gradient-link-button.svelte │ │ │ ├── icon-link.svelte │ │ │ ├── intersection-observer.svelte │ │ │ ├── link-button.svelte │ │ │ ├── open-graph.svelte │ │ │ ├── portrait-card.svelte │ │ │ ├── recommendation-item-section.svelte │ │ │ ├── reveal.svelte │ │ │ ├── section.svelte │ │ │ └── vertical-stroke.svelte │ │ └── svgs │ │ │ ├── devx.svelte │ │ │ ├── github.svelte │ │ │ ├── gitpod.svelte │ │ │ ├── linkedin.svelte │ │ │ ├── listen.svelte │ │ │ ├── read.svelte │ │ │ ├── switcher │ │ │ ├── moon.svelte │ │ │ └── sun.svelte │ │ │ ├── twitter.svelte │ │ │ └── watch.svelte │ ├── contents │ │ ├── index.ts │ │ ├── index │ │ │ ├── devx-content.ts │ │ │ ├── founding-members.ts │ │ │ ├── learn-more.ts │ │ │ └── recommendations.ts │ │ └── nav.ts │ ├── helper.ts │ ├── stores │ │ └── mobile-menu.ts │ ├── types │ │ ├── analytics.ts │ │ ├── gradient-content-card.type.ts │ │ ├── icon-link.ts │ │ ├── open-graph.type.ts │ │ ├── portrait.type.ts │ │ └── recommendation-item.type.ts │ └── utils │ │ ├── analytics.svelte │ │ ├── analytics.ts │ │ └── save-to-sheet.ts └── routes │ ├── 404 │ └── +page.svelte │ ├── +error.svelte │ ├── +layout.svelte │ ├── +layout.ts │ ├── +page.svelte │ ├── api │ ├── collect-data │ │ └── +server.ts │ └── submit-form │ │ └── +server.ts │ ├── imprint │ └── +page.svelte │ └── privacy │ └── +page.svelte ├── static ├── favicon.png ├── font.css ├── fonts │ ├── Manrope-Bold.woff2 │ └── Manrope-Regular.woff2 ├── images │ └── portraits │ │ ├── abi_noda.png │ │ ├── alexander_podkhalyuzin.jpg │ │ ├── chris_weichel.jpg │ │ ├── cirpo.jpeg │ │ ├── elvis_kahoro.jpeg │ │ ├── geoffrey_teale.jpg │ │ ├── josh_maxwell.jpeg │ │ ├── pauline_narvas.png │ │ ├── phillip_carter.jpeg │ │ └── zohar_einy.jpeg └── media-image.jpg ├── svelte.config.js ├── tailwind.config.cjs ├── tests └── test.ts ├── tsconfig.json └── vite.config.ts /.env.example: -------------------------------------------------------------------------------- 1 | ANALYTICS_WRITE_KEY= 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | *.css 10 | 11 | # Ignore files for PNPM, NPM and YARN 12 | pnpm-lock.yaml 13 | package-lock.json 14 | yarn.lock 15 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript') 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | .netlify 10 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: gitpod/workspace-full-vnc:latest 2 | 3 | ports: 4 | - port: 5173 5 | onOpen: open-preview 6 | visibility: public 7 | name: Website 8 | description: Preview of Website 9 | - port: 5900 10 | onOpen: ignore 11 | name: VNC 12 | description: VNC Server 13 | - port: 6080 14 | onOpen: ignore 15 | name: VNC 16 | description: VNC Viewer 17 | 18 | # List the start up tasks. You can start them in parallel in multiple terminals. See https://www.gitpod.io/docs/config-start-tasks/ 19 | tasks: 20 | - init: npm install 21 | command: npm run dev 22 | name: Dev 23 | 24 | github: 25 | prebuilds: 26 | # enable for the master/default branch (defaults to true) 27 | master: true 28 | # enable for all branches in this repo (defaults to false) 29 | branches: true 30 | # enable for pull requests coming from this repo (defaults to true) 31 | pullRequests: true 32 | # enable for pull requests coming from forks (defaults to false) 33 | pullRequestsFromForks: true 34 | # add a check to pull requests (defaults to true) 35 | addCheck: true 36 | # add a "Review in Gitpod" button as a comment to pull requests (defaults to false) 37 | addComment: false 38 | # add a "Review in Gitpod" button to the pull request's description (defaults to false) 39 | addBadge: true 40 | # add a label once the prebuild is ready to pull requests (defaults to false) 41 | addLabel: false 42 | 43 | vscode: 44 | extensions: 45 | - svelte.svelte-vscode 46 | - bradlc.vscode-tailwindcss 47 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/sh 3 | . "$(dirname "$0")/_/husky.sh" 4 | 5 | npx svelte-check --fail-on-hints 6 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "pluginSearchDirs": ["."], 7 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "netlify dev", 6 | "type": "node", 7 | "request": "launch", 8 | "skipFiles": ["/**"], 9 | "outFiles": ["${workspaceFolder}/.netlify/functions-serve/**/*.js"], 10 | "program": "${workspaceFolder}/node_modules/.bin/netlify", 11 | "args": ["dev"], 12 | "console": "integratedTerminal", 13 | "env": { "BROWSER": "none" }, 14 | "serverReadyAction": { 15 | "pattern": "Server now ready on (https?://[w:.-]+)", 16 | "uriFormat": "%s", 17 | "action": "debugWithChrome" 18 | } 19 | }, 20 | { 21 | "name": "netlify functions:serve", 22 | "type": "node", 23 | "request": "launch", 24 | "skipFiles": ["/**"], 25 | "outFiles": ["${workspaceFolder}/.netlify/functions-serve/**/*.js"], 26 | "program": "${workspaceFolder}/node_modules/.bin/netlify", 27 | "args": ["functions:serve"], 28 | "console": "integratedTerminal" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Gitpod 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DevX Website 2 | 3 | [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/gitpod-io/website) 4 | [![Pull Requests Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://makeapullrequest.com) 5 | 6 | > This repository contains the website hosted on [https://www.developerexperience.us/](https://www.developerexperience.us/). 7 | 8 | With developerexperience.us and our DevX activities, we want to create a shared space for those that work on creating a better developer experience for all of us. 9 | 10 | Contributing is as easy as starting a new workspace: 11 | 12 | [![Open in Gitpod](https://www.gitpod.io/svg/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/gitpod-io/devx-community) 13 | 14 | ## Technology stack 15 | 16 | This website uses the following technologies: 17 | 18 | - [Svelte](https://svelte.dev) 19 | - [SvelteKit](https://kit.svelte.dev) 20 | - [Tailwind CSS](https://tailwindcss.com) 21 | - [Netlify](https://www.netlify.com) 22 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "npm run build" 3 | publish = "build/" 4 | 5 | [functions] 6 | directory = "src/functions" 7 | node_bundler = "esbuild" 8 | 9 | [dev] 10 | command = "npm run dev" 11 | targetPort = 5173 12 | 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "devx-community", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite dev", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "test": "playwright test", 10 | "prepare": "husky install", 11 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 12 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 13 | "lint": "prettier --check . && eslint .", 14 | "format": "prettier --write ." 15 | }, 16 | "devDependencies": { 17 | "@playwright/test": "^1.29.0", 18 | "@sveltejs/adapter-netlify": "^1.0.0", 19 | "@sveltejs/kit": "^1.0.1", 20 | "@types/google-spreadsheet": "^3.3.0", 21 | "@typescript-eslint/eslint-plugin": "^5.46.1", 22 | "@typescript-eslint/parser": "^5.46.1", 23 | "autoprefixer": "^10.4.13", 24 | "eslint": "^8.30.0", 25 | "eslint-config-prettier": "^8.5.0", 26 | "eslint-plugin-svelte3": "^4.0.0", 27 | "husky": "^8.0.2", 28 | "lint-staged": "^13.1.0", 29 | "postcss": "^8.4.20", 30 | "postcss-load-config": "^4.0.1", 31 | "prettier": "^2.8.1", 32 | "prettier-plugin-svelte": "^2.9.0", 33 | "prettier-plugin-tailwindcss": "^0.2.1", 34 | "svelte": "^3.55.0", 35 | "svelte-check": "^2.10.2", 36 | "svelte-preprocess": "^5.0.0", 37 | "tailwindcss": "^3.2.4", 38 | "tslib": "^2.4.1", 39 | "typescript": "^4.9.4", 40 | "vite": "^4.0.2" 41 | }, 42 | "type": "module", 43 | "lint-staged": { 44 | "*.{cjs,js,ts,css,scss,svelte}": [ 45 | "eslint --fix", 46 | "prettier --write" 47 | ] 48 | }, 49 | "dependencies": { 50 | "google-spreadsheet": "^3.3.0", 51 | "nanoid": "^4.0.0", 52 | "node-fetch": "^3.3.0" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /playwright.config.ts: -------------------------------------------------------------------------------- 1 | import type { PlaywrightTestConfig } from '@playwright/test'; 2 | 3 | const config: PlaywrightTestConfig = { 4 | webServer: { 5 | command: 'npm run build && npm run preview', 6 | port: 4173 7 | } 8 | }; 9 | 10 | export default config; 11 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const tailwindcss = require('tailwindcss'); 2 | const autoprefixer = require('autoprefixer'); 3 | 4 | const config = { 5 | plugins: [ 6 | //Some plugins, like tailwindcss/nesting, need to run before Tailwind, 7 | tailwindcss(), 8 | //But others, like autoprefixer, need to run after, 9 | autoprefixer 10 | ] 11 | }; 12 | 13 | module.exports = config; 14 | -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | :root { 7 | --dark-black: #070707; 8 | --black: #161616; 9 | --grey: #5a5353; 10 | --grey-light: #bfbfbf; 11 | --grey-slight: #f5f4f4; 12 | --red: #ff5043; 13 | --brown-light: #cdc0b2; 14 | --brown-dark: #64584a; 15 | --white: #fdfdfd; 16 | --white-light: #fdfbfb; 17 | 18 | --grey-slight-alpha: #f5f4f4cc; 19 | --black-alpha: #161616cc; 20 | 21 | --highlight: var(--red); 22 | 23 | --xx-large: 10rem; 24 | --x-large: 4.5rem; 25 | --large: 4rem; 26 | --medium: 3.5rem; 27 | --small: 3rem; 28 | --x-small: 2rem; 29 | --xx-small: 1.5rem; 30 | 31 | --h1: 5rem; 32 | --h2: 3rem; 33 | --h3: 2rem; 34 | --h4: 1.75rem; 35 | 36 | --p-x-large: 1.5rem; 37 | --p-large: 1.25rem; 38 | --p-medium: 1.125rem; 39 | --p-small: 1rem; 40 | 41 | --shadow-hover-default: 0px 8px 8px 0px rgba(0, 0, 0, 0.1); 42 | 43 | --shadow-default: 0px 1px 1px rgba(0, 0, 0, 0.1); 44 | } 45 | 46 | body.light { 47 | --important: var(--black); 48 | --body: var(--grey); 49 | --sub: var(--brown-light); 50 | --bg: var(--grey-slight); 51 | --box: var(--white); 52 | --nav: var(--grey-slight-alpha); 53 | 54 | --gradient-primary: linear-gradient(224.91deg, var(--red) 32.52%, #cdc0b2 79.06%); 55 | --gradient-stroke: linear-gradient(180deg, #ffffff 0%, #ece7e5 100%); 56 | --gradient-404: linear-gradient(224.91deg, var(--white) 32.52%, var(--brown-light) 79.06%); 57 | } 58 | 59 | body.dark { 60 | --important: var(--white-light); 61 | --body: var(--grey-light); 62 | --sub: var(--brown-dark); 63 | --bg: var(--black); 64 | --box: var(--dark-black); 65 | --nav: var(--black-alpha); 66 | 67 | --gradient-primary: linear-gradient(224.91deg, var(--red) 32.52%, #64584a 79.06%); 68 | --gradient-stroke: linear-gradient(179.95deg, #332d23 0.04%, #0f0e0b 99.8%); 69 | --gradient-404: linear-gradient(224.91deg, var(--dark-black) 32.52%, var(--brown-dark) 79.06%); 70 | } 71 | 72 | *, 73 | *::before, 74 | *::after { 75 | @apply m-0 p-0; 76 | box-sizing: inherit; 77 | -webkit-font-smoothing: antialiased; 78 | -moz-osx-font-smoothing: grayscale; 79 | transition: all 0.5s cubic-bezier(0.25, 1, 0.5, 1); 80 | } 81 | 82 | html { 83 | @apply box-border scroll-p-xx-small overflow-x-hidden; 84 | } 85 | 86 | body { 87 | @apply bg-bg text-base text-body md:text-main; 88 | text-rendering: optimizeLegibility; 89 | } 90 | 91 | main { 92 | @apply text-base text-body md:text-main; 93 | } 94 | 95 | h1, 96 | .h1, 97 | h2, 98 | .h2, 99 | h3, 100 | .h3, 101 | h4, 102 | .h4, 103 | h5, 104 | .h5, 105 | h6, 106 | .h6 { 107 | @apply font-bold text-important; 108 | } 109 | 110 | p + p { 111 | @apply mt-xx-small md:mt-x-small; 112 | } 113 | 114 | a { 115 | @apply underline transition-all delay-50 duration-200 hover:decoration-transparent; 116 | } 117 | 118 | [type='checkbox'] { 119 | @apply sr-only; 120 | } 121 | 122 | [type='checkbox'] + label::before { 123 | content: ''; 124 | @apply h-5 w-5 rounded-sm border border-solid border-body; 125 | } 126 | 127 | [type='checkbox'] + label::after { 128 | content: '\2713'; 129 | @apply absolute ml-1 -mt-0.5 font-serif text-base opacity-0 transition-all duration-200; 130 | color: var(--red); 131 | } 132 | 133 | [type='checkbox']:checked + label::after { 134 | @apply text-white opacity-100; 135 | } 136 | 137 | [type='checkbox']:checked + label::before { 138 | background: var(--red); 139 | border-color: var(--red); 140 | } 141 | } 142 | 143 | @layer components { 144 | .h2 { 145 | @apply text-h3 leading-[2.5rem] md:text-h2 md:leading-[3.375rem]; 146 | } 147 | 148 | .h3 { 149 | @apply text-p-x-large leading-[2rem] tracking-[0.15em] md:text-h3 md:leading-[2.391rem]; 150 | } 151 | 152 | .h4 { 153 | @apply text-p-large leading-[1.5rem] md:text-h4 md:leading-[2rem]; 154 | } 155 | 156 | .h5 { 157 | @apply text-p-medium tracking-[0.15em]; 158 | } 159 | 160 | .h6 { 161 | @apply mb-2 text-p-small leading-[20.8px]; 162 | } 163 | 164 | .text-large { 165 | @apply text-p-x-large leading-[33.6px]; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | declare namespace App { 5 | // interface Locals {} 6 | // interface PageData {} 7 | // interface Platform {} 8 | } 9 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | %sveltekit.head% 9 | 10 | 11 | 35 |
%sveltekit.body%
36 | 37 | 38 | -------------------------------------------------------------------------------- /src/lib/components/index/community-recommendations.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 |
15 | 16 | 17 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /src/lib/components/index/developer-experience.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 |
11 |

Community Manifesto

12 |

13 | Developer experience - our daily experience when trying to get the job done. All of that 14 | should be efficient, sustainable and joyful. 15 |

16 |

Happy developers build better software!

17 |

18 | The myriad of tools that are released each single day initially sounded like the promised 19 | developer-land. While choice is great, it doesn't necessarily make our lives easier. How does 20 | that feel? 21 |

22 |
23 | 24 | 25 |
26 |
27 | {#each Array(4) as _} 28 | 29 | {/each} 30 |
31 | 35 |

The Developer Experience Gap” by Stephen O'Grady, Redmonk

36 |
37 |
38 |
39 |
40 |

There is light at the end of the tunnel.

41 |

42 | Individual developers, teams and projects start to think deeply about design, style and taste 43 | for tools to help us get into a flow focused on what we all love most: being creative and 44 | writing elegant code. 45 |

46 |

47 | What all of them have in common is the desire to delight, the desire to reduce friction, and 48 | the desire to leverage automation to create a Swiss clockwork that works reliably below the 49 | surface. 50 |

51 |

This community is for them.

52 |
53 |
54 | -------------------------------------------------------------------------------- /src/lib/components/index/founding-members.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |
9 |

DevX Community was built by a community of industry experts

10 |
14 | {#each foundingMembers as item} 15 | 16 | {/each} 17 |
18 |
19 |
20 | -------------------------------------------------------------------------------- /src/lib/components/index/fragments/devx-blog.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

11 | DevX Blog is a community-driven platform for articles and interviews on developer experience. We 12 | highlight and create content to help those working in developer experience get even better at 13 | their job. 14 |

15 |
16 |

Highlighted Posts

17 |
21 | {#each devXBlog as item} 22 | 26 | {/each} 27 |
28 |
29 | 30 | 31 | 32 |
33 | -------------------------------------------------------------------------------- /src/lib/components/index/fragments/devx-conf.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 |

10 | DevX Conf is a virtual conference 11 | on developer experience that happens every year. DevX practitioners at leading companies discuss 12 | their best tools, processes, and latest learnings. 13 |

14 |
15 |

Highlighted Talks

16 |
20 | {#each devXConf as item} 21 | 22 | {/each} 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /src/lib/components/index/fragments/devx-pod.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

11 | DevX Pod features in-depth interviews with DevX experts. Hosts Pauline Narvas and Chris Weichel 12 | speak with developer experience leaders to unpack the ins-and-outs of the field. 13 |

14 |
15 |

Highlighted Episodes

16 |
20 | {#each devXPod as item} 21 | 25 | {/each} 26 |
27 |
28 | 29 | 30 | 31 |
32 | -------------------------------------------------------------------------------- /src/lib/components/index/fragments/how-to-join-item.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |

{title}

7 | 8 |
9 | -------------------------------------------------------------------------------- /src/lib/components/index/fragments/how-to-join.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |

How to join?

7 |
To join our DevX community, you must fulfil these requirements.
8 | You are in a Head of Developer Experience, Head of Platform, Senior DevX Engineer or similar 10 | role that is fully dedicated to developer experience. 12 | You align with our community manifesto and are eager to share your knowledge and learnings to 14 | make the developer experience space better for all. 16 |
17 | -------------------------------------------------------------------------------- /src/lib/components/index/fragments/join-now.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 |
19 | 20 | Join the community 21 | 22 |
26 |
27 | -------------------------------------------------------------------------------- /src/lib/components/index/hero.svelte: -------------------------------------------------------------------------------- 1 | 33 | 34 |
35 |
36 | 37 | 38 | 39 | 40 |
41 |

42 | A dedicated space
for developer experience 43 |

44 | 45 |
46 | 47 | 73 | -------------------------------------------------------------------------------- /src/lib/components/index/learn-more.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
21 |
22 |
23 |
    24 | {#each iconLinks as link} 25 |
  • 26 | 27 |
  • 28 | {/each} 29 |
30 |
31 | 32 |
33 | 34 |
35 |
36 | 37 |
38 | 39 | 40 |
41 |

Exchange ideas and knowledge with DevX leaders

42 | Join the community 45 |
46 | 47 | 48 |
49 |
50 | -------------------------------------------------------------------------------- /src/lib/components/index/sign-up.svelte: -------------------------------------------------------------------------------- 1 | 45 | 46 | 47 | {#if isSignupSuccessful} 48 |
49 | 50 |

Thanks for signing up for the DevX digest.

51 |

You'll shortly get a confirmation email.

52 |
53 | {:else} 54 |
55 |

Sign up for DevX Digest

56 |

57 | Sign up to stay updated on the latest DevX discoveries and news. 58 |

59 |
60 | 69 | 70 | {#if isFormDirty && !email}Please input your email address{/if} 73 |
74 |
75 |
76 | 82 | 87 | {#if isFormDirty && !consent}Please consent to sign up{/if} 90 |
91 |

92 | By submitting this form I acknowledge that I have read and understood the Privacy Policy 95 |

96 |
97 | Sign up 98 |
99 |
100 |
101 | {/if} 102 |
103 | -------------------------------------------------------------------------------- /src/lib/components/index/what-is-this-community.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
14 |
15 | 16 |
17 | 18 |
19 | Join the community 22 |
23 |
24 | -------------------------------------------------------------------------------- /src/lib/components/layout/container.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/lib/components/layout/footer-dots.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |
9 | {#each Array(4) as _} 10 | 11 | {/each} 12 |
13 |
14 | -------------------------------------------------------------------------------- /src/lib/components/layout/footer.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |
11 |
12 | 13 |
14 |

DevX - a space dedicated to developer experience.

15 |

16 | An initative organised by Gitpod. 17 |
18 | gitpod.io 19 |

20 | 21 |
22 |
27 |
28 | 42 |
43 |
44 |
45 | -------------------------------------------------------------------------------- /src/lib/components/layout/mobile-nav/index.svelte: -------------------------------------------------------------------------------- 1 | 31 | 32 | {#if $showMobileMenu} 33 |
36 |
    37 | {#each navItems as item} 38 |
  • 39 | {item.title} 44 |
  • 45 | {/each} 46 |
47 | 48 |
49 | {/if} 50 | -------------------------------------------------------------------------------- /src/lib/components/layout/mobile-nav/toggle.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 39 | -------------------------------------------------------------------------------- /src/lib/components/layout/nav.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 40 | 41 | 47 | -------------------------------------------------------------------------------- /src/lib/components/layout/theme-switcher.svelte: -------------------------------------------------------------------------------- 1 | 41 | 42 |
43 | 46 | 49 | 52 |
53 | 54 | 73 | -------------------------------------------------------------------------------- /src/lib/components/library/animated-line.svelte: -------------------------------------------------------------------------------- 1 | 30 | 31 |
32 | 33 | 44 | -------------------------------------------------------------------------------- /src/lib/components/library/animated-text.svelte: -------------------------------------------------------------------------------- 1 | 44 | 45 |

46 | {@html mutateText(text)} 47 |

48 | 49 | 58 | -------------------------------------------------------------------------------- /src/lib/components/library/annotation.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | [{label}] 6 | -------------------------------------------------------------------------------- /src/lib/components/library/big-dot.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /src/lib/components/library/content-section.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 |
13 |

{title}

14 | 15 |
16 | 17 |
18 |
19 | 20 | 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/library/dot.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /src/lib/components/library/full-bleed.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 | 8 |
9 | 10 | 20 | -------------------------------------------------------------------------------- /src/lib/components/library/gradient-card-no-hover.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 19 | 20 | 21 | 22 | 30 | -------------------------------------------------------------------------------- /src/lib/components/library/gradient-card.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 19 | 20 | 21 | 22 | 40 | -------------------------------------------------------------------------------- /src/lib/components/library/gradient-content-card.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 |
12 |
13 |
{data.text}
14 | {#if data.subtext} 15 | {data.subtext} 16 | {/if} 17 |
18 |
19 | {data.label} 20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /src/lib/components/library/gradient-link-button.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 20 | 21 | 22 | 23 | 44 | -------------------------------------------------------------------------------- /src/lib/components/library/icon-link.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | {text} 13 | 14 | -------------------------------------------------------------------------------- /src/lib/components/library/intersection-observer.svelte: -------------------------------------------------------------------------------- 1 | 58 | 59 |
60 | 61 |
62 | 63 | 69 | -------------------------------------------------------------------------------- /src/lib/components/library/link-button.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/lib/components/library/open-graph.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | {title} 20 | 21 | 22 | 23 | {#if norobots} 24 | 25 | {/if} 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 39 | 40 | -------------------------------------------------------------------------------- /src/lib/components/library/portrait-card.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
13 |
14 |
15 | photo of {portrait.name} 22 | 23 |
24 |
{portrait.name}
25 |
{portrait.role}
26 |
{portrait.company}
27 |
28 | {#if portrait.githubLink} 29 | {/if} 31 | {#if portrait.twitterLink}{/if} 34 | {#if portrait.linkedinLink}{/if} 37 |
38 |
39 |
40 | -------------------------------------------------------------------------------- /src/lib/components/library/recommendation-item-section.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 |

{title}

10 |
    11 | {#each recommendationItems as item} 12 |
  • 13 | {item.text} by {item.by} 14 |
  • 15 | {/each} 16 |
17 |
18 | -------------------------------------------------------------------------------- /src/lib/components/library/reveal.svelte: -------------------------------------------------------------------------------- 1 | 29 | 30 |
31 | 32 |
33 | 34 | 44 | -------------------------------------------------------------------------------- /src/lib/components/library/section.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 |
18 | 19 |

{title}

20 | {#if text}

{@html text}

{/if} 21 | 22 |
23 | {#if line} 24 | 25 | {/if} 26 |
27 | -------------------------------------------------------------------------------- /src/lib/components/library/vertical-stroke.svelte: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /src/lib/components/svgs/devx.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | DevX 8 | 9 | -------------------------------------------------------------------------------- /src/lib/components/svgs/github.svelte: -------------------------------------------------------------------------------- 1 | 9 | 16 | 17 | -------------------------------------------------------------------------------- /src/lib/components/svgs/gitpod.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 11 | 15 | 19 | 25 | 31 | 37 | 41 | 47 | 48 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/lib/components/svgs/linkedin.svelte: -------------------------------------------------------------------------------- 1 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /src/lib/components/svgs/listen.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /src/lib/components/svgs/read.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /src/lib/components/svgs/switcher/moon.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /src/lib/components/svgs/switcher/sun.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /src/lib/components/svgs/twitter.svelte: -------------------------------------------------------------------------------- 1 | 9 | 16 | 17 | -------------------------------------------------------------------------------- /src/lib/components/svgs/watch.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /src/lib/contents/index.ts: -------------------------------------------------------------------------------- 1 | export const learnMoreItems: { title: string; text: string }[] = [ 2 | { 3 | title: 'DevX Pod', 4 | text: 'DevX Conf is a space for creators where we can start from first principles, collaborate, listen, discuss and declutter our workflows, toolchains and minds. To improve developer experience. To make us feel again like everything is at our fingertips. We want to foster an ecosystem that sparks dialogue and establishes best practices and frameworks across the areas of coding, testing, building, deploying, collaborating on and running software.' 5 | }, 6 | { 7 | title: 'DevX Pod', 8 | text: 'DevX Conf is a space for creators where we can start from first principles, collaborate, listen, discuss and declutter our workflows, toolchains and minds. To improve developer experience. To make us feel again like everything is at our fingertips. We want to foster an ecosystem that sparks dialogue and establishes best practices and frameworks across the areas of coding, testing, building, deploying, collaborating on and running software.' 9 | }, 10 | { 11 | title: 'DevX Pod', 12 | text: 'DevX Conf is a space for creators where we can start from first principles, collaborate, listen, discuss and declutter our workflows, toolchains and minds. To improve developer experience. To make us feel again like everything is at our fingertips. We want to foster an ecosystem that sparks dialogue and establishes best practices and frameworks across the areas of coding, testing, building, deploying, collaborating on and running software.' 13 | } 14 | ]; 15 | -------------------------------------------------------------------------------- /src/lib/contents/index/devx-content.ts: -------------------------------------------------------------------------------- 1 | import type { GradientContentCard } from '$lib/types/gradient-content-card.type'; 2 | 3 | export const devXConf: GradientContentCard[] = [ 4 | { 5 | label: 'Watch now', 6 | text: 'How Spotify engineers use Backstage', 7 | href: 'https://www.youtube.com/watch?v=YswvyxUQvPw', 8 | subtext: '- Himanshu Mishra (Spotify)' 9 | }, 10 | { 11 | label: 'Watch now', 12 | text: 'Remote development can improve your developers remote work experience', 13 | href: 'https://www.youtube.com/watch?v=FLxeKNLjfKU', 14 | subtext: '- Maya Kaczorowski (Tailscale)' 15 | }, 16 | { 17 | label: 'Watch now', 18 | text: 'The Next Generation of Developer-First Products', 19 | href: 'https://www.youtube.com/watch?v=ja-Pr58FCIQ', 20 | subtext: '- Zeno Rocha (WorkOS)' 21 | }, 22 | { 23 | label: 'Watch now', 24 | text: 'Designing for developers', 25 | href: 'https://www.youtube.com/watch?v=-oSb5GUyUFo', 26 | subtext: '- Boris Kirov (Elastic)' 27 | } 28 | ]; 29 | 30 | export const devXBlog: GradientContentCard[] = [ 31 | { 32 | label: 'Read now', 33 | text: 'The Psychology of DevX', 34 | href: 'https://www.gitpod.io/blog/psychology-of-devx' 35 | }, 36 | { 37 | label: 'Read now', 38 | text: 'The evolution of DevX', 39 | href: 'https://www.gitpod.io/blog/the-evolution-of-devx' 40 | }, 41 | { 42 | label: 'Read now', 43 | text: 'The radiating circles of DevX', 44 | href: 'https://www.gitpod.io/blog/the-radiating-circle-of-devx' 45 | }, 46 | { 47 | label: 'Read now', 48 | text: 'Building a developer experience team', 49 | href: 'https://www.gitpod.io/blog/building-devx-teams' 50 | }, 51 | { 52 | label: 'Read now', 53 | text: 'How DevX affects us all', 54 | href: 'https://www.gitpod.io/blog/devx-affects-us-all' 55 | }, 56 | { 57 | label: 'Read now', 58 | text: 'The rise of ephemeral dev environments', 59 | href: 'https://www.gitpod.io/blog/ephemeral-dev-envs' 60 | } 61 | ]; 62 | 63 | export const devXPod: GradientContentCard[] = [ 64 | { 65 | label: 'Listen now', 66 | text: 'Building DevX teams with Cirpo and Lou', 67 | href: 'https://devxpod.buzzsprout.com/1895030/9637256-building-a-developer-experience-team-w-cirpo-dazn-eng-lou-gitpod' 68 | }, 69 | { 70 | label: 'Listen now', 71 | text: 'Measuring and improving DevX productivity with Abi Noda', 72 | href: 'https://devxpod.buzzsprout.com/1895030/11142190-measuring-and-improving-developer-productivity-w-abi-noda-from-getdx' 73 | }, 74 | { 75 | label: 'Listen now', 76 | text: 'Growing DevX from 10 to 100 with Anton Drukh', 77 | href: 'https://devxpod.buzzsprout.com/1895030/10419920-growing-developer-experience-from-10-to-100-developers-with-anton-drukh' 78 | } 79 | ]; 80 | -------------------------------------------------------------------------------- /src/lib/contents/index/founding-members.ts: -------------------------------------------------------------------------------- 1 | import type { Portrait } from '$lib/types/portrait.type'; 2 | 3 | export const foundingMembers: Portrait[] = [ 4 | { 5 | imgsrc: '/images/portraits/cirpo.jpeg', 6 | name: 'Cirpo', 7 | company: '@Spotify', 8 | role: 'Engineering Manager - Core Infra', 9 | linkedinLink: 'https://www.linkedin.com/in/cirpo/', 10 | twitterLink: 'https://twitter.com/cirpo' 11 | }, 12 | 13 | { 14 | imgsrc: 'images/portraits/abi_noda.png', 15 | name: 'Abi Noda', 16 | company: '@DX', 17 | role: 'CEO', 18 | linkedinLink: 'https://www.linkedin.com/in/abinoda/', 19 | twitterLink: 'https://twitter.com/abinoda' 20 | }, 21 | { 22 | imgsrc: '/images/portraits/pauline_narvas.png', 23 | name: 'Pauline Narvas', 24 | company: '@Gitpod', 25 | role: 'Head of Community', 26 | linkedinLink: 'https://www.linkedin.com/in/pnarvas/', 27 | twitterLink: 'https://twitter.com/paulienuh' 28 | }, 29 | { 30 | imgsrc: '/images/portraits/josh_maxwell.jpeg', 31 | name: 'Josh Maxwell', 32 | company: '@Qualtrics', 33 | linkedinLink: 'https://www.linkedin.com/in/cctechwiz/', 34 | role: 'Software Engineer', 35 | twitterLink: 'https://twitter.com/cctechwiz' 36 | }, 37 | { 38 | imgsrc: '/images/portraits/phillip_carter.jpeg', 39 | name: 'Phillip Carter', 40 | company: '@Honeycomb', 41 | role: 'Product & DX', 42 | linkedinLink: 'https://www.linkedin.com/in/phillip-carter-4714a135/', 43 | twitterLink: 'https://twitter.com/_cartermp' 44 | }, 45 | { 46 | imgsrc: '/images/portraits/chris_weichel.jpg', 47 | name: 'Christian Weichel', 48 | role: 'CTO', 49 | company: '@Gitpod', 50 | linkedinLink: 'https://www.linkedin.com/in/christian-weichel-740b4224/', 51 | twitterLink: 'https://twitter.com/csweichel' 52 | }, 53 | { 54 | imgsrc: '/images/portraits/geoffrey_teale.jpg', 55 | name: 'Geoffrey Teale', 56 | company: '@Upvest', 57 | role: 'Head of Developer Experience', 58 | linkedinLink: 'https://www.linkedin.com/in/geoffteale/', 59 | twitterLink: 'https://twitter.com/tealeg' 60 | }, 61 | { 62 | imgsrc: '/images/portraits/alexander_podkhalyuzin.jpg', 63 | name: 'Alexander Podkhalyuzin', 64 | role: 'Customer Success Engineer', 65 | company: '@Jetbrains' 66 | }, 67 | { 68 | imgsrc: '/images/portraits/zohar_einy.jpeg', 69 | name: 'Zohar Einy', 70 | role: 'CEO', 71 | company: '@Port', 72 | linkedinLink: 'https://www.linkedin.com/in/zohar-einy-b6219612a/', 73 | twitterLink: 'https://twitter.com/ZoharEiny' 74 | }, 75 | { 76 | imgsrc: '/images/portraits/elvis_kahoro.jpeg', 77 | name: 'Elvis Kahoro', 78 | company: '@Warp', 79 | role: 'DevX Engineer', 80 | linkedinLink: 'https://www.linkedin.com/in/elviskahoro/' 81 | } 82 | ]; 83 | -------------------------------------------------------------------------------- /src/lib/contents/index/learn-more.ts: -------------------------------------------------------------------------------- 1 | import type { IconLink } from '$lib/types/icon-link'; 2 | import Listen__SvelteComponent_ from '../../components/svgs/listen.svelte'; 3 | import Watch__SvelteComponent_ from '../../components/svgs/watch.svelte'; 4 | import Read__SvelteComponent_ from '../../components/svgs/read.svelte'; 5 | 6 | export const iconLinks: IconLink[] = [ 7 | { 8 | iconClasses: 'h-[18px] w-[18px]', 9 | icon: Read__SvelteComponent_, 10 | href: '#devx-blog', 11 | text: 'DevX Blog' 12 | }, 13 | { 14 | iconClasses: 'h-[14px] w-[20px]', 15 | icon: Watch__SvelteComponent_, 16 | href: '#devx-conf', 17 | text: 'DevX Conf' 18 | }, 19 | { 20 | iconClasses: 'h-[20px] w-[18px]', 21 | icon: Listen__SvelteComponent_, 22 | href: '#devx-pod', 23 | text: 'DevX Pod' 24 | } 25 | ]; 26 | -------------------------------------------------------------------------------- /src/lib/contents/index/recommendations.ts: -------------------------------------------------------------------------------- 1 | import type { RecommendationItem } from '$lib/types/recommendation-item.type'; 2 | 3 | export const blogRecommendations: RecommendationItem[] = [ 4 | { 5 | href: 'https://kenneth.io/post/developer-experience-infrastructure-dxi', 6 | by: 'Kenneth Auchenberg', 7 | text: 'Developer Experience Infrastructure (DXI)' 8 | }, 9 | { 10 | href: 'https://medium.com/dazn-tech/developer-experience-dx-at-dazn-e6de9a0208d2', 11 | by: 'Cirpo', 12 | text: 'Developer Experience (DX) at DAZN' 13 | }, 14 | { 15 | href: 'https://www.akitasoftware.com/blog', 16 | by: 'Akita (Jean Yang)', 17 | text: 'Akita Engineering Blog' 18 | }, 19 | { 20 | href: 'https://teale.de/', 21 | by: 'Geoffrey J. Teale', 22 | text: 'Teale Blog' 23 | } 24 | ]; 25 | 26 | export const knowledgeBases: RecommendationItem[] = [ 27 | { 28 | text: 'DX Tips: The DevTools Magazine', 29 | by: 'swyx', 30 | href: 'https://dx.tips/' 31 | }, 32 | { 33 | text: 'Developer Experience', 34 | by: 'Prokop Simek', 35 | href: 'https://developerexperience.io/' 36 | } 37 | ]; 38 | 39 | export const podcasts: RecommendationItem[] = [ 40 | { 41 | text: 'The Sourcegraph Podcast', 42 | by: 'Beyang & Quinn', 43 | href: 'https://podcasts.apple.com/us/podcast/the-sourcegraph-podcast/id1516219009' 44 | }, 45 | { 46 | text: 'Scaling DevTools', 47 | by: 'Jack Bridger', 48 | href: 'https://podcasts.apple.com/us/podcast/scaling-devtools/id1620866569' 49 | }, 50 | { 51 | text: 'Developer Experience', 52 | by: 'Algolia', 53 | href: 'https://podcasts.apple.com/us/podcast/developer-experience/id1573728860' 54 | }, 55 | { 56 | text: 'NerdOut@Spotify', 57 | by: 'Spotify R&D', 58 | href: 'https://podcasts.apple.com/us/podcast/nerdout-spotify/id1610028432' 59 | }, 60 | { 61 | text: 'DevOps Deployed', 62 | by: 'DevOps Directive', 63 | href: 'https://www.youtube.com/playlist?list=PLFzuOAehUPHFMFSe7OeKLecTcbjydSUHa' 64 | } 65 | ]; 66 | -------------------------------------------------------------------------------- /src/lib/contents/nav.ts: -------------------------------------------------------------------------------- 1 | export const navItems = [ 2 | { 3 | href: '/#devx', 4 | title: 'DevX' 5 | }, 6 | { 7 | href: '/#community', 8 | title: 'Community' 9 | }, 10 | { 11 | href: '/#resources', 12 | title: 'Resources' 13 | } 14 | ]; 15 | -------------------------------------------------------------------------------- /src/lib/helper.ts: -------------------------------------------------------------------------------- 1 | export const showHideOverflowY = (bool: boolean) => { 2 | const html = document.querySelector('html'); 3 | if (bool) { 4 | html!.classList.add('overflow-y-hidden'); 5 | } else { 6 | html!.classList.remove('overflow-y-hidden'); 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /src/lib/stores/mobile-menu.ts: -------------------------------------------------------------------------------- 1 | import { writable } from 'svelte/store'; 2 | 3 | export default writable(false); 4 | -------------------------------------------------------------------------------- /src/lib/types/analytics.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable @typescript-eslint/no-explicit-any 2 | export interface AnalyticsPayload { 3 | type: 'event' | 'identity' | 'page'; 4 | userID?: string; 5 | props?: any; 6 | traits?: any; 7 | context?: any; 8 | eventName?: string; 9 | } 10 | 11 | export interface PageProps { 12 | url: string; 13 | path: string; 14 | referrer?: string; 15 | title?: string; 16 | search?: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/lib/types/gradient-content-card.type.ts: -------------------------------------------------------------------------------- 1 | export type GradientContentCard = { 2 | text: string; 3 | href: string; 4 | subtext?: string; 5 | label: string; 6 | }; 7 | -------------------------------------------------------------------------------- /src/lib/types/icon-link.ts: -------------------------------------------------------------------------------- 1 | export type IconLink = { 2 | icon: any; 3 | iconClasses?: string; 4 | href: string; 5 | text: string; 6 | }; 7 | -------------------------------------------------------------------------------- /src/lib/types/open-graph.type.ts: -------------------------------------------------------------------------------- 1 | export type OpenGraph = { 2 | description: string; 3 | title: string; 4 | image?: string; 5 | imageTwitter?: string; 6 | norobots?: boolean; 7 | keywords?: string; 8 | }; 9 | -------------------------------------------------------------------------------- /src/lib/types/portrait.type.ts: -------------------------------------------------------------------------------- 1 | export type Portrait = { 2 | imgsrc: string; 3 | name: string; 4 | company: string; 5 | role: string; 6 | githubLink?: string; 7 | twitterLink?: string; 8 | linkedinLink?: string; 9 | }; 10 | -------------------------------------------------------------------------------- /src/lib/types/recommendation-item.type.ts: -------------------------------------------------------------------------------- 1 | export type RecommendationItem = { 2 | href: string; 3 | by: string; 4 | text: string; 5 | }; 6 | -------------------------------------------------------------------------------- /src/lib/utils/analytics.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 103 | -------------------------------------------------------------------------------- /src/lib/utils/analytics.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable @typescript-eslint/no-explicit-any 2 | 3 | import type { AnalyticsPayload, PageProps } from '../types/analytics'; 4 | import crypto from 'node:crypto'; 5 | 6 | declare global { 7 | interface Window { 8 | prevPages?: string[]; 9 | } 10 | } 11 | 12 | export const generateHash = async (value: string) => { 13 | const hash = crypto.createHash('sha512').update(value).digest('hex'); 14 | return hash; 15 | }; 16 | 17 | const getPageProps = (): PageProps => { 18 | return { 19 | path: window.location.pathname, 20 | url: window.location.href, 21 | search: window.location.search, 22 | title: document.title, 23 | referrer: window.prevPages ? window.prevPages[window.prevPages.length - 1] : undefined 24 | }; 25 | }; 26 | 27 | export const trackEvent = async (eventName: string, props: any) => { 28 | const pageProps = getPageProps(); 29 | 30 | const body: AnalyticsPayload = { 31 | type: 'event', 32 | eventName, 33 | props: props, 34 | context: { page: pageProps } 35 | }; 36 | 37 | await fetch('/api/collect-data', { 38 | method: 'POST', 39 | body: JSON.stringify(body) 40 | }); 41 | }; 42 | 43 | export const trackIdentity = async (traits: any) => { 44 | const body: AnalyticsPayload = { 45 | type: 'identity', 46 | traits: traits, 47 | context: { page: getPageProps() } 48 | }; 49 | 50 | await fetch('/api/collect-data', { 51 | method: 'POST', 52 | body: JSON.stringify(body) 53 | }); 54 | }; 55 | 56 | export const trackPage = async () => { 57 | const pageProps = getPageProps(); 58 | const body: AnalyticsPayload = { 59 | type: 'page', 60 | props: pageProps, 61 | context: { page: pageProps } 62 | }; 63 | 64 | await fetch('/api/collect-data', { 65 | method: 'POST', 66 | body: JSON.stringify(body) 67 | }); 68 | }; 69 | -------------------------------------------------------------------------------- /src/lib/utils/save-to-sheet.ts: -------------------------------------------------------------------------------- 1 | import gs from 'google-spreadsheet'; 2 | import { env } from '$env/dynamic/private'; 3 | 4 | export default async (sheetInfo: { title: string; data: any }): Promise => { 5 | try { 6 | const doc = new gs.GoogleSpreadsheet(process.env.FEEDBACK_SHEET_ID); 7 | await doc.useServiceAccountAuth({ 8 | client_email: env.FEEDBACK_GOOGLE_SERVICE_ACCOUNT_EMAIL as string, 9 | private_key: Buffer.from(env.FEEDBACK_GOOGLE_PRIVATE_KEY_BASE64 as string, 'base64').toString( 10 | 'utf8' 11 | ) 12 | }); 13 | await doc.loadInfo(); 14 | const sheet = doc.sheetsByTitle[sheetInfo.title]; 15 | const sheetInfoData = sheetInfo.data[0]; 16 | 17 | const rows = await sheet.getRows(); 18 | const existingEmails: string[] = []; 19 | rows.map((row) => { 20 | const data = row._rawData[0]; 21 | existingEmails.push(data); 22 | }); 23 | if (existingEmails.includes(sheetInfoData)) { 24 | return 'duplicate'; 25 | } 26 | await sheet.addRow([sheetInfo.data]); 27 | return true; 28 | } catch (error) { 29 | console.error(error); 30 | return false; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /src/routes/+error.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | {#if $page.status === 404} 7 |
8 |
11 |

404

12 |
13 |

You just hit a route that doesn't exist

14 | Back to safety 15 |
16 | {/if} 17 | -------------------------------------------------------------------------------- /src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 | 11 |
17 | -------------------------------------------------------------------------------- /src/routes/+layout.ts: -------------------------------------------------------------------------------- 1 | export const prerender = true; 2 | -------------------------------------------------------------------------------- /src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/routes/404/+page.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
9 |

404

10 |
11 |

You just hit a route that doesn't exist

12 | Back to safety 13 |
14 | -------------------------------------------------------------------------------- /src/routes/api/collect-data/+server.ts: -------------------------------------------------------------------------------- 1 | /* eslint no-empty: ["error", { "allowEmptyCatch": true }] */ 2 | import { json, type RequestHandler } from '@sveltejs/kit'; 3 | import fetch from 'node-fetch'; 4 | import { env } from '$env/dynamic/private'; 5 | import { generateHash } from '$lib/utils/analytics'; 6 | import type { AnalyticsPayload, PageProps } from '$lib/types/analytics'; 7 | 8 | const writeKey = env.ANALYTICS_WRITE_KEY || ''; 9 | 10 | export const POST: RequestHandler = async ({ request }) => { 11 | const body = (await request.json()) as AnalyticsPayload; 12 | const ip = request.headers.get('x-forwarded-for')?.split(',')[0]; 13 | if (!ip) { 14 | return json({ message: 'no x-forwarded-for header provided' }, { status: 400 }); 15 | } 16 | const agent = request.headers.get('user-agent') || ''; 17 | 18 | const date = new Date(); 19 | const today = `${date.getDate()}/${date.getMonth()}/${date.getFullYear()}`; 20 | 21 | const toHashString = ip + agent + today; 22 | 23 | const hash = await generateHash(toHashString); 24 | 25 | const maskIp = (ip: string) => { 26 | const octets = ip.split('.'); 27 | return octets?.length == 4 ? octets.slice(0, 3).concat(['0']).join('.') : undefined; 28 | }; 29 | 30 | const getServerContext = () => { 31 | return { 32 | userAgent: agent, 33 | ip: maskIp(ip) 34 | }; 35 | }; 36 | 37 | if (!writeKey) { 38 | return json({ message: 'no token in environment' }, { status: 200 }); 39 | } 40 | try { 41 | const basicAuthHeader = `${writeKey}:`; 42 | const authHeader = Buffer.from(basicAuthHeader).toString('base64'); 43 | switch (body.type) { 44 | case 'event': 45 | if (!body.eventName) return json({ message: 'Please provide eventName' }, { status: 400 }); 46 | await fetch('https://api.segment.io/v1/track', { 47 | method: 'POST', 48 | headers: { 'Content-Type': 'application/json', Authorization: `Basic ${authHeader}` }, 49 | body: JSON.stringify({ 50 | anonymousId: hash, 51 | event: body.eventName, 52 | properties: body.props, 53 | context: { 54 | ...body.context, 55 | ...getServerContext() 56 | }, 57 | sentAt: new Date().toISOString() 58 | }) 59 | }); 60 | 61 | break; 62 | case 'identity': 63 | if (!body.traits) return json({ message: 'Please provide traits' }, { status: 400 }); 64 | await fetch('https://api.segment.io/v1/identify', { 65 | method: 'POST', 66 | headers: { 'Content-Type': 'application/json', Authorization: `Basic ${authHeader}` }, 67 | body: JSON.stringify({ 68 | anonymousId: hash, 69 | traits: body.traits, 70 | context: { 71 | ...body.context, 72 | ...getServerContext() 73 | }, 74 | sentAt: new Date().toISOString() 75 | }) 76 | }); 77 | 78 | break; 79 | case 'page': 80 | if (!body.props.url || !body.props.path) 81 | return json({ message: 'Please include url and path in props' }, { status: 400 }); 82 | await fetch('https://api.segment.io/v1/page', { 83 | method: 'POST', 84 | headers: { 'Content-Type': 'application/json', Authorization: `Basic ${authHeader}` }, 85 | body: JSON.stringify({ 86 | anonymousId: hash, 87 | properties: body.props as PageProps, 88 | context: { 89 | ...body.context, 90 | ...getServerContext() 91 | }, 92 | sentAt: new Date().toISOString() 93 | }) 94 | }); 95 | break; 96 | default: 97 | return json({ message: 'please provide valid type' }, { status: 400 }); 98 | } 99 | 100 | return json({ message: 'success' }, { status: 200 }); 101 | } catch (e) { 102 | console.log(e); 103 | return json({ message: `failed` }, { status: 500 }); 104 | } 105 | }; 106 | -------------------------------------------------------------------------------- /src/routes/api/submit-form/+server.ts: -------------------------------------------------------------------------------- 1 | import save from '$lib/utils/save-to-sheet'; 2 | import { json } from '@sveltejs/kit'; 3 | 4 | async function saveToSheet(data: any) { 5 | const isSaved = await save({ 6 | title: 'DevX Community - Signups', 7 | data 8 | }); 9 | 10 | if (isSaved === 'duplicate') { 11 | return { 12 | statusCode: 409, 13 | body: 'duplicate' 14 | }; 15 | } else { 16 | return { 17 | statusCode: isSaved ? 200 : 500, 18 | body: JSON.stringify(data) + ' added' 19 | }; 20 | } 21 | } 22 | 23 | export const POST = async ({ request }: any) => { 24 | console.log(request); 25 | const body = await request.json(); 26 | const email = body; 27 | 28 | try { 29 | const saveResponse = await saveToSheet(email); 30 | 31 | return json(saveResponse.body, { 32 | status: saveResponse.statusCode 33 | }); 34 | } catch (err) { 35 | console.error(err); 36 | return json(err, { 37 | status: 400 38 | }); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /src/routes/imprint/+page.svelte: -------------------------------------------------------------------------------- 1 |
2 |

Imprint

3 |

4 |

Gitpod GmbH
5 |
Managing Directors: Sven Efftinge, Moritz Eysholdt
6 |
Am Germaniahafen 1
7 |
24143 Kiel
8 |
Germany
9 |
10 |
HRB 22228, Amtsgericht Kiel
11 |
12 |
VAT-ID : DE335127327
13 |
14 | 15 | 16 |

Disclaimer

17 | 18 |

Liability for content

19 |

20 | As a service provider we are responsible according to § 7 paragraph 1 of TMG for own contents on 21 | these pages under the general laws. According to § § 8 to 10 TMG we are not obliged as a service 22 | provider to monitor transmitted or stored foreign information or to investigate circumstances 23 | that indicate illegal activity. Obligations to remove or block the use of information under the 24 | general laws remain unaffected. However, a relevant liability is only possible from the date of 25 | knowledge of a specific infringement. Upon notification of such violations, we will remove the 26 | content immediately. 27 |

28 | 29 |

Liability for links

30 |

31 | Our site contains links to external websites over which we have no control. Therefore we can not 32 | accept any responsibility for their content. The respective provider or operator of the pages is 33 | always responsible for the contents of any Linked Site. The linked sites were checked at the 34 | time of linking for possible violations of law. Illegal contents were at the time of linking. A 35 | permanent control of the linked pages is unreasonable without concrete evidence of a violation. 36 | Upon notification of violations, we will remove such links immediately. 37 |

38 | 39 |

Copyright

40 |

41 | The contents and works on these pages created by the site operator are subject to German 42 | copyright law. Duplication, processing, distribution and any kind of exploitation outside the 43 | limits of copyright require the written consent of its respective author or creator. Downloads 44 | and copies of these pages are only permitted for private, non-commercial use. As far as the 45 | content is not created by the website operator, the copyrights of third parties. Especially 46 | content of third parties will be marked as such. If you still get aware of copyright 47 | infringement, we ask for a hint. Upon notification of violations, we will remove such content 48 | immediately. 49 |

50 | 51 |

Settlements of Disputes

52 |

53 | The European Commission provides a platform for an online settlement of disputes which can be 54 | accessed under https://ec.europa.eu/consumers/odr/. Gitpod is neither obliged to take part in alternative dispute resolutions before a consumer 57 | dispute settlement commission or will do so voluntarily. 58 |

59 |
60 | -------------------------------------------------------------------------------- /src/routes/privacy/+page.svelte: -------------------------------------------------------------------------------- 1 |

Privacy Policy

2 |
Last updated September 5, 2022
3 |
4 |

5 | As this is a static website, we won’t be collecting any personal identifiable information about 6 | you in the context of the European General Data Protection Regulation (GDPR), unless you choose 7 | to contact us via email addresses posted on this website. Furthermore, this website is not using 8 | any advertisements, analytics, user tracking or cookies. The controller is Gitpod GmbH, Am 9 | Germaniahafen 1, 24143 Kiel/Germany, registered with the commercial register of the local court 10 | (Amtsgericht) Kiel under HRB 22228 ("we/us/our" or "Gitpod"). We offer services to our users and 11 | visitors (the "User/you/your") on our website https://developerexperience.us ("Website"). For 12 | any questions about data protection you may contact us via data@gitpod.io. If you would like to understand more about our privacy practices concerning Gitpod products 15 | and services, please refer to 16 | https://www.gitpod.io/privacy 17 |

18 |

In Short

19 |
    20 |
  • 21 |

    Controller

    22 |

    23 | Gitpod GmbH, am Germaniahafen 1, 24143 Kiel/Germany, registered with the commercial register 24 | of the local court (Amtsgericht) Kiel under HRB 22228, Email: contact@gitpod.io. We have appointed a data protection officer who may be contacted via 27 | data@gitpod.io. 28 |

    29 |
  • 30 |
  • 31 |

    32 | Purpose and Legal Basis of Processing Data; Provision and Recipients of Data 33 |

    34 |

    35 | When contacting us via email, the User’s details (name and email) are stored for the purpose 36 | of processing the enquiry and, if applicable, follow-up questions based on your consent 37 | (under Art. 6 (1) a. GDPR) or fulfilling your request on a contractual basis (under Art. 6 38 | (1) b. GDPR) 39 |

    40 |
  • 41 |
  • 42 |

    Your Rights

    43 |

    44 | You have the right to withdraw your consent relating to the use of data any time with effect 45 | for the future when such data processing is based on your consent. You are entitled to 46 | access the data stored by us and are also entitled to amend or rectify your data if such 47 | data are incorrect. You have the right to object to the processing of your personal data, 48 | for example if your personal data are processed for direct marketing purposes. You are 49 | entitled to request the erasure of your data. You are entitled to receive information about 50 | the stored data (in a structured, current and machine-readable format) at any time and to 51 | request the correction or deletion of the data in case of incorrect data storage. You have 52 | also the right to lodge a complaint with a supervisory authority of your choice. An overview 53 | of the European National Data Protection Authorities may be found here. 56 |

    57 |
  • 58 |
  • 59 |

    Period for Storing Data; Deletion

    60 |

    61 | The data are deleted if such data are no longer necessary for the purpose of processing, 62 | unless required by law to be retained. 63 |

    64 |
  • 65 |
  • 66 |

    Data Security

    67 |

    68 | We have implemented measures to ensure data and IT security. The Website is operated through 69 | a safe SSL-connection. If an SSL-connection is activated third parties are prevented from 70 | reading any data that are transferred by you to us. 71 |

    72 |
  • 73 |
74 |

More Detailed Information

75 | 120 |
    121 |
  • 122 |

    What is Personal Data?

    123 |

    124 | We have implemented measures to ensure data and IT security. The Website is operated through 125 | a safe SSL-connection. If an SSL-connection is activated third parties are prevented from 126 | reading any data that are transferred by you to us. 127 |

    128 |
  • 129 |
  • 130 |

    Applicable Laws to our processing of Personal Data

    131 |

    132 | We have implemented measures to ensure data and IT security. The Website is operated through 133 | a safe SSL-connection. If an SSL-connection is activated third parties are prevented from 134 | reading any data that are transferred by you to us. 135 |

    136 |
  • 137 |
  • 138 |

    139 | How is my Data processed when visiting the Website and contacting us? 140 |

    141 |
    142 |

    Visiting the Website

    143 |
    144 |
    145 |

    This website is not collecting any personal information about you.

    146 |

    Contacting us

    147 |
    148 |
    149 |

    150 | When contacting us via email, the User’s details (name and email) are stored for the purpose 151 | of processing the enquiry and, if applicable, follow-up questions based on your consent 152 | (under Art. 6 (1) a. GDPR) or fulfilling your request on a contractual basis (under Art. 6 153 | (1) b. GDPR). Use of Front: the mail provider “Front” by Frontapp, Inc., 1455 Market St Fl 154 | 19, San Francisco, California, 94102, United States receives and processes on our behalf the 155 | data necessary to manage client inquiries and emails. For more information refer to 156 | https://front.com/privacy-policy. 157 |

    158 |
  • 159 |
  • 160 |

    161 | What Third Party Services, Cookies, Analytics and Social Plugins does the Website use? 162 |

    163 |
    164 |

    Cookies

    165 |

    166 | This website is not using any cookies, third party services, analytics or social plugins. 167 |

    168 |
  • 169 |
  • 170 |

    171 | Are my Data transferred to Third Parties? Does Profiling or automated decision making take 172 | place? 173 |

    174 |
    175 |

    Transfer of Data to Third Parties

    176 |

    177 | We will transfer your personal data to a third party only (i) within the scope of legal 178 | provisions, i.e. if we are obliged to transfer the data due to a government or court order, 179 | or, (ii) if applicable, legal provisions authorize the transfer, e.g. if the transfer is 180 | required to pursue our legitimate interests or to fulfil a contract, for example in case of 181 | mergers and acquisitions, (iii) or if you give your explicit consent. 182 |

    183 | For more information please refer to this privacy policy or contact us via 184 | data@gitpod.io. 185 |

    186 |

    Automated Decision Making including Profiling

    187 |

    188 | In general we do not process any personal data via automated decision making including 189 | profiling via the Website or Service. However, such profiling or automated decision making 190 | may happen by third party providers through the Website or Service. We will inform you about 191 | such fact if possible. 192 |

    193 | Profiling means any automated processing of personal data to evaluate certain personal aspects 194 | relating to a natural person, in particular to analyse or predict aspects relating to the performance 195 | of work, economic situation, health, personal preferences, interests, reliability, behaviour, 196 | location or relocation of that natural person. Examples of such profiling include the analysis 197 | of data (e.g. based on statistical methods) with the aim of displaying personalized advertising 198 | to the user or (for example) giving shopping tips. The data subject shall not be subject to a 199 | decision based exclusively on automated processing, including profiling, which has legal effect 200 | against them or significantly affects them in a similar manner. 201 |

    202 |
  • 203 |
  • 204 |

    Is my Data transferred outside the EU?

    205 |

    206 | When contacting us via email, your data may be transferred to countries outside the EU by 207 | the third party services referred to in Section III. 210 |

    211 |
  • 212 |
  • 213 |

    Your Rights

    214 | As a data subject you have the right: 215 |
      216 |
    • 217 | (where we are relying on your consent) to withdraw your consent to us at any time. As a 218 | result, we are no longer allowed to continue the processing of data based on this consent 219 | in the future; 220 |
    • 221 |
    • 222 | to object to the processing of your personal data, if your personal data are processed on 223 | the basis of legitimate interests pursuant to Art. 6 (1) f. GDPR insofar as there are 224 | reasons for this arising from your particular situation; 225 |
    • 226 |
    • to obtain from us access to your personal data;
    • 227 |
    • 228 | to obtain from us without undue delay the rectification of inaccurate personal data 229 | concerning you; 230 |
    • 231 |
    • 232 | to obtain the erasure of your personal data stored with us, unless the processing is 233 | necessary to exercise the right to free expression of opinion and information, to fulfil a 234 | legal obligation, for reasons of public interest or to assert, exercise or defend legal 235 | claims; 236 |
    • 237 |
    • 238 | to request the restriction of the processing of your personal data, if e.g. the accuracy 239 | of the data is disputed by you, the processing is unlawful, but you refuse its deletion 240 | and we no longer need the data, but you need it to assert, exercise or defend legal claims 241 | or you have filed an objection against the processing; and 242 |
    • 243 |
    • 244 | to receive your personal data, which you have provided to us, in a structured, current and 245 | machine-readable format or to request the transmission to another controller. 246 |
    • 247 |
    248 |
    249 |

    250 | If you wish to make use of your rights mentioned above please send an email to data@gitpod.io. 253 |

    254 | If you obtain access to your personal data you may, in particular, request access to the following 255 | information: the purposes of the processing, the categories of personal data concerned, the recipients 256 | or categories of recipients to whom the personal data have been or will be disclosed. 257 |

    258 | You have the right to lodge a complaint vis-à-vis a supervisory authority of your choice. For 259 | example for Berlin/Germany: 260 | https://www.datenschutz-berlin.de/kontakt.html. An overview of the European National Data Protection Authorities may be found here: 266 | 271 | http://ec.europa.eu/newsroom/article29/item-detail.cfm?item_id=612080 273 |

    274 |
  • 275 |
  • 276 |

    277 | Duration of Storing your Data; Data Security; Access and Changes to this Privacy Policy; 278 | Contact Details 279 |

    280 |
    281 |

    Duration of Storing your Data

    282 |

    283 | As a rule, we only store your personal data for as long as it is necessary for the execution 284 | of the contract or the respective purpose and limit the storage period to an absolutely 285 | necessary minimum. 286 |

    287 | Criteria for the storage period include whether the data are still up-to-date, whether the contractual 288 | relationship with us still exists, whether an inquiry has already been processed, whether a process 289 | has been completed or not, and whether any legal retention periods for the personal data concerned 290 | are relevant or not. 291 |

    292 |

    Data Security

    293 |

    294 | We have installed technical and organisational measures in order to safeguard our Website 295 | and/or Service against loss, destruction, access, changes or the distribution of your data 296 | by unauthorised persons. 297 |

    298 | The Website and Service is operated through a safe SSL-connection. If an SSL-connection is activated 299 | third parties are prevented from reading any data that is transferred by you to us. 300 |

    301 | We store Personal Information in encrypted format, leveraging state-of-the-art encryption algorithms. 302 |

    303 | We also maintain an Information Security & Privacy program with established policies and procedures 304 | that govern the confidentiality, integrity and availability of data. 305 |

    306 |

    Access and Changes to this Privacy Policy

    307 |

    308 | This privacy policy is accessible via our Website and may be 309 | downloaded and printed anytime. 310 |

    311 | We reserve the right to change this privacy policy at any time, taking into account currently 312 | applicable data protection provisions. In case of any changes, an update will be posted to our 313 | website showing the new version of the policy and the date of last review. 314 |

    315 |

    Contact

    316 |

    317 | For any inquiries and additional questions about processing personal data please contact data@gitpod.io 320 |

    321 | Further details may be found here. 322 |

    323 |
  • 324 |
325 |
326 | 327 | 339 | -------------------------------------------------------------------------------- /static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/favicon.png -------------------------------------------------------------------------------- /static/font.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Manrope'; 3 | font-style: normal; 4 | font-weight: 400; 5 | font-display: swap; 6 | src: url('./fonts/Manrope-Regular.woff2') format('woff2'); 7 | } 8 | 9 | @font-face { 10 | font-family: 'Manrope'; 11 | font-style: bold; 12 | font-weight: 600; 13 | font-display: swap; 14 | src: url('./fonts/Manrope-Bold.woff2') format('woff2'); 15 | } 16 | -------------------------------------------------------------------------------- /static/fonts/Manrope-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/fonts/Manrope-Bold.woff2 -------------------------------------------------------------------------------- /static/fonts/Manrope-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/fonts/Manrope-Regular.woff2 -------------------------------------------------------------------------------- /static/images/portraits/abi_noda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/abi_noda.png -------------------------------------------------------------------------------- /static/images/portraits/alexander_podkhalyuzin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/alexander_podkhalyuzin.jpg -------------------------------------------------------------------------------- /static/images/portraits/chris_weichel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/chris_weichel.jpg -------------------------------------------------------------------------------- /static/images/portraits/cirpo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/cirpo.jpeg -------------------------------------------------------------------------------- /static/images/portraits/elvis_kahoro.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/elvis_kahoro.jpeg -------------------------------------------------------------------------------- /static/images/portraits/geoffrey_teale.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/geoffrey_teale.jpg -------------------------------------------------------------------------------- /static/images/portraits/josh_maxwell.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/josh_maxwell.jpeg -------------------------------------------------------------------------------- /static/images/portraits/pauline_narvas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/pauline_narvas.png -------------------------------------------------------------------------------- /static/images/portraits/phillip_carter.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/phillip_carter.jpeg -------------------------------------------------------------------------------- /static/images/portraits/zohar_einy.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/images/portraits/zohar_einy.jpeg -------------------------------------------------------------------------------- /static/media-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-io/devx-community/669501ffeb2b60890d7b72613c8d6dc1f170be57/static/media-image.jpg -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-netlify'; 2 | import preprocess from 'svelte-preprocess'; 3 | import { vitePreprocess } from '@sveltejs/kit/vite'; 4 | 5 | /** @type {import('@sveltejs/kit').Config} */ 6 | const config = { 7 | // Consult https://github.com/sveltejs/svelte-preprocess 8 | // for more information about preprocessors 9 | preprocess: [ 10 | vitePreprocess(), 11 | preprocess({ 12 | postcss: true 13 | }) 14 | ], 15 | 16 | kit: { 17 | adapter: adapter({ 18 | split: true 19 | }), 20 | files: { 21 | lib: 'src/lib' 22 | } 23 | } 24 | }; 25 | 26 | export default config; 27 | -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | const defaultTheme = require('tailwindcss/defaultTheme'); 2 | 3 | const config = { 4 | content: ['./src/**/*.{html,js,svelte,ts}'], 5 | darkMode: 'class', 6 | theme: { 7 | extend: { 8 | colors: { 9 | explicit: { 10 | white: 'var(--white)', 11 | black: 'var(--black)', 12 | 'white-light': 'var(--white-light)', 13 | 'grey-slight': 'var(--grey-slight)' 14 | }, 15 | nav: 'var(--nav)', 16 | highlight: 'var(--highlight)', 17 | important: 'var(--important)', 18 | body: 'var(--body)', 19 | sub: 'var(--sub)', 20 | bg: 'var(--bg)', 21 | box: 'var(--box)' 22 | }, 23 | boxShadow: { 24 | 'hover-default': 'var(--shadow-hover-default)', 25 | default: 'var(--shadow-default)' 26 | }, 27 | transitionDelay: { 28 | 50: '50ms' 29 | }, 30 | backgroundImage: { 31 | primary: 'var(--gradient-primary)', 32 | stroke: 'var(--gradient-stroke)', 33 | 404: 'var(--gradient-404)' 34 | }, 35 | spacing: { 36 | 'xx-large': 'var(--xx-large)', 37 | 'x-large': 'var(--x-large)', 38 | large: 'var(--large)', 39 | medium: 'var(--medium)', 40 | small: 'var(--small)', 41 | 'x-small': 'var(--x-small)', 42 | 'xx-small': 'var(--xx-small)' 43 | }, 44 | fontFamily: { 45 | sans: ['Manrope', ...defaultTheme.fontFamily.sans] 46 | }, 47 | fontSize: { 48 | h1: 'var(--h1)', 49 | h2: 'var(--h2)', 50 | h3: 'var(--h3)', 51 | h4: 'var(--h4)', 52 | 53 | 'p-x-large': 'var(--p-x-large)', 54 | 'p-large': 'var(--p-large)', 55 | 'p-medium': 'var(--p-medium)', 56 | 'p-small': 'var(--p-small)', 57 | 58 | inter: [ 59 | 'var(--p-large)', 60 | { 61 | lineHeight: '1.625rem', 62 | letterSpacing: '0.2em' 63 | } 64 | ], 65 | main: ['18px', { lineHeight: '1.688rem' }] 66 | } 67 | } 68 | }, 69 | 70 | plugins: [] 71 | }; 72 | 73 | module.exports = config; 74 | -------------------------------------------------------------------------------- /tests/test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from '@playwright/test'; 2 | 3 | test('index page has expected h1', async ({ page }) => { 4 | await page.goto('/'); 5 | expect(await page.textContent('h1')).toBe('Welcome to SvelteKit'); 6 | }); 7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import type { UserConfig } from 'vite'; 3 | import { execSync } from 'node:child_process'; 4 | 5 | let extendedViteDevServerOptions; 6 | 7 | try { 8 | const gitpodPortUrl = execSync(`gp url ${5173}`).toString().trim(); 9 | 10 | extendedViteDevServerOptions = { 11 | hmr: { 12 | protocol: 'wss', 13 | host: new URL(gitpodPortUrl).hostname, 14 | clientPort: 443 15 | } 16 | }; 17 | } catch { 18 | extendedViteDevServerOptions = {}; 19 | } 20 | 21 | const config: UserConfig = { 22 | plugins: [sveltekit()], 23 | server: { 24 | ...extendedViteDevServerOptions 25 | } 26 | }; 27 | 28 | export default config; 29 | --------------------------------------------------------------------------------