From 4bcff57f94364177d417ebe844b93cf05ce128f8 Mon Sep 17 00:00:00 2001 From: Nisar Hassan Naqvi Date: Tue, 4 Aug 2020 03:10:45 +0000 Subject: [PATCH 1/5] add prettier(extensions + config + ignore). --- .gitpod.yml | 18 ++++++++++-------- .prettierignore | 4 ++++ .prettierrc.json | 1 + 3 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc.json diff --git a/.gitpod.yml b/.gitpod.yml index 2a36d9f9a..d7ec893d4 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -12,21 +12,23 @@ vscode: - jpoissonnier.vscode-styled-components@0.0.29:7hF8G3VtB+HNearI5Zw+NA== - paulmolluzzo.convert-css-in-js@1.1.3:YnjK47pXScU3DMFfQzkkOw== + - esbenp.prettier-vscode@5.1.3:t532ajsImUSrA9N8Bd7jQw== + github: prebuilds: # enable for the master/default branch (defaults to true) master: true - # enable for all branches in this repo (defaults to false) +# enable for all branches in this repo (defaults to false) branches: true - # enable for pull requests coming from this repo (defaults to true) +# enable for pull requests coming from this repo (defaults to true) pullRequests: true - # enable for pull requests coming from forks (defaults to false) +# enable for pull requests coming from forks (defaults to false) pullRequestsFromForks: true - # add a check to pull requests (defaults to true) +# add a check to pull requests (defaults to true) addCheck: true - # add a "Review in Gitpod" button as a comment to pull requests (defaults to false) +# add a "Review in Gitpod" button as a comment to pull requests (defaults to false) addComment: false - # add a "Review in Gitpod" button to the pull request's description (defaults to false) +# add a "Review in Gitpod" button to the pull request's description (defaults to false) addBadge: false - # add a label once the prebuild is ready to pull requests (defaults to false) - addLabel: false +# add a label once the prebuild is ready to pull requests (defaults to false) + addLabel: false \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..db82f00bf --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +node_modules/ +.public/ +.cache/ + diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1 @@ +{} From ef10622e5c7f8e29a0b23d33488c74dfb23220f6 Mon Sep 17 00:00:00 2001 From: Nisar Hassan Naqvi Date: Tue, 4 Aug 2020 04:20:51 +0000 Subject: [PATCH 2/5] fix linting + type checking errors + format the entire code base with prettier. --- src/blog/bitbucket.md | 22 +- .../build-a-webhook-for-google-assistant.md | 64 +- .../continuous-dev-environment-in-devops.md | 5 +- src/blog/dev-env-as-code.md | 10 +- src/blog/developing-nuxtjs-in-browser.md | 4 +- src/blog/docker-in-gitpod.md | 30 +- src/blog/github-codespaces.md | 22 +- src/blog/github-flow.md | 9 +- src/blog/gitlab-support.md | 25 +- src/blog/gitpod-launch.md | 27 +- src/blog/gitpod-online-ide.md | 32 +- src/blog/gitpod-self-hosted-0.4.0.md | 7 +- src/blog/gitpodify.md | 29 +- src/blog/local-services-in-gitpod.md | 30 +- src/blog/native-ui-with-vnc.md | 2 +- src/blog/node-js-development.md | 58 +- src/blog/node-js-gitpod.md | 8 +- src/blog/october-2018-release.md | 6 +- src/blog/open-vsx-in-gitpod.md | 10 +- src/blog/open-vsx.md | 2 +- src/blog/prebuilds.md | 9 +- src/blog/status-page.md | 6 +- src/blog/update-december-2019.md | 43 +- src/blog/visual-studio-online-vs-gitpod.md | 13 +- src/blog/vscode-extension-in-online-ide.md | 2 +- src/blog/when-code-reviews-lgtm.md | 4 +- src/blog/workspace-snapshots.md | 15 +- src/browser.ts | 4 +- src/components/ActionCard.tsx | 69 +- src/components/Arrow.tsx | 53 +- src/components/BackToTopButton.tsx | 75 +- src/components/Banner.tsx | 125 +- src/components/Bg.tsx | 27 +- src/components/Circle.tsx | 2 +- src/components/DropDown.tsx | 160 +- src/components/ExternalLink.tsx | 54 +- src/components/FeatureCard.tsx | 385 +++-- src/components/FeatureCards.tsx | 35 +- src/components/FeatureItem.tsx | 22 +- src/components/FeaturesSection.tsx | 43 +- src/components/Footer.tsx | 378 ++--- src/components/InfoCard.tsx | 124 +- src/components/LayoutMain.tsx | 4 +- src/components/Linkset.tsx | 92 +- src/components/MoreInfo.tsx | 155 +- src/components/Nav.tsx | 205 +-- src/components/NewsletterForm.tsx | 79 +- src/components/Offers.tsx | 117 +- src/components/OnBoarding.tsx | 20 +- src/components/PopOver.tsx | 71 +- src/components/PricingBox.tsx | 201 +-- src/components/PricingTable.tsx | 179 ++- src/components/Quote.tsx | 135 +- src/components/TextBox.tsx | 72 +- src/components/TextCard.tsx | 46 +- src/components/TextCards.tsx | 18 +- src/components/blog/PostBanner.tsx | 132 +- src/components/blog/PostPreview.tsx | 168 +- src/components/careers/ExpandableJob.tsx | 169 +- src/components/docs/DocSearch.tsx | 54 +- src/components/docs/DocSideBar.tsx | 29 +- src/components/docs/DocTopicChooser.tsx | 43 +- src/components/docs/EditInGitpod.tsx | 60 +- src/components/docs/NavigationArrows.tsx | 44 +- src/components/docs/ReachOut.tsx | 120 +- src/components/features/FeatureBox.tsx | 133 +- .../features/FullAutomationButtons.tsx | 38 +- .../features/FullAutomationGraphics.tsx | 49 +- src/components/features/Intro.tsx | 117 +- src/components/features/StarFortFree.tsx | 40 +- src/components/index/Banner.tsx | 42 +- src/components/index/GetStarted.tsx | 124 +- src/components/index/PrefixInput.tsx | 539 ++++--- src/components/index/Project.tsx | 87 +- src/components/index/SaveHours.tsx | 30 +- src/components/index/StartWorkspace.tsx | 107 +- src/components/index/Testimonials.tsx | 70 +- src/components/index/TextFeature.tsx | 78 +- src/components/index/TrustedBy.tsx | 142 +- src/components/pricing/Plans.tsx | 169 +- src/components/pricing/PricingBoxes.tsx | 418 ++--- src/components/pricing/SelfHostedFAQs.tsx | 186 ++- src/components/pricing/Tabs.tsx | 102 +- src/components/self-hosted/Install.tsx | 156 +- src/content/a-markdown-page.md | 2 +- src/docs/README.md | 2 + src/docs/browser-extension.md | 5 +- src/docs/changelog.md | 1 + src/docs/checkout-location.md | 25 +- src/docs/command-line-interface.md | 7 + src/docs/config-docker.md | 26 +- src/docs/config-editor.md | 11 +- src/docs/config-gitpod-file.md | 7 +- src/docs/config-ports.md | 21 +- src/docs/config-start-tasks.md | 48 +- src/docs/configuration.md | 12 +- src/docs/context-urls.md | 12 +- src/docs/environment-variables.md | 12 +- src/docs/getting-started.md | 2 +- src/docs/git.md | 53 +- src/docs/ide.md | 12 +- src/docs/languages/bash.md | 8 +- src/docs/languages/cpp.md | 11 +- src/docs/languages/dart.md | 7 +- src/docs/languages/dotnet.md | 34 +- src/docs/languages/go.md | 26 +- src/docs/languages/html.md | 14 +- src/docs/languages/java.md | 41 +- src/docs/languages/php.md | 12 +- src/docs/languages/python.md | 59 +- src/docs/languages/ruby.md | 13 +- src/docs/languages/rust.md | 73 +- src/docs/languages/vue.md | 17 +- src/docs/life-of-workspace.md | 11 +- src/docs/menu.ts | 402 ++--- src/docs/prebuilds.md | 20 +- src/docs/professional-open-source.md | 8 +- src/docs/release-notes.md | 8 +- .../release-notes/2019-02-15/february-2019.md | 28 +- .../release-notes/2019-04-05/april-2019.md | 2 +- .../release-notes/2019-06-17/june-2019.md | 1 + src/docs/search.md | 22 +- src/docs/self-hosted/0.3.0/admin/admin.md | 3 - .../self-hosted/0.3.0/install/database.md | 21 +- .../0.3.0/install/docker-registry.md | 1 + src/docs/self-hosted/0.3.0/install/helm-2x.md | 4 + .../self-hosted/0.3.0/install/https-certs.md | 9 +- .../0.3.0/install/install-on-gcp-manual.md | 43 +- .../0.3.0/install/install-on-gcp-script.md | 4 +- .../0.3.0/install/install-on-kubernetes.md | 25 +- src/docs/self-hosted/0.3.0/install/nodes.md | 12 +- src/docs/self-hosted/0.3.0/install/oauth.md | 30 +- .../0.3.0/install/prepare-installation.md | 37 +- src/docs/self-hosted/0.3.0/install/storage.md | 9 +- .../self-hosted/0.3.0/install/workspaces.md | 1 + src/docs/self-hosted/0.3.0/self-hosted.md | 10 +- src/docs/self-hosted/0.4.0/admin/admin.md | 3 - .../self-hosted/0.4.0/install/database.md | 27 +- .../0.4.0/install/docker-registry.md | 5 +- src/docs/self-hosted/0.4.0/install/helm-2x.md | 4 + .../self-hosted/0.4.0/install/https-certs.md | 10 +- .../0.4.0/install/install-on-gcp-manual.md | 43 +- .../0.4.0/install/install-on-gcp-script.md | 5 +- .../0.4.0/install/install-on-kubernetes.md | 20 +- src/docs/self-hosted/0.4.0/install/nodes.md | 12 +- src/docs/self-hosted/0.4.0/install/oauth.md | 45 +- src/docs/self-hosted/0.4.0/install/storage.md | 11 +- .../self-hosted/0.4.0/install/workspaces.md | 1 + src/docs/self-hosted/0.4.0/self-hosted.md | 8 +- src/docs/sharing-and-collaboration.md | 16 +- src/docs/teams.md | 14 +- src/docs/tips-and-tricks.md | 33 +- src/docs/workspaces.md | 8 +- src/layouts/docs.tsx | 33 +- src/layouts/index.tsx | 199 +-- src/pages/404.tsx | 55 +- src/pages/about.tsx | 148 +- src/pages/blog.tsx | 198 ++- src/pages/careers.tsx | 385 +++-- src/pages/contact.tsx | 356 +++-- src/pages/education.tsx | 346 +++-- src/pages/enterprise.tsx | 302 ++-- src/pages/features.tsx | 22 +- src/pages/github-student-developer-pack.tsx | 162 +- src/pages/github-teacher-toolbox.tsx | 161 +- src/pages/imprint.tsx | 114 +- src/pages/index.tsx | 271 ++-- src/pages/media-kit.tsx | 238 +-- src/pages/pricing.tsx | 53 +- src/pages/privacy.tsx | 1364 ++++++++--------- src/pages/recruiting.tsx | 357 +++-- src/pages/self-hosted.tsx | 106 +- src/pages/terms.tsx | 924 +++++------ src/pages/vendor.tsx | 337 ++-- src/styles/normalize.ts | 2 +- src/styles/variables.ts | 70 +- src/templates/blog.tsx | 339 ++-- src/templates/doc.tsx | 88 +- src/typings.d.ts | 20 +- src/utils/authors.ts | 207 +-- src/utils/education.tsx | 57 +- src/utils/enterprise.tsx | 72 +- src/utils/features.tsx | 683 +++++---- src/utils/helpers.ts | 4 +- src/utils/index.tsx | 89 +- src/utils/link.tsx | 35 +- src/utils/moreInfoContents.tsx | 36 +- src/utils/projects.tsx | 65 +- src/utils/recruiting.tsx | 41 +- src/utils/self-hosted.tsx | 64 +- src/utils/vendor.tsx | 42 +- 191 files changed, 8506 insertions(+), 7978 deletions(-) diff --git a/src/blog/bitbucket.md b/src/blog/bitbucket.md index f85a458c6..9428ee981 100644 --- a/src/blog/bitbucket.md +++ b/src/blog/bitbucket.md @@ -25,18 +25,21 @@ For more convenience, you can also install Gitpod's browser extension (for [Chro Gitpod also supports other types of Bitbucket URLs, like: - - Opening file URLs +- Opening file URLs -

Example: https://gitpod.io/#https://bitbucket.org/gitpod/spring-petclinic/.../petclinic/PetClinicApplication.java

- - Opening branches +

Example: https://gitpod.io/#https://bitbucket.org/gitpod/spring-petclinic/.../petclinic/PetClinicApplication.java

-

Example: https://gitpod.io/#https://bitbucket.org/gitpod/spring-petclinic/src/my-branch/

- - Opening issues +- Opening branches -

Example: https://gitpod.io/#https://bitbucket.org/gitpod/spring-petclinic/issues/1/make-first-name-optional

- - Opening pull requests +

Example: https://gitpod.io/#https://bitbucket.org/gitpod/spring-petclinic/src/my-branch/

-

Example: https://gitpod.io/#https://bitbucket.org/gitpod/spring-petclinic/pull-requests/1/allow-omitting-first-name/diff

+- Opening issues + +

Example: https://gitpod.io/#https://bitbucket.org/gitpod/spring-petclinic/issues/1/make-first-name-optional

+ +- Opening pull requests + +

Example: https://gitpod.io/#https://bitbucket.org/gitpod/spring-petclinic/pull-requests/1/allow-omitting-first-name/diff

Depending on the context, your dev environment will be initialized differently. @@ -60,7 +63,8 @@ There is much more you can do to make sure every team member gets a ready-to-cod Gitpod’s [prebuilt workspaces](/docs/prebuilds/) are key to providing ephemeral, ready-to-code dev environments for your branches and projects. You can configure Gitpod to run your project's build asynchronously every time someone pushes new commits or branches to your repository. So when a developer wants to start coding, she can start immediately, because everything is already prepared. Enabling prebuilds on your Bitbucket project is done by configuring a Webhook. This can be done automatically: Just trigger the first prebuild on your project manually, and Gitpod will take it from there. To do that, use the prefix `https://gitpod.io/#prebuild/`, as in -> __https://gitpod.io/#prebuild/__`https://bitbucket.org//` + +> **https://gitpod.io/#prebuild/**`https://bitbucket.org//` ## We Need Your Feedback diff --git a/src/blog/build-a-webhook-for-google-assistant.md b/src/blog/build-a-webhook-for-google-assistant.md index f46885525..9c08e3ce1 100644 --- a/src/blog/build-a-webhook-for-google-assistant.md +++ b/src/blog/build-a-webhook-for-google-assistant.md @@ -10,14 +10,17 @@ image: https://res-3.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/ This post is all about how to build your webhook for your Google Assistant action and host it temporarily on Gitpod and test your code. ## Prerequisites -* Node JS -* Express JS -* Basics on how to use Github + +- Node JS +- Express JS +- Basics on how to use Github If you have these in place, Let's get started. ## What is Gitpod? + First of all I would like to start this section by saying, I ❤ Gitpod. Gitpod is an online IDE for Github. Gitpod provides you with a fully working development environment, including a VS Code-powered IDE and a cloud-based Linux container configured specifically for the project at hand. Just prefix your Github repo URL with "https://gitpod.io/#", So that the final link looks something like this "https://gitpod.io/#https://github.com//" or you can also use the Gitpod [browser extension](https://chrome.google.com/webstore/detail/gitpod-online-ide/dodmmooeoklaejobgleioelladacbeki?hl=en) to add the Gitpod button to Github page. + ## Let's start building @@ -25,28 +28,29 @@ First of all I would like to start this section by saying, I ❤ Gitpod. Gitpod I have created a Github repo which will help you get started without any hassle. The repo is basically a boilerplate to get started with building your webhook. The code is written in Node JS, So it would be easier for you to build on top of it if you are already familiar with Node JS. We will be using the [action-on-google](https://www.npmjs.com/package/actions-on-google) Node JS library (This client library makes it easy to create Actions for the Google Assistant and supports Dialogflow, Actions SDK, and Smart Home fulfillment.). ### Create your Action -* Head over to https://console.actions.google.com/ and click on New Project. + +- Head over to https://console.actions.google.com/ and click on New Project. ![Google Actions Console](https://res-2.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/Annotation-2019-06-28-141627.png) -* Enter your project name and click on create project. +- Enter your project name and click on create project. ![Google Actions Create New Project Prompt](https://res-1.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/gitpod-action.png) -* Now select a category for your Action. -* Now under the Develop menu, give your action a name. -* Now head over to actions menu in Develop tab and click on **Add your first action**. +- Now select a category for your Action. +- Now under the Develop menu, give your action a name. +- Now head over to actions menu in Develop tab and click on **Add your first action**. !["Add your first action" button](https://res-1.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/temp2.png) -* In the next section choose **custom intent** and click on **build**. Doing this will redirect you to the **Dialogflow console** and it should look something like this. +- In the next section choose **custom intent** and click on **build**. Doing this will redirect you to the **Dialogflow console** and it should look something like this. ![Dialogflow console](https://res-3.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/temp3.png) -* Click on create to **create** your agent on Dialogflow. -* Once your agent is ready, you will already have two default Intents (Default Fallback Intent and Default Welcome Intent) in place and these two do pretty good at their job. -* Now it's time to create a new intent and enable fulfillments for that intent so that we can serve responses from the webhook that we will be building in the next section. -* Click on create a new intent, give it a name and training phrase (training phrase will be used to invoke the intent). Now that your intent is almost ready scroll down and under fulfillments **enable webhook call** for the new Default welcome intent and the new intent you just created. +- Click on create to **create** your agent on Dialogflow. +- Once your agent is ready, you will already have two default Intents (Default Fallback Intent and Default Welcome Intent) in place and these two do pretty good at their job. +- Now it's time to create a new intent and enable fulfillments for that intent so that we can serve responses from the webhook that we will be building in the next section. +- Click on create a new intent, give it a name and training phrase (training phrase will be used to invoke the intent). Now that your intent is almost ready scroll down and under fulfillments **enable webhook call** for the new Default welcome intent and the new intent you just created. ### Understanding .gitpod.yml @@ -69,6 +73,7 @@ When starting or restarting a workspace you typically want to run certain tasks. Gitpod allows you to configure start tasks in the .gitpod.yml file. For instance, the start script for this repository is defined as: + ``` tasks: - init: npm install @@ -76,6 +81,7 @@ tasks: ``` You can have multiple tasks, which are opened on separated terminals. + ``` tasks: - init: npm install @@ -84,32 +90,33 @@ tasks: ``` #### `init` command + The init property can be used to specify shell commands that should only be executed after a workspace was freshly cloned and needs to be initialized somehow. Such tasks are usually builds or downloading dependencies. Anything you only want to do once but not when you restart a workspace or start a snapshot. In our case the `init` command is + ``` tasks: - init: npm install ``` - ### Get the Gitpod setup running -* Fork my [repo (dialogflow-webhook-boilerplate-nodejs)](https://github.com/anudeepreddy/dialogflow-webhook-boilerplate-nodejs) **or** just click on the run in gitpod button in my repo. (If you do this you have to fork it from the workspace so that you can commit your own changes to your repo). -* Now you can just prefix your repo url with "https://gitpod.io/#". This should take you to Gitpod and start your workspace. The workspace take a little while to start. -* Once the workspace is running you should see something like this. + +- Fork my [repo (dialogflow-webhook-boilerplate-nodejs)](https://github.com/anudeepreddy/dialogflow-webhook-boilerplate-nodejs) **or** just click on the run in gitpod button in my repo. (If you do this you have to fork it from the workspace so that you can commit your own changes to your repo). +- Now you can just prefix your repo url with "https://gitpod.io/#". This should take you to Gitpod and start your workspace. The workspace take a little while to start. +- Once the workspace is running you should see something like this. ![Gitpod Workspace](https://res-2.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/Annotation-2019-06-25-171555.png) -* If you notice the Node app is already running in the first terminal. This is automated by a Gitpod configuration file. And the webhook URL is printed on to the second terminal. All the dependencies that are required are also installed while creating the workspace. +- If you notice the Node app is already running in the first terminal. This is automated by a Gitpod configuration file. And the webhook URL is printed on to the second terminal. All the dependencies that are required are also installed while creating the workspace. ![Gitpod integrated Linux Terminals](https://res-5.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/Annotation-2019-06-25-171555-crop.png) -* Now that the webhook is running and i presume that you already have your agent on Dialogflow (If not create an agent), Next thing you need to do is to copy the webhook URL from the terminal and paste it in the Fulfillments section in the Dialogflow Console. +- Now that the webhook is running and i presume that you already have your agent on Dialogflow (If not create an agent), Next thing you need to do is to copy the webhook URL from the terminal and paste it in the Fulfillments section in the Dialogflow Console. ![Dialogflow console Fullfillments section](https://res-5.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/Annotation-2019-06-25-172359.png) - -* Open the index.js file which contains the code for the webhook. +- Open the index.js file which contains the code for the webhook. ![File index.js which contains the source code for the webhook](https://res-1.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/carbon--1-.png) @@ -122,25 +129,26 @@ We will be adding the following code to display a card when the new intent is in Replace the URL's and other contents in the code and stop the previous instance of the app from running and start it again after you have made changes to the code by running `npm start` in the terminal. -* To test your action you can click on **See how it works in Google Assistant** in the Dialogflow console. +- To test your action you can click on **See how it works in Google Assistant** in the Dialogflow console. ![See how it works in Google Assistant](https://res-3.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/Annotation-2019-06-28-175558.png) -* Invoking the intent would give you response similar to this. +- Invoking the intent would give you response similar to this. ![Response on invoking the intent](https://res-5.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/Screenshot_20190628-181019.png) Refer to the links below to add your own functionalities. ## Links to Refer -* If you would like to learn more about the actions-on-google library, you can find it here - https://www.npmjs.com/package/actions-on-google -* Go through these examples - https://developers.google.com/actions/samples/github -* Rich responses example - https://github.com/actions-on-google/dialogflow-conversation-components-nodejs + +- If you would like to learn more about the actions-on-google library, you can find it here - https://www.npmjs.com/package/actions-on-google +- Go through these examples - https://developers.google.com/actions/samples/github +- Rich responses example - https://github.com/actions-on-google/dialogflow-conversation-components-nodejs ## Conclusion -Gitpod can make your life much simpler by automating your development setup just by adding a simple configuration file to your repo. You can refer to the Gitpod [Docs](https://www.gitpod.io/docs/) to learn more about the platform. Gitpod lets you work with unlimited workspace but with 100hrs/month runtime. It also provides Personal and unlimited plans as well. If you are a student then you can claim Gitpod Unlimited plan for just $9. +Gitpod can make your life much simpler by automating your development setup just by adding a simple configuration file to your repo. You can refer to the Gitpod [Docs](https://www.gitpod.io/docs/) to learn more about the platform. Gitpod lets you work with unlimited workspace but with 100hrs/month runtime. It also provides Personal and unlimited plans as well. If you are a student then you can claim Gitpod Unlimited plan for just \$9. ![Animated character waving hand with a smile](https://res-3.cloudinary.com/anudeepc/image/upload/q_auto/v1/blog-images/character.gif) -# Happy coding with Gitpod ✨ +# Happy coding with Gitpod ✨ diff --git a/src/blog/continuous-dev-environment-in-devops.md b/src/blog/continuous-dev-environment-in-devops.md index 54d85d281..5b5cad4ff 100644 --- a/src/blog/continuous-dev-environment-in-devops.md +++ b/src/blog/continuous-dev-environment-in-devops.md @@ -18,6 +18,7 @@ Getting our dev environments into a ready-to-code state is usually still done ma **Continuous dev environments** are a crucial part in a fully optimized DevOps toolchain, that allow to instantaneously spin up a ready-to-code development environment from any git state. Continuous dev environments reduce friction in onboarding and task switching and improves reproducibility across the project. ## Automated Dev Environments + Automating dev environments is not new and usually focusses on the initial setup, but that doesn't quite cut it. Of course, we all have felt the pain of being on-boarded in a new project, spending the first week figuring out what tools to install and how to configure them correctly. Manually setting up a dev environment is a waste of energy. Surprising that we still do such things, given that we developers are usually busy automating everything else in the world. ![disposable dev environments](./continuous-dev-environment-in-devops/gears.jpg) @@ -67,15 +68,17 @@ The Theia IDE open-source project is fully configured with continuously prebuilt ![Theia in Gitpod](./continuous-dev-environment-in-devops/theia.png) ## But my environment is different than those from my teammates! + Yes, of course, there are personal preferences like themes, keybindings, or even one or the other tool. Some developers heavily use command-line tools and have very advanced configurations. Others use particular VS Code extensions that improve their workflow significantly. ![Individual](./continuous-dev-environment-in-devops/share.jpg) > Why don't we share all that goodness within the team? -While [Gitpod](/) lets you have user-specific settings, we see an opportunity in sharing the wisdom within the team to ***build a perfect, friction-free setup for everyone***. This way, you can share your impressive terminal skills and configuration with your team, and you might learn a new thing or two as well. +While [Gitpod](/) lets you have user-specific settings, we see an opportunity in sharing the wisdom within the team to **_build a perfect, friction-free setup for everyone_**. This way, you can share your impressive terminal skills and configuration with your team, and you might learn a new thing or two as well. ## The missing piece in DevOps + I'm pretty sure, automated ready-to-code dev environments will become mainstream. The advantages and implications are just too good to be ignored. Everyone who has understood and experienced the benefits of a proper DevOps toolchain should understand how providing dev environments on-demand completes that experience. Ironing out that last area of non-reproducible and very annoying yak-shaving should be high on our todo list as it will improve developer productivity drastically. Gitpod is available [to open-source projects for free and affordable for commercial projects](/pricing), through the Saas offering (Gitpod.io). [Gitpod Enterprise](/pricing#enterprise) will soon be released, allows self-hosting Gitpod on any Kubernetes cluster, and integrates with GitHub Enterprise, GitLab, Jenkins, JIRA and other tools in your DevOps toolchain. diff --git a/src/blog/dev-env-as-code.md b/src/blog/dev-env-as-code.md index 8075b62b0..71d45a0f8 100644 --- a/src/blog/dev-env-as-code.md +++ b/src/blog/dev-env-as-code.md @@ -24,7 +24,7 @@ It often goes like that: 1. **Reads lengthy, mostly outdated setup procedure** 1. **Installs requirements on the developer machine, -updates/downgrades versions, etc.** + updates/downgrades versions, etc.** 1. **Tries to run the build … waits 20 minutes** @@ -52,7 +52,7 @@ Another pet peeve is when you need to fix something on a maintenance branch. Fix Tinkering with a six months old technology stack can be so annoying. You have to deal with all those old libraries and versions of them. However, you still have to make it work somehow. -![Photo by [JESHOOTS.COM](https://unsplash.com/@jeshoots?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://cdn-images-1.medium.com/max/10944/0*fni6JI11_OS6eJV7)*Photo by [JESHOOTS.COM](https://unsplash.com/@jeshoots?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)* +![Photo by [JESHOOTS.COM](https://unsplash.com/@jeshoots?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://cdn-images-1.medium.com/max/10944/0*fni6JI11_OS6eJV7)_Photo by [JESHOOTS.COM](https://unsplash.com/@jeshoots?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)_ All this suffering can end if we applied the ‘infrastructure as code’ idea to our dev environments, too. Why not make dev environment setups automated, reliably reproducible, and versioned by writing them down in an executable format and checking them into the project’s source code repository? @@ -66,13 +66,13 @@ So let’s please stop polluting our readme files and start writing setup instru ### Dockerfiles -Docker files are a pretty neat way to describe a development environment. Imagine you want to add something like ‘*asciidoctor*’ to your project’s toolchain. You could just add the following line to your dev environment’s Dockerfile: +Docker files are a pretty neat way to describe a development environment. Imagine you want to add something like ‘_asciidoctor_’ to your project’s toolchain. You could just add the following line to your dev environment’s Dockerfile: RUN apt-get install -y asciidoctor Once you push the change to the repository and the docker image gets updated (automatically), all team members have the new tool in their development environment. We need to get to coding with a single click. -![Photo by [Clément H](https://unsplash.com/@clemhlrdt?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://cdn-images-1.medium.com/max/12000/0*_7n4Htwk2Iz-r9qA)*Photo by [Clément H](https://unsplash.com/@clemhlrdt?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)* +![Photo by [Clément H](https://unsplash.com/@clemhlrdt?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://cdn-images-1.medium.com/max/12000/0*_7n4Htwk2Iz-r9qA)_Photo by [Clément H](https://unsplash.com/@clemhlrdt?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)_ ### **Automated IDE Setup** @@ -94,4 +94,4 @@ Applying the lessons learned from DevOps to our development setup can save us so ![ActiveState’s Developer Survey 2018: How much time do you spent on managing dependencies and development tools](https://cdn-images-1.medium.com/max/3200/1*Vvl3N-1hDANiy15Pc9xeiQ.png) -Do we really need to welcome new colleagues or contributors with a painful on-boarding experience? Let’s skip the prose in the *readme* and write code to have our dev environment setup **automated, reproducible, and versioned.** +Do we really need to welcome new colleagues or contributors with a painful on-boarding experience? Let’s skip the prose in the _readme_ and write code to have our dev environment setup **automated, reproducible, and versioned.** diff --git a/src/blog/developing-nuxtjs-in-browser.md b/src/blog/developing-nuxtjs-in-browser.md index cb0b919e7..575994493 100644 --- a/src/blog/developing-nuxtjs-in-browser.md +++ b/src/blog/developing-nuxtjs-in-browser.md @@ -61,11 +61,11 @@ In the terminal type A notification window will pop up asking you to either open the web app externally or in a view side-by-side to the editor area. -![Running app in the Gitpod workspace](https://cdn-images-1.medium.com/max/3200/0*psT2Ar8PKkWYVpKV)*Running app in the Gitpod workspace* +![Running app in the Gitpod workspace](https://cdn-images-1.medium.com/max/3200/0*psT2Ar8PKkWYVpKV)_Running app in the Gitpod workspace_ ## **Bonus Points** -Now you can start changing the application and of course committing to your repo. Also you should consider adding a *.gitpod* file to the root directory, so the build and dev server automatically startup next time you open a Gitpod workspace. +Now you can start changing the application and of course committing to your repo. Also you should consider adding a _.gitpod_ file to the root directory, so the build and dev server automatically startup next time you open a Gitpod workspace. Here’s the contents: diff --git a/src/blog/docker-in-gitpod.md b/src/blog/docker-in-gitpod.md index 1a79eb302..979d0812c 100644 --- a/src/blog/docker-in-gitpod.md +++ b/src/blog/docker-in-gitpod.md @@ -17,19 +17,19 @@ Of course, there is always room for improvement, especially with a service as ne And indeed that hasn’t been straight forward. You had to: -* create a Dockerfile on your machine +- create a Dockerfile on your machine -* build that Dockerfile on your machine +- build that Dockerfile on your machine -* push it to hub.docker.com (no account? Create one first!) +- push it to hub.docker.com (no account? Create one first!) -* create a branch in your project with a customized .gitpod.yml file which references that specific image +- create a branch in your project with a customized .gitpod.yml file which references that specific image -* visit *gitpod.io/#* +- visit _gitpod.io/#_ -* get no feedback except ‘Build has status FAILURE’… +- get no feedback except ‘Build has status FAILURE’… -* rinse and repeat from step 2 +- rinse and repeat from step 2 That was way too tedious for everyone to start playing around. @@ -64,18 +64,18 @@ tasks: cargo build cargo run ports: - - port: 8000 + - port: 8000 ``` It references the Dockerfile next to it, says that the resulting app should be accessible on port 8000 and contains the command executed on workspace startup: set config, start postgres, build and run app (I basically copied those from the repo’s .md file). The Dockerfile itself inherits from our default image [gitpod/workspace-full](https://hub.docker.com/r/gitpod/workspace-full/)¹ and contains: -* PostgreSQL (+ some configuration for the gitpod user) +- PostgreSQL (+ some configuration for the gitpod user) -* specific Rust toolchain +- specific Rust toolchain -* some project specific setup +- some project specific setup Here it is: @@ -122,13 +122,13 @@ Now whenever anyone accesses the repository through Gitpod, be it a branch, a pa Once the service has build and is running, we just follow the tutorial: -* Open /people: Click Open on the appearing messagebox² and change the path in the integrated browser to http://8000-/people , click Reload : The query results in an empty [] +- Open /people: Click Open on the appearing messagebox² and change the path in the integrated browser to http://8000-/people , click Reload : The query results in an empty [] -* Hit F1 -> "Open new Terminal" and paste: +- Hit F1 -> "Open new Terminal" and paste: - curl -XPOST [http://localhost:8000/people](http://localhost:8000/people) -H "Content-Type: application/json" --data '{"id": 123, "first_name": "Jon", "last_name": "Doe", "age": 64, "profession": "Engineer", "salary": 1024}' + curl -XPOST [http://localhost:8000/people](http://localhost:8000/people) -H "Content-Type: application/json" --data '{"id": 123, "first_name": "Jon", "last_name": "Doe", "age": 64, "profession": "Engineer", "salary": 1024}' -* Hit Reload again to see Jon Doe’s people entry +- Hit Reload again to see Jon Doe’s people entry ## Try it yourself diff --git a/src/blog/github-codespaces.md b/src/blog/github-codespaces.md index 37c05049a..8bad54aad 100644 --- a/src/blog/github-codespaces.md +++ b/src/blog/github-codespaces.md @@ -5,7 +5,8 @@ subtitle: A Milestone for Automated Development Environments title: GitHub Codespaces, Welcome to the Party! image: /gh-cs-bg.jpg --- -Today, GitHub announced the private beta of [GitHub Codespaces](https://github.com/features/codespaces), which provide container-based dev environments for GitHub projects. At Gitpod, we are building a similar solution, and while GitHub’s Codespaces don’t fully implement everything we do, they truly embrace the notion of dev environments as code. + +Today, GitHub announced the private beta of [GitHub Codespaces](https://github.com/features/codespaces), which provide container-based dev environments for GitHub projects. At Gitpod, we are building a similar solution, and while GitHub’s Codespaces don’t fully implement everything we do, they truly embrace the notion of dev environments as code. This is great news, because it really helps to explain why this is going to change professional software development entirely. @@ -15,9 +16,9 @@ Describing development environments in code has many benefits: - It eliminates onboarding friction: no matter if you are new to a project, need to go back to an old branch or just picking up development after a few weeks. Just go to your project and start coding immediately. -- Remote work becomes a breeze: now everyone can access source code more securely (no local copies) from any device, including Chromebooks and tablets. +- Remote work becomes a breeze: now everyone can access source code more securely (no local copies) from any device, including Chromebooks and tablets. -- Everybody gets the same setup: this means that “works on my machine” situations are a problem of the past. +- Everybody gets the same setup: this means that “works on my machine” situations are a problem of the past. - With Gitpod, you can even take snapshots of any state of your dev environment and share exact clones of it. @@ -29,7 +30,7 @@ As software systems become more complex so do dev environments. Have you ever tr When we started working on Gitpod, we had everything running locally in minikube, too. Very quickly we realized that this would not scale. Our SaaS offering is deployed in Kubernetes clusters across the globe—that’s nothing you’d want to replicate locally. -For the past year the whole team has developed Gitpod in Gitpod. Everyone in the team can start coding on any branch immediately. That includes their own preview deployment which is already connected to and fully debuggable from their browser-based development environment. For a more in-depth look at our development pipeline—and what’s in it for you—check out [Chris’ talk](https://www.youtube.com/watch?v=dFMpXUsJcGM) (inlined below) and our [previous post](https://www.freecodecamp.org/news/developing-kubernetes-applications-with-joy/) on the matter. +For the past year the whole team has developed Gitpod in Gitpod. Everyone in the team can start coding on any branch immediately. That includes their own preview deployment which is already connected to and fully debuggable from their browser-based development environment. For a more in-depth look at our development pipeline—and what’s in it for you—check out [Chris’ talk](https://www.youtube.com/watch?v=dFMpXUsJcGM) (inlined below) and our [previous post](https://www.freecodecamp.org/news/developing-kubernetes-applications-with-joy/) on the matter. `youtube: dFMpXUsJcGM` @@ -45,14 +46,13 @@ Given all these benefits, you might wonder why no one did this earlier. After al There have been attempts to automate dev environments in the past (e.g. Docker, Vagrant, Cloud9). These early approaches always came with too many compromises, and their benefits did not quite outweigh the drawbacks. The biggest blocker was that developers could no longer use the powerful tools they normally would, most importantly an awesome Editor/IDE. -This has changed since, with VS Code, a web-technology based IDE has become so popular among developers. However, Microsoft has not open-sourced the browser version of VS Code. For GitHub, a Microsoft-owned company, this is obviously not an issue. For everyone else we have developed Eclipse [Theia](https://dev.to/svenefftinge/theia-1-0-finally-a-good-browser-ide-3ok0). +This has changed since, with VS Code, a web-technology based IDE has become so popular among developers. However, Microsoft has not open-sourced the browser version of VS Code. For GitHub, a Microsoft-owned company, this is obviously not an issue. For everyone else we have developed Eclipse [Theia](https://dev.to/svenefftinge/theia-1-0-finally-a-good-browser-ide-3ok0). -Theia provides the same functionality as VS Code, even supports VS Code extensions, and comes with an architecture that allows everyone to customize the IDE easily. It is developed as a true open-source, vendor-neutral project at the Eclipse Foundation *) and is adopted by Google, IBM, RedHat, SAP, arm, Arduino and many more. Mike Milinkovich wrote about the [differences between Theia and VS Code](https://blogs.eclipse.org/post/mike-milinkovich/eclipse-theia-and-vs-code-differences-explained) recently. +Theia provides the same functionality as VS Code, even supports VS Code extensions, and comes with an architecture that allows everyone to customize the IDE easily. It is developed as a true open-source, vendor-neutral project at the Eclipse Foundation \*) and is adopted by Google, IBM, RedHat, SAP, arm, Arduino and many more. Mike Milinkovich wrote about the [differences between Theia and VS Code](https://blogs.eclipse.org/post/mike-milinkovich/eclipse-theia-and-vs-code-differences-explained) recently. This new generation of Theia-based Web-IDEs go way beyond online-playgrounds which are barely sufficient for web development or quick prototypes. Today, we can finally run a professional IDE in a browser tab. -*) To avoid misunderstandings: Theia has technically nothing in common with the classic Eclipse IDE, but is an independent project under the umbrella of the Eclipse Foundation. - +\*) To avoid misunderstandings: Theia has technically nothing in common with the classic Eclipse IDE, but is an independent project under the umbrella of the Eclipse Foundation. ### What About GitLab, Atlassian’s Bitbucket, and Other Git Hosting? @@ -66,15 +66,15 @@ To also serve users beyond just GitHub, we have been focussing on integrating Gi Chances are that you host your Git repositories or other dev infrastructure in a private cloud, or on a local network where they can't be accessed from the outside. Thus, a hosted IDE service must be on the same private cloud or network. This is possible with [Gitpod Self-Hosted](/self-hosted/) which can be installed on Kubernetes and does not require a connection to the public internet. -Today we are releasing a new version which brings Gitpod Self-Hosted on par with Gitpod.io. The new release includes better GitLab integration and a new admin UI. With Gitpod Self-Hosted you can now enjoy this liberating way of developing software with your own GitLab installation. +Today we are releasing a new version which brings Gitpod Self-Hosted on par with Gitpod.io. The new release includes better GitLab integration and a new admin UI. With Gitpod Self-Hosted you can now enjoy this liberating way of developing software with your own GitLab installation. **Gitpod Self-Hosted is free for up to five users, and a free trial month for unlimited users is available, too.** ### Summary -We are quickly headed into a wonderful future, where developers are no longer intimidated by tedious and outdated setup procedures. Professional software projects will provide automated, prebuilt development environments that enable teams to start contributing, doing code reviews, reproducing bugs or just exploring new ideas immediately from any device securely. +We are quickly headed into a wonderful future, where developers are no longer intimidated by tedious and outdated setup procedures. Professional software projects will provide automated, prebuilt development environments that enable teams to start contributing, doing code reviews, reproducing bugs or just exploring new ideas immediately from any device securely. -CI/CD has taught us how versioned, reproducible infrastructure as code is key to scale modern software development. Now it is time to apply these lessons to our development environments and furthermore improve our lead times getting from ideas to production. +CI/CD has taught us how versioned, reproducible infrastructure as code is key to scale modern software development. Now it is time to apply these lessons to our development environments and furthermore improve our lead times getting from ideas to production. Experience the future of software development now! diff --git a/src/blog/github-flow.md b/src/blog/github-flow.md index 3020e7591..5c68269a2 100644 --- a/src/blog/github-flow.md +++ b/src/blog/github-flow.md @@ -11,7 +11,7 @@ As software developers, we already spend a lot of our time in browsers. Be it fo However, when it comes to the actual coding and debugging, we have to prepare our local development environments manually. We do this based on often outdated, incomplete or just plain wrong documentation. The transition from an online repository to the actual coding is a barrier that hinders thousands of possible contributions every day. Coding needs to get more accessible. -![(Programming Environment - Dilbert by Scott Adams. Source: [http://dilbert.com/strip/2017-01-02)](http://dilbert.com/strip/2017-01-02))](https://cdn-images-1.medium.com/max/2048/0*f260tcqJvgvCguFu)*(Source: [http://dilbert.com/strip/2017-01-02)](http://dilbert.com/strip/2017-01-02))* +![(Programming Environment - Dilbert by Scott Adams. Source: [http://dilbert.com/strip/2017-01-02)](http://dilbert.com/strip/2017-01-02))](https://cdn-images-1.medium.com/max/2048/0*f260tcqJvgvCguFu)_(Source: [http://dilbert.com/strip/2017-01-02)](http://dilbert.com/strip/2017-01-02))_ But that only needs to be done once, right? Unfortunately, no. Coding is a team sport. We are not just adding code, but also do code reviews or fix bugs on maintenance branches which often require a different setup. Moreover, today’s applications are loosely coupled compositions of independent microservices and sub-projects, written in different languages requiring different development setups. Consequently, we have to maintain setups for multiple projects and branches, trying to keep documentation in sync including all the cases for the different platforms. As a result, we are wasting precious time every day. We should spend this time and effort on more fun and productive things. @@ -23,12 +23,13 @@ In this article, I will walk you through an automated, cloud-based development w Starting a workspace with Gitpod is much easier than with other cloud IDEs. Gitpod doesn’t require you to configure workspaces with container images, Git information and so on. Instead, you directly go to a GitHub repository and click the Gitpod-Button [see below]. Gitpod provides you with a ready to use workspace, so that you can immediately start coding without any configuration steps. -![Button provided by Gitpod’s browser extension](https://cdn-images-1.medium.com/max/3200/0*MjUIJ1zspz3CF8oo)*Button provided by Gitpod’s browser extension* +![Button provided by Gitpod’s browser extension](https://cdn-images-1.medium.com/max/3200/0*MjUIJ1zspz3CF8oo)_Button provided by Gitpod’s browser extension_ + > To see the Gitpod button on the GitHub page, you would have to [install a browser extension](https://gitpod.io). Alternatively, you can manually prefix any GitHub URL with `https://gitpod.io/#`. For instance, clicking the following link will instantly provide you a development workspace for the Eclipse Theia project: [https://gitpod.io/#https://github.com/theia-ide/theia](https://gitpod.io/#https://github.com/theia-ide/theia) Of course, different projects need different setups. Gitpod has a three-stage process to determine the workspace configuration, e.g. what docker image to use for development, what startup script to run, and which ports to expose: -1. It first looks for a *.gitpod* configuration file in the repository. Note, that it will check the state of the currently viewed commit. This allows you to keep working configuration for old states as well as trying a new configuration in a pull request. +1. It first looks for a _.gitpod_ configuration file in the repository. Note, that it will check the state of the currently viewed commit. This allows you to keep working configuration for old states as well as trying a new configuration in a pull request. 1. Second, if there is no configuration in the cloned repository, a central repository called ‘[definitely-gp](https://github.com/gitpod-io/definitely-gp)’ is checked for configuration. It is a public repository which contains configurations for arbitrary GitHub projects. That is useful if you want to provide configuration for a repository you don’t have write access to. Everybody is invited to contribute to this. @@ -44,7 +45,7 @@ Some great features, which are heavily used on GitHub, are issues and pull reque Lastly, of course, when clicking the Gitpod button on a pull request, Gitpod beams you right into code review mode. A panel on the left will list the changed files, allowing you to go through them one by one. Changes are opened in the diff editor where you can also read and add review comments. And because it is a full IDE, we can navigate through the entire code base, run code or add commits at will. Approving the pull request is supported, too. -![Inline code review comments](https://cdn-images-1.medium.com/max/3200/0*8N39dT5P6Q1zQdIR)*Inline code review comments* +![Inline code review comments](https://cdn-images-1.medium.com/max/3200/0*8N39dT5P6Q1zQdIR)_Inline code review comments_ **Theia IDE** diff --git a/src/blog/gitlab-support.md b/src/blog/gitlab-support.md index 7cfb336ee..abf464978 100644 --- a/src/blog/gitlab-support.md +++ b/src/blog/gitlab-support.md @@ -15,21 +15,25 @@ We are happy to announce that you can finally enjoy Gitpod's frictionless ready- Starting a dev environment for a GitLab project works just as with GitHub, i.e. you prefix any GitLab project URL with `gitpod.io/#`. You can try it out with the Spring PetClinic example: - https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic +https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic Besides the standard project URL, Gitpod supports - - opening file URLs -

Example: https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic/.../petclinic/PetClinicApplication.java

- - opening branches +- opening file URLs -

Example: https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic/tree/my-branch

- - opening issues +

Example: https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic/.../petclinic/PetClinicApplication.java

-

Example: https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic/issues/1

- - opening merge requests +- opening branches -

Example: https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic/merge_requests/1

+

Example: https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic/tree/my-branch

+ +- opening issues + +

Example: https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic/issues/1

+ +- opening merge requests + +

Example: https://gitpod.io/#https://gitlab.com/gitpod/spring-petclinic/merge_requests/1

Depending on the context, your dev environment will be initialized differently. @@ -53,7 +57,8 @@ There is much more you can do to make sure every team member gets a ready-to-cod Gitpod’s [prebuilt workspaces](/docs/prebuilds/) are key to providing ephemeral, ready-to-code dev environments for your branches and projects. You can configure Gitpod to run your project's build asynchronously every time someone pushes new commits or branches to your repository. So when a developer wants to start coding, she can, because everything is already prepared. Enabling prebuilds on your GitLab project is done by configuring a Webhook. But don't fear, you don't have to do that manually, just run a prebuild on your project and it will be configured automatically. To do that, use the prefix `https://gitpod.io/#prebuild/`, as in -> __https://gitpod.io/#prebuild/__`https://gitlab.com//` + +> **https://gitpod.io/#prebuild/**`https://gitlab.com//` ## We Need Your Feedback diff --git a/src/blog/gitpod-launch.md b/src/blog/gitpod-launch.md index ca25c4fb1..03abe6ce6 100644 --- a/src/blog/gitpod-launch.md +++ b/src/blog/gitpod-launch.md @@ -14,6 +14,7 @@ This friction is not only time consuming but is a serious barrier for contributo Today, we are happy to announce the launch of [Gitpod.io](https://gitpod.io), an online service that provides disposable, ready-to-code development environments for GitHub projects. ## One-Click Dev Environments for GitHub + Here's how Gitpod works: You are on GitHub and want to start working on a project. Instead of going through the manual setups, etc. you simply click a button to start a ready-to-code dev environment in your browser. You can now code, review, or just try out the project. Once you are done you simply close the tab. ![Gitpod button added by Gitpod browser extension](./gitpod-launch/browser-ext.png) @@ -23,11 +24,12 @@ Don’t see the button on GitHub yet? You need to [install a small browser exten You can try Gitpod right now. It's free for public repositories. ## No Setup -Not all projects are equal. We maintain a [developer friendly docker image](https://github.com/gitpod-io/workspace-images/blob/master/full/Dockerfile) that includes all the commonly used tools and version managers. But you can point to your own docker image in a __.gitpod.yml__ file. Gitpod will pick it up and even build the image if needed. Read [Gero's post](/blog/docker-in-gitpod/) for more details. -With Gitpod, contributors don’t need to go through a list of usually outdated setup instructions. Instead, they get exactly what they need for the project at hand with no additional effort. As a side-effect, any "works-on-my-machine" scenarios are eliminated, because every team member uses the same working setup on the same kind of machine in the cloud. Since the __.gitpod.yml__ is versioned with the code, going back to old releases and branches becomes super easy, too. We call this [dev environment as code](/blog/dev-env-as-code/). +Not all projects are equal. We maintain a [developer friendly docker image](https://github.com/gitpod-io/workspace-images/blob/master/full/Dockerfile) that includes all the commonly used tools and version managers. But you can point to your own docker image in a **.gitpod.yml** file. Gitpod will pick it up and even build the image if needed. Read [Gero's post](/blog/docker-in-gitpod/) for more details. + +With Gitpod, contributors don’t need to go through a list of usually outdated setup instructions. Instead, they get exactly what they need for the project at hand with no additional effort. As a side-effect, any "works-on-my-machine" scenarios are eliminated, because every team member uses the same working setup on the same kind of machine in the cloud. Since the **.gitpod.yml** is versioned with the code, going back to old releases and branches becomes super easy, too. We call this [dev environment as code](/blog/dev-env-as-code/). -To optimize the experience, the __.gitpod.yml__ accepts [further configuration](/docs/configuration/), where you can automatically start builds, watchers and dev servers in multiple terminals. You can configure how they appear in the IDE layout and hook up all your web ports and previews. +To optimize the experience, the **.gitpod.yml** accepts [further configuration](/docs/configuration/), where you can automatically start builds, watchers and dev servers in multiple terminals. You can configure how they appear in the IDE layout and hook up all your web ports and previews. As a project owner you should do everything you can to streamline the experience for contributors, so everybody including yourself can focus on being creative and writing code. Gitpod lets you automate the setup and make sure developers can access a dev environment that really is ready to code. @@ -36,6 +38,7 @@ A great example is [ssloy's tinyraytracer project](https://github.com/ssloy/tiny ![Tinyraytracer Gitpod workspace](./gitpod-launch/tinyrt.png) ## Less Waiting + There is an additional bit of friction that every developer has to go through regularly: Running the build and downloading dependencies. @@ -49,6 +52,7 @@ We call this feature prebuilt workspaces and you can read more about it in [Chri ![Prebuilt Workspaces](./gitpod-launch/prebuilt-workspaces.png) ## More Flow + Your dev environment opens differently depending on the GitHub page you are coming from. You can, for instance, open branches or files by simply going to the respective GitHub page and pressing the button (or prefixing the URL) there. When coming from an issue, Gitpod understands you want to fix it, so you’ll get a fresh local branch and the commit message is prepared with a reference to the issue. @@ -60,6 +64,7 @@ Even if you prefer your local machine for development, being able to do [deep co ![Inlined Code Review](./gitpod-launch/inline-comments.png) ## A Complete IDE Running in the Cloud + While Gitpod keeps the convenience and accessibility of online coding playgrounds and sandboxes, it is not a toy but a complete dev environment running in the cloud. We teamed-up with Google, Ericsson, Arm and Red Hat to develop the open-source project [Eclipse Theia](https://theia-ide.org). The project puts [VS Code](https://code.visualstudio.com/)’s state-of-the-art technology and UX into the browser based on an extensible architecture that is optimized for the cloud. @@ -69,10 +74,12 @@ Gitpod already comes with several VS Code extensions pre-installed (such as Go s In addition to one of the best code editors, Gitpod environments provide full featured terminals backed by Linux containers running in the cloud. As a result, you get the same command line tools you would use locally together with the hottest IDE tech available today. And all of that in a browser tab. ## Collaboration + Gitpod comes with two major features supporting collaboration. - - [Sharing running dev environments](/docs/sharing-and-collaboration/) with other users comes in handy if you want to look at code with a colleague to hunt down a bug together or do some pair programming. Collaborators will see the same code you see and even the terminals are synced and shared. - - [Snapshots](/blog/workspace-snapshots/) are useful in many ways. In a nutshell, they allow taking an immutable copy of your dev environment at any point in time. You can share the provided link wherever you want. Users opening such a snapshot link will get an exact clone of the environment including all state and even UI layout. This feature is great for sharing reproducibles in issues, but also good for blog posts or solutions on Stack Overflow. +- [Sharing running dev environments](/docs/sharing-and-collaboration/) with other users comes in handy if you want to look at code with a colleague to hunt down a bug together or do some pair programming. Collaborators will see the same code you see and even the terminals are synced and shared. + +- [Snapshots](/blog/workspace-snapshots/) are useful in many ways. In a nutshell, they allow taking an immutable copy of your dev environment at any point in time. You can share the provided link wherever you want. Users opening such a snapshot link will get an exact clone of the environment including all state and even UI layout. This feature is great for sharing reproducibles in issues, but also good for blog posts or solutions on Stack Overflow. ![Collaboration: Share Running Workspace or Snapshot](/gitpod-launch/collaboration.png) @@ -81,17 +88,19 @@ Gitpod comes with two major features supporting collaboration. An important part of leaving the beta was to find a good pricing model that addresses the needs for the various user groups. We think we have found a good balance by providing the following individual subscription options: - - a **free 100-hour per month plan** for open-source development - - a **paid 100-hour per month plan** for individuals working privately - - a **paid unlimited plan** for professional use - _(I know some of you are lucky enough to do professional open-source. Decide what works best for you in that case ;-))_ +- a **free 100-hour per month plan** for open-source development +- a **paid 100-hour per month plan** for individuals working privately +- a **paid unlimited plan** for professional use + +_(I know some of you are lucky enough to do professional open-source. Decide what works best for you in that case ;-))_ We also offer **team subscriptions**, which allow managers to buy a batch of seats and assign them to the team. And, of course, a special **students discount** is in store, eligible if your primary GitHub URL belongs to an educational institution. ## Thank You ❤️ + I want to take the opportunity to thank all the people who have helped to make Gitpod a reality: all the [enthusiastic](https://twitter.com/JeremyJaydan/status/1096742668137246721) [early](https://twitter.com/RalfDMueller/status/1054079167841660928) [adopters](https://twitter.com/doppelganger9/status/1088926330857680896) who provided [great feedback](https://github.com/gitpod-io/gitpod/issues) during the beta phase; contributors who have helped by identifying bugs and by sharing their use cases; and of course the [Eclipse Theia community](https://github.com/theia-ide/theia/graphs/contributors) working with passion on an open-source IDE platform for the future. Furthermore, I want to thank Michael Bernstein from [Reify](https://www.reifyworks.com/) for clarifying our messaging with us and Kelly Fitzpatrick and the rest of the [Redmonk](https://redmonk.com/) team for their guidance and helpful feedback. diff --git a/src/blog/gitpod-online-ide.md b/src/blog/gitpod-online-ide.md index 0b7b9c47c..8cc77691e 100644 --- a/src/blog/gitpod-online-ide.md +++ b/src/blog/gitpod-online-ide.md @@ -9,7 +9,7 @@ image: https://cdn-images-1.medium.com/max/6908/1*HNDYawJpDgX6gP_e0w17mg.png After over one year of intensive work, we are proud to announce the public Beta of Gitpod. -Gitpod is an online IDE which can be launched from any GitHub page. Simply **prefix any GitHub-URL with “*https://gitpod.io/#*”** or use our [browser extension](https://chrome.google.com/webstore/detail/gitpod-online-ide/dodmmooeoklaejobgleioelladacbeki?hl=en) that adds a button to GitHub pages. +Gitpod is an online IDE which can be launched from any GitHub page. Simply **prefix any GitHub-URL with “_https://gitpod.io/#_”** or use our [browser extension](https://chrome.google.com/webstore/detail/gitpod-online-ide/dodmmooeoklaejobgleioelladacbeki?hl=en) that adds a button to GitHub pages. Within seconds, Gitpod provides you with a fully working development environment, including a VS Code-powered IDE and a cloud-based Linux container configured specifically for the project at hand. @@ -35,7 +35,7 @@ Starting a Gitpod workspace from an issue will automatically create a branch and Once you are in the IDE, you can interact with GitHub in various ways. Besides the obvious Git integration, you can do things like **commenting inline in editors, approving and even merging PRs**. -![Inline Comments For Pull Requests](https://cdn-images-1.medium.com/max/6908/1*HNDYawJpDgX6gP_e0w17mg.png)*Inline Comments For Pull Requests* +![Inline Comments For Pull Requests](https://cdn-images-1.medium.com/max/6908/1*HNDYawJpDgX6gP_e0w17mg.png)_Inline Comments For Pull Requests_ ## **Automated Setup** @@ -61,13 +61,13 @@ Gitpod gives developers full featured terminals to run any processes such as com The IDE in Gitpod is based on [Theia](http://theia-ide.org), an open-source project that we ([TypeFox](https://www.typefox.io/)) have started together with our friends from Ericsson in early 2017. You can think of it as **the online version of VS Code**. We love VS Code, but needed some additional properties, like a more extensible architecture and the ability to run in browsers connected to a remote backend. Theia is a true open-source project, hosted at the Eclipse Foundation and developed by a diverse crowd of engineers backed by TypeFox, Ericsson, Red Hat, Arm and others. -![Language Tooling In Action](https://cdn-images-1.medium.com/max/6796/1*5DnbR6-FbyVQ8ILgFHJXOw.png)*Language Tooling In Action* +![Language Tooling In Action](https://cdn-images-1.medium.com/max/6796/1*5DnbR6-FbyVQ8ILgFHJXOw.png)_Language Tooling In Action_ ## **Supports Many Languages** Being based on VS Code and its Language Server Protocol, Theia supports most major programming languages. The table below provides a good overview of the current state. -![Current State of Supported Programming Languages](https://cdn-images-1.medium.com/max/4712/1*BshL6_wwY2XYRDKSMYiSDg.png)*Current State of Supported Programming Languages* +![Current State of Supported Programming Languages](https://cdn-images-1.medium.com/max/4712/1*BshL6_wwY2XYRDKSMYiSDg.png)_Current State of Supported Programming Languages_ Additional languages like **C#, Swift, Clojure, Groovy, Objective-C, Markdown, Less, XML and many others** are supported with syntax coloring, as well. Because it is so easy to create an extension for Theia, support will improve both in breadth (more languages) and depth, shortly. @@ -77,23 +77,23 @@ You can use Gitpod with any GitHub repository. The login is done through GitHub Why not try it now? If you don’t have a particular repository in mind, you can pick one of the below: -* **JavaScript**: -[https://gitpod.io/#**https://github.com/ooade/NextSimpleStarter**](https://gitpod.io/#https://github.com/ooade/NextSimpleStarter) +- **JavaScript**: + [https://gitpod.io/#**https://github.com/ooade/NextSimpleStarter**](https://gitpod.io/#https://github.com/ooade/NextSimpleStarter) -* **Go**: -[https://gitpod.io/#**https://github.com/demo-apps/go-gin-app**](https://gitpod.io/#https://github.com/demo-apps/go-gin-app) +- **Go**: + [https://gitpod.io/#**https://github.com/demo-apps/go-gin-app**](https://gitpod.io/#https://github.com/demo-apps/go-gin-app) -* **Java**: -[https://gitpod.io/#**https://github.com/gitpod-io/spring-petclinic**](https://gitpod.io/#https://github.com/gitpod-io/spring-petclinic) +- **Java**: + [https://gitpod.io/#**https://github.com/gitpod-io/spring-petclinic**](https://gitpod.io/#https://github.com/gitpod-io/spring-petclinic) -* **Ruby**: -[https://gitpod.io/#**https://github.com/gitpod-io/rails\_sample\_app**](https://gitpod.io/#https://github.com/gitpod-io/rails_sample_app) +- **Ruby**: + [https://gitpod.io/#**https://github.com/gitpod-io/rails_sample_app**](https://gitpod.io/#https://github.com/gitpod-io/rails_sample_app) -* **Python**: -[https://gitpod.io/#**https://github.com/sibtc/django-beginners-guide**](https://gitpod.io/#https://github.com/sibtc/django-beginners-guide) +- **Python**: + [https://gitpod.io/#**https://github.com/sibtc/django-beginners-guide**](https://gitpod.io/#https://github.com/sibtc/django-beginners-guide) -* **PHP**: -[https://gitpod.io/#**https://github.com/symfony/demo**](https://gitpod.io/#https://github.com/symfony/demo) +- **PHP**: + [https://gitpod.io/#**https://github.com/symfony/demo**](https://gitpod.io/#https://github.com/symfony/demo) ## **Where Are We Going From Here?** diff --git a/src/blog/gitpod-self-hosted-0.4.0.md b/src/blog/gitpod-self-hosted-0.4.0.md index da4ffdd1f..bfd4314dc 100644 --- a/src/blog/gitpod-self-hosted-0.4.0.md +++ b/src/blog/gitpod-self-hosted-0.4.0.md @@ -6,7 +6,8 @@ title: Gitpod Self-Hosted 0.4.0 image: /cloud-download.png teaserImage: /cloud-download.png --- -We are excited to announce the new release of Gitpod Self-Hosted in version 0.4.0. Gitpod Self-Hosted allows everyone to set-up and run a service with the same features as gitpod.io in your cloud or corporate network. + +We are excited to announce the new release of Gitpod Self-Hosted in version 0.4.0. Gitpod Self-Hosted allows everyone to set-up and run a service with the same features as gitpod.io in your cloud or corporate network. ### How Does it Work? @@ -18,12 +19,12 @@ Gitpod Self-Hosted is truly self-hosted: it does not require an internet connect Operating Gitpod in production on gitpod.io has enabled us to battle-harden this product at scale. Both offerings share the same codebase, hence offer the same qualities regarding scalability, cloud-density, reliability, and security. All improvements that we make on Gitpod’s SaaS offering directly benefit the self-hosted version. -This release ships a plethora of bugfixes and improvements, particularly in the area of GitLab integration. +This release ships a plethora of bugfixes and improvements, particularly in the area of GitLab integration. There is one major feature that I want to show in more detail since you can't try this on gitpod.io: ### New Admin UI -This release ships with a new web UI for administrative tasks. The UI is particularly handy when providing support fo users. +This release ships with a new web UI for administrative tasks. The UI is particularly handy when providing support fo users. It allows for easy listing and searching of users and worksapces. When selecting a user, the UI will show the user's details and workspaces, as you can in the following screenshot: diff --git a/src/blog/gitpodify.md b/src/blog/gitpodify.md index cf54bc278..c78ab8a13 100644 --- a/src/blog/gitpodify.md +++ b/src/blog/gitpodify.md @@ -17,11 +17,11 @@ What if there was a better way to do this? Maybe one day we can all just forget
-|
 
| The idea in brief | -| --- | --- | -|   The problem | Figuring out which dependencies, tools, and language versions to install to properly configure a dev environment takes a lot of time and energy, and has to be repeated from scratch every time you use a different computer, and for every new project. | -|   The cause | Most setup instructions are written in a format that is not executable or reproducible, like plain text in markdown files. | -|   The solution | To solve this problem for every developer of your project, setup instructions should be written in a format that is executable, like scripts and Dockerfiles, and ideally versioned and shipped with your code. Gitpod was invented to make this easy. | +|
 
| The idea in brief | +| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|   The problem | Figuring out which dependencies, tools, and language versions to install to properly configure a dev environment takes a lot of time and energy, and has to be repeated from scratch every time you use a different computer, and for every new project. | +|   The cause | Most setup instructions are written in a format that is not executable or reproducible, like plain text in markdown files. | +|   The solution | To solve this problem for every developer of your project, setup instructions should be written in a format that is executable, like scripts and Dockerfiles, and ideally versioned and shipped with your code. Gitpod was invented to make this easy. | ## Introducing Gitpod @@ -34,6 +34,7 @@ The first thing you'll probably want to do is try opening your repository in Git ```bash gitpod.io/#https://github.com/gitpod-io/website ``` +
When you see the IDE and Terminal, just try building and running your project as usual. Maybe it will just work out of the box, but maybe you'll notice that something is missing or broken, and you can iterate on your Gitpod setup to fix it (see table of contents below). @@ -43,6 +44,7 @@ Once you're happy with your automated setup, a cool way to guide your contributo ```markdown [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/...) ``` + [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/gitpod-io/website) Happy with your onboarding experience? Great! You're all set. 🎉 @@ -80,6 +82,7 @@ tasks: command: npm run server - command: npm run client ``` +
But this example probably won't work, because `npm run client` likely also needs dependencies from `npm install`, so you might get an error like this in your second Terminal: @@ -144,6 +147,7 @@ The solution is to write a small Dockerfile for your project. If a particular `t image: file: .gitpod.dockerfile ``` +
Then add a new file called `.gitpod.dockerfile` at the root of your repository, containing: @@ -156,6 +160,7 @@ RUN sudo apt-get update \ tool \ && sudo rm -rf /var/lib/apt/lists/* ``` +
From now on, every new Gitpod workspace that will be opened for your repository will come with `tool` pre-installed. Cool right? @@ -173,6 +178,7 @@ Simply base your `.gitpod.dockerfile` on: ```Dockerfile FROM gitpod/workspace-postgres ``` +
This will give you an auto-starting PostgreSQL server (it should auto-start every time you open a new Terminal), plus a few utility scripts that you can run in a Terminal or in a [`.gitpod.yml`](#running-init-scripts) command: @@ -198,6 +204,7 @@ If your project needs MySQL to work, we also have a dedicated [MySQL image](http ```Dockerfile FROM gitpod/workspace-mysql ``` +
Then you'll get an auto-starting MySQL server, and you can use the `mysql` CLI like so: @@ -219,6 +226,7 @@ RUN sudo apt-get update \ redis-server \ && sudo rm -rf /var/lib/apt/lists/* ``` +
Then, you'll be able to start the Redis server by running this in a Terminal or in a `.gitpod.yml` command: @@ -236,6 +244,7 @@ Simply base your `.gitpod.dockerfile` on: ```Dockerfile FROM gitpod/workspace-mongodb ``` +
Then start the MongoDB server by running this in a Terminal or in a `.gitpod.yml` command: @@ -261,6 +270,7 @@ Simply base your `.gitpod.dockerfile` on: ```Dockerfile FROM gitpod/workspace-full-vnc ``` +
This will give you a virtual X server and a Remote Desktop client running on port `6080`: @@ -280,6 +290,7 @@ RUN sudo apt-get update \ libnss3-dev \ && sudo rm -rf /var/lib/apt/lists/* ``` +
To learn more, please see our dedicated post on [Developing native UI applications in Gitpod](/blog/native-ui-with-vnc/). @@ -301,6 +312,7 @@ ports: - port: 9000-9999 onOpen: ignore ``` +
Another way to open web previews is to run `gp preview ` in a Terminal or in your [`.gitpod.yml`](#running-init-scripts) commands. This can be used in combination with `gp url ` to open a web preview for a given port, like so: @@ -310,6 +322,7 @@ tasks: - command: python3 -m http.server 8080 - command: gp preview $(gp url 8080) ``` +
However, if the preview opens too soon, you might see an error like this: @@ -324,6 +337,7 @@ tasks: command: npm run server 3000 - command: gp await-port 3000 && gp preview $(gp url 3000) ``` +
If the `Port X didn't respond` error persists, please double-check in the Terminal output that your server is actually running on that port, then refresh the Preview pane. (Or, if it's a Browser tab, please close it and re-open it from the IDE's "Open Ports" view — refresh isn't currently supported for Browser preview tabs). @@ -356,6 +370,7 @@ devServer: { disableHostCheck: true, }, ``` +
Alternatively, if you don't want to use `disableHostCheck`, you can also add `'.gitpod.io'` to your `allowedHosts`, like so: @@ -366,6 +381,7 @@ devServer: { allowedHosts: ['localhost', '.gitpod.io'], }, ``` +
See all `webpack-dev-server` configuration options [here](https://webpack.js.org/configuration/dev-server/). @@ -424,6 +440,7 @@ And then point `ng serve` to that file using the `--proxy-config` parameter: ```bash ng serve --proxy-config proxy.config.json --host 0.0.0.0 --disable-host-check --port 3000 ``` +
For a complete example using PostgreSQL, Angular CLI, disableHostCheck, and a backend proxy, please check out the [PeerTube](https://joinpeertube.org/) project ([.gitpod.yml](https://github.com/Chocobozzz/PeerTube/blob/develop/.gitpod.yml), [Dockerfile](https://github.com/Chocobozzz/PeerTube/blob/develop/support/docker/gitpod/Dockerfile), [proxy.config.json](https://github.com/Chocobozzz/PeerTube/blob/develop/client/proxy.config.json), [ng serve command](https://github.com/Chocobozzz/PeerTube/blob/master/scripts/watch/client.sh)). @@ -442,7 +459,7 @@ More and more projects are using headless Chrome as a dependency (e.g. via [Pupp In this case, you'll want to use Chrome's `--no-sandbox` and/or `--disable-setuid-sandbox` flags. With Puppeteer, it may look like this: ```js -const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']}); +const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] }) ``` ## Setting env variables diff --git a/src/blog/local-services-in-gitpod.md b/src/blog/local-services-in-gitpod.md index b65084986..4b39389e3 100644 --- a/src/blog/local-services-in-gitpod.md +++ b/src/blog/local-services-in-gitpod.md @@ -17,26 +17,30 @@ On top of that, they do incur additional cost if used often. ![Inlets to the Rescue](local-services-in-gitpod/concept.png) [Inlets](https://github.com/inlets/inlets) is a great piece of kit written by [Alex Ellis](https://twitter.com/alexellisuk) which is basically the Open-Source version of the services mentioned above. + > Of course you can [contribute to inlets](https://github.com/inlets/inlets#development) itself using Gitpod. It consists of a server which would run in your workspace, and a client which would run on your local machine. The client then acts as a kind of reverse proxy into your local network opening it up to programs running in your Gitpod workspace. Making this work involves running both, the server and client: + 1. download and run inlets in your workspace: - ``` - curl -sLS https://get.inlets.dev | sh - export token=$(head -c 16 /dev/urandom | shasum | cut -d" " -f1) - echo "token: $token" - echo "remote: $(gp url 8090 | sed -e 's/https/wss/')" - ./inlets server --port 8080 --control-port=8090 --token="$token" - ``` - Gitpod will show you notifications that there are new services on the ports `8080` and `8090`. Expose the port `8090` and leave the other one as is. +``` +curl -sLS https://get.inlets.dev | sh +export token=$(head -c 16 /dev/urandom | shasum | cut -d" " -f1) +echo "token: $token" +echo "remote: $(gp url 8090 | sed -e 's/https/wss/')" +./inlets server --port 8080 --control-port=8090 --token="$token" +``` + +Gitpod will show you notifications that there are new services on the ports `8080` and `8090`. Expose the port `8090` and leave the other one as is. 2. run the inlets client on your local machine. The remote address and token are printed by the commands executed in step one. - ``` - inlets client --remote= --token= --upstream= - ``` + +``` +inlets client --remote= --token= --upstream= +``` There's a lot going on there, so let's look at things in detail. In the workspace we first download `inlets` using its shell installer (we could have used `brew install inlets`, too, but that's a tad slower). Then we produce a token which prevents unauthorized access to our inlets server. Note that without tokens, the handshake performed by the inlets client and server fails. @@ -47,10 +51,11 @@ On the client side (where I just assumed you already have [inlets installed](htt What you choose as `--upstream` depends on which kind of service you want to expose. Suppose you had a webserver running on port 8080 (e.g. `curl lama.sh | sh`), then this would be `--upstream localhost:8080`. ## Example 1: your local Docker daemon + Running a container engine like Docker or `containerd` in a Gitpod workspace is still [work-in-progress](https://github.com/gitpod-io/gitpod/issues/755). Until that's possible your only recurse is to connect to a remote daemon. Usually that daemon would run somewhere in the cloud, too, e.g. in your dev-cluster. However, some of us don't have a Kubernetes cluster laying around or just need access to docker to try something real quick. -> This is *not* how we plan to ultimatively support Docker/other containers in a Gitpod workspace. +> This is _not_ how we plan to ultimatively support Docker/other containers in a Gitpod workspace. Using inlets you can make the Docker enging running on your local machine (or in your local network) available in your Gitpod workspace. @@ -73,5 +78,6 @@ Inlets does not [support tunneling TCP](https://github.com/inlets/inlets-pro-pkg By combining the two, you can have programs in your workspace talk to TCP services in your local network/on your machine. ## Wrapping up + This day and age it's rare enough to find a situation where the service you want to talk to isn't available on the Internet (outside of corporate policy, that is). If you do find yourself in that situation however, that's no reason to relinquish the convenience and benefits of Gitpod. diff --git a/src/blog/native-ui-with-vnc.md b/src/blog/native-ui-with-vnc.md index b2dcbd817..51500c514 100644 --- a/src/blog/native-ui-with-vnc.md +++ b/src/blog/native-ui-with-vnc.md @@ -24,7 +24,7 @@ Let’s use Gitpod to write [a simple desktop-native application in Go](https:// This Dockerfile uses the gitpod/workspace-full-vnc image which sports the setup necessary to run X11 and VNC in Gitpod. It runs a [web-based VNC viewer](https://novnc.com) on port 6080 — during startup, Gitpod will ask you if you want to open this page. -![The Hello World UI example running in Gitpod](https://cdn-images-1.medium.com/max/6720/1*8xUjJfd3pV0QXyK-ytyhwA.png)*The Hello World UI example running in Gitpod* +![The Hello World UI example running in Gitpod](https://cdn-images-1.medium.com/max/6720/1*8xUjJfd3pV0QXyK-ytyhwA.png)_The Hello World UI example running in Gitpod_ ## Native UI in Gitpod = X11 + VNC diff --git a/src/blog/node-js-development.md b/src/blog/node-js-development.md index ed2ce5dc1..97bcaa569 100644 --- a/src/blog/node-js-development.md +++ b/src/blog/node-js-development.md @@ -17,17 +17,17 @@ The dev environment is called [Gitpod](https://www.gitpod.io/) and is entirely f ### Table of Contents -* [Hello World](#hello-world) +- [Hello World](#hello-world) -* [Automating Node.js setup](#automating-nodejs-setup) +- [Automating Node.js setup](#automating-nodejs-setup) -* [Working with Pull Requests](#working-with-pull-requests) +- [Working with Pull Requests](#working-with-pull-requests) -* [Working Together](#working-together) +- [Working Together](#working-together) -* [Developing full-stack Node.js applications](#developing-full-stack-nodejs-applications) +- [Developing full-stack Node.js applications](#developing-full-stack-nodejs-applications) -* [Summary](#summary) +- [Summary](#summary) ## Hello World @@ -37,9 +37,9 @@ Let’s get started by developing a simple “Hello World” application and lea Gitpod treats any GitHub repository as a project which can be opened. Let’s start by creating a new repository for our Hello World project: -* open your GitHub dashboard and select New Repository; +- open your GitHub dashboard and select New Repository; -* enter a repository name and click Create repository. +- enter a repository name and click Create repository. Now, we can open the created project in Gitpod. You can do it by simply prefixing the repository URL with gitpod.io/#. For example, I’ve called my repository node-hello-world and it can be opened in Gitpod with **gitpod.io/#**https://github.com/akosyakov/node-hello-world. @@ -51,21 +51,21 @@ Gitpod starts a new workspace, which is a Linux-based cloud container, and provi ![How to create a new project on GitHub and then open it in Gitpod](https://cdn-images-1.medium.com/max/2608/1*mXM-VDzzmpXCvlAVvQIjVw.gif) -*If you don’t want to create a new project from scratch, click on [a snapshot link](https://gitpod.io/#snapshot/0d82ae08-c328-4cb5-96e5-7233d5de0c11) of my workspace to try Hello World application. I will cover later how one can make a workspace snapshot.* +_If you don’t want to create a new project from scratch, click on [a snapshot link](https://gitpod.io/#snapshot/0d82ae08-c328-4cb5-96e5-7233d5de0c11) of my workspace to try Hello World application. I will cover later how one can make a workspace snapshot._ ### Writing a Node.js application By default, each workspace is preconfigured with standard tools like Node.js, npm, yarn and nvm. Later we will learn how to change the Node.js setup. Now, let’s code something and run it: -* open the command palette (F1) and select New File command; +- open the command palette (F1) and select New File command; -* create a new file with app.js name and type the following content: +- create a new file with app.js name and type the following content: - const message = 'Hello World'; + const message = 'Hello World'; - console.log(message, 'from Gitpod!'); + console.log(message, 'from Gitpod!'); -![As you type, you can see that Gitpod validates your code. It also provides you with smart completions and documentation on hover.](https://cdn-images-1.medium.com/max/2612/0*b-63v0Asfa09vfzG)*As you type, you can see that Gitpod validates your code. It also provides you with smart completions and documentation on hover.* +![As you type, you can see that Gitpod validates your code. It also provides you with smart completions and documentation on hover.](https://cdn-images-1.medium.com/max/2612/0*b-63v0Asfa09vfzG)_As you type, you can see that Gitpod validates your code. It also provides you with smart completions and documentation on hover._ ### Run / Debug a Node.js application @@ -77,13 +77,13 @@ Of course, you can have more than one terminal to your cloud workspace. Next up, let’s see how we can debug the application: -* create a debug configuration (Debug-> Add Configuration) and select Node.js: Launch Program configuration snippet in the content assist of the opened editor; +- create a debug configuration (Debug-> Add Configuration) and select Node.js: Launch Program configuration snippet in the content assist of the opened editor; -* add a breakpoint into app.js file, by clicking on the gutter on the left; +- add a breakpoint into app.js file, by clicking on the gutter on the left; -* open the Debug View (View -> Debug), +- open the Debug View (View -> Debug), -* press the green play icon to start debugging (or press F5). +- press the green play icon to start debugging (or press F5). Our program should run, and when a breakpoint hits you can inspect call stack, variables and even use the debug console to evaluate expressions. @@ -135,7 +135,7 @@ And change the Dockerfile to use Node.js 10.x as the base image: To try it our we need to push the config back to GitHub and open a new workspace. Let’s do this through a pull request, so we learn about the GitHub integration on the way. -*Here is [another snapshot link](https://gitpod.io/#snapshot/ea0d6704-a513-4c94-b8e7-fe72c3d8e5fb) to try our configuration without opening a pull request. You can learn more about workspace configuration [here](https://www.gitpod.io/docs/configuration/).* +_Here is [another snapshot link](https://gitpod.io/#snapshot/ea0d6704-a513-4c94-b8e7-fe72c3d8e5fb) to try our configuration without opening a pull request. You can learn more about workspace configuration [here](https://www.gitpod.io/docs/configuration/)._ ## Working with Pull Requests @@ -145,13 +145,13 @@ Gitpod provides seamless integration with GitHub features like creating and revi Let’s open a new pull request from Gitpod: -* commit your changes using the Git view (see above); +- commit your changes using the Git view (see above); -* use Git: Checkout command or click the branch item in the status bar to create a new branch. Name it somehow, e.g. gitpodify; +- use Git: Checkout command or click the branch item in the status bar to create a new branch. Name it somehow, e.g. gitpodify; -* next up open the Pull Request view on the right. You cannot create a new pull request yet, because first the new branch should be published to GitHub, click publish changes; +- next up open the Pull Request view on the right. You cannot create a new pull request yet, because first the new branch should be published to GitHub, click publish changes; -* after that, the Pull Request view will be updated and you can open a new pull request. +- after that, the Pull Request view will be updated and you can open a new pull request. ![How to make a PR in Gitpod](https://cdn-images-1.medium.com/max/2608/0*vHysVOgVJaH6-j1t) @@ -161,7 +161,7 @@ As I’ve mentioned at the beginning Gitpod treats each GitHub repository as a p Let’s go to the pull request page on GitHub and prefix its URL with gitpod.io/#, just like we did initially: -![How to open a Gitpod workspace from a PR page on GitHub](https://cdn-images-1.medium.com/max/2608/0*YXS_V_quV3Lg7Y-X)*Opening a PR with new workspace image can take some time since Gitpod needs to build the image. But it is only rebuilt when changed.* +![How to open a Gitpod workspace from a PR page on GitHub](https://cdn-images-1.medium.com/max/2608/0*YXS_V_quV3Lg7Y-X)_Opening a PR with new workspace image can take some time since Gitpod needs to build the image. But it is only rebuilt when changed._ As you can see, Gitpod opens with a branch for your pull request. PR file changes are presented on the left sidebar to review. Our init and command workspace tasks are executed in terminals, Node.js is 10.x now, and Hello World is printed. @@ -179,7 +179,7 @@ You can share your running workspaces with colleagues to collaborate on exactly In order to share a running workspace: click on your account avatar, select Share Running Workspace, enable sharing, copy a link and share the copied link with your colleagues. -![How to share a running Gitpod workspace](https://cdn-images-1.medium.com/max/2608/0*yp7USviOYhUm_P40)*Both users use exactly the same workspace and see the shared output in terminals.* +![How to share a running Gitpod workspace](https://cdn-images-1.medium.com/max/2608/0*yp7USviOYhUm_P40)_Both users use exactly the same workspace and see the shared output in terminals._ ### Showcasing Node.js applications @@ -187,17 +187,17 @@ You can take a complete snapshot (clone) of your workspace, even including your In order to share a workspace snapshot: click on your account avatar, select Share Workspace Snapshot, copy a link and share the copied link where you want. -![How to share a Gitpod workspace Snapshot](https://cdn-images-1.medium.com/max/2608/0*-n2I6-4fPuKK70_5)*The [shared workspace snapshot](https://gitpod.io/#snapshot/14dc69f1-0e8c-4a36-b221-0ab16e91326e) preserves not only the development setup but the IDE layout and even selection in the editor.* +![How to share a Gitpod workspace Snapshot](https://cdn-images-1.medium.com/max/2608/0*-n2I6-4fPuKK70_5)_The [shared workspace snapshot](https://gitpod.io/#snapshot/14dc69f1-0e8c-4a36-b221-0ab16e91326e) preserves not only the development setup but the IDE layout and even selection in the editor._ ## Developing full-stack Node.js applications So far, we’ve only had a look at a simple Node.js application. In case you wonder whether it will scale to sophisticated applications you can try any of the following repositories: -* [Node.js Shopping Cart](https://github.com/gitpod-io/nodejs-shopping-cart) is a reference Node.js application demonstrating how to use the Express framework. You can open it in Gitpod with [one-click](https://gitpod.io/#https://github.com/gitpod-io/nodejs-shopping-cart) and follow along [this blog post](https://medium.com/gitpod/debugging-node-js-applications-in-theia-76c94c76f0a1) explaining in details how to debug the app. +- [Node.js Shopping Cart](https://github.com/gitpod-io/nodejs-shopping-cart) is a reference Node.js application demonstrating how to use the Express framework. You can open it in Gitpod with [one-click](https://gitpod.io/#https://github.com/gitpod-io/nodejs-shopping-cart) and follow along [this blog post](https://medium.com/gitpod/debugging-node-js-applications-in-theia-76c94c76f0a1) explaining in details how to debug the app. -* Gitpod is based on an open-source IDE framework — [Theia](http://theia-ide.org). It’s built with a lot of JS technologies, including Node.js, Express, TypeScript and React. And, of course, [Gitpod is used to develop Theia](https://github.com/theia-ide/theia/blob/master/doc/Developing.md#run-the-browser-example-with-gitpod). +- Gitpod is based on an open-source IDE framework — [Theia](http://theia-ide.org). It’s built with a lot of JS technologies, including Node.js, Express, TypeScript and React. And, of course, [Gitpod is used to develop Theia](https://github.com/theia-ide/theia/blob/master/doc/Developing.md#run-the-browser-example-with-gitpod). -* You even can develop Electron applications in Gitpod, like VS Code. Chris demonstrates it in [this blog post](https://medium.com/gitpod/developing-native-ui-applications-in-gitpod-15af2967c24e). +- You even can develop Electron applications in Gitpod, like VS Code. Chris demonstrates it in [this blog post](https://medium.com/gitpod/developing-native-ui-applications-in-gitpod-15af2967c24e). ## Summary diff --git a/src/blog/node-js-gitpod.md b/src/blog/node-js-gitpod.md index ae06425d0..c4464cfc7 100644 --- a/src/blog/node-js-gitpod.md +++ b/src/blog/node-js-gitpod.md @@ -54,7 +54,7 @@ First, we need to add a breakpoint to the routing logic. It is defined in routes Next, add a breakpoint in the editor margin against a line which you want to debug. A route callback handling / path looks promising. -![Debugging: Breakpoints](https://cdn-images-1.medium.com/max/2988/1*AaqYqH5LILFw4g0-jNu5Bg.png)*Breakpoints are displayed in the debug view and applied to currently running sessions.* +![Debugging: Breakpoints](https://cdn-images-1.medium.com/max/2988/1*AaqYqH5LILFw4g0-jNu5Bg.png)_Breakpoints are displayed in the debug view and applied to currently running sessions._ Now, in the app, try navigating to the homepage. The debug session will pause on the breakpoint. You can traverse the current stack trace, inspect variables and control the execution flow with the debug actions toolbar: @@ -64,11 +64,11 @@ Now, in the app, try navigating to the homepage. The debug session will pause on There are several ways to see variables’ values: -* you can traverse current scopes and variables in the debug view; +- you can traverse current scopes and variables in the debug view; -* you can hover over expressions in the editor to evaluate them with a current session; +- you can hover over expressions in the editor to evaluate them with a current session; -* or you can use the debug console (REPL) to evaluate custom expressions. +- or you can use the debug console (REPL) to evaluate custom expressions. You can always double-click on any variable to modify its value. diff --git a/src/blog/october-2018-release.md b/src/blog/october-2018-release.md index 739e027e6..8cf465828 100644 --- a/src/blog/october-2018-release.md +++ b/src/blog/october-2018-release.md @@ -14,7 +14,7 @@ Please keep sending all that useful feedback! Today, we are pleased to announce a new version of [Gitpod](https://www.gitpod.io). -![A Cake with Sparkles Photo by [Audrey Fretz](https://unsplash.com/@parkstreet?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://cdn-images-1.medium.com/max/10944/0*TrpIB26qJjpdoAmh)*Photo by [Audrey Fretz](https://unsplash.com/@parkstreet?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)* +![A Cake with Sparkles Photo by [Audrey Fretz](https://unsplash.com/@parkstreet?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://cdn-images-1.medium.com/max/10944/0*TrpIB26qJjpdoAmh)_Photo by [Audrey Fretz](https://unsplash.com/@parkstreet?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)_ Here are the most important new features and improvements: @@ -27,9 +27,9 @@ To allow you using Gitpod as much as you want, during the beta you can now ## Docker File Support ⚙️ -Most projects need special tools, which can be provided by naming a custom Docker image in your *.gitpod* file. +Most projects need special tools, which can be provided by naming a custom Docker image in your _.gitpod_ file. -Starting today, you can point to a *Dockerfile* that sits next to the *.gitpod* file. Gitpod will take care of building and caching it for you. Instead of managing your own docker builds and versions, simply put the *Dockerfile* into the repository and you will always have a working setup for the branch at hand. +Starting today, you can point to a _Dockerfile_ that sits next to the _.gitpod_ file. Gitpod will take care of building and caching it for you. Instead of managing your own docker builds and versions, simply put the _Dockerfile_ into the repository and you will always have a working setup for the branch at hand. Please read [Gero’s post](/blog/docker-in-gitpod) explaining this feature in more detail. diff --git a/src/blog/open-vsx-in-gitpod.md b/src/blog/open-vsx-in-gitpod.md index d3141dabd..45a5fbedc 100644 --- a/src/blog/open-vsx-in-gitpod.md +++ b/src/blog/open-vsx-in-gitpod.md @@ -21,7 +21,7 @@ Adoption from the tool-side is going well, too. We started by supporting Open VS As you may already know, Gitpod lets you describe your dev environment as code. This means that you write configuration and code that makes Gitpod automatically generate ready-to-code dev environments for your project. -An important part of such a configuration is the set of IDE extensions you need. In Gitpod you have two choices, you can either +An important part of such a configuration is the set of IDE extensions you need. In Gitpod you have two choices, you can either **[1] Install an extension for your project's dev environment, or** @@ -37,8 +37,8 @@ Some extensions however are a matter of personal taste, such as themes and keybi While more and more extensions land in Open VSX on a daily basis, there still might be cases where you are missing a certain extension that exists in the MS marketplace. There are three things you can do: - - Ideally, you go to the extension's repository itself and kindly ask the developer to publish it to Open VSX. Publishing is a one-liner (`npx ovsx publish`), so it's really low effort. - - Download the extension's `.vsix` file (e.g. from the extension's GitHub Releases) and drag and drop it into the IDE's Extensions view. That will install and activate it automatically. - - Create a PR over at https://github.com/open-vsx/publish-extensions — that's where we seed the Open VSX registry by automatically publishing popular open-source extensions. +- Ideally, you go to the extension's repository itself and kindly ask the developer to publish it to Open VSX. Publishing is a one-liner (`npx ovsx publish`), so it's really low effort. +- Download the extension's `.vsix` file (e.g. from the extension's GitHub Releases) and drag and drop it into the IDE's Extensions view. That will install and activate it automatically. +- Create a PR over at https://github.com/open-vsx/publish-extensions — that's where we seed the Open VSX registry by automatically publishing popular open-source extensions. - You can find more information in our [docs](/docs/vscode-extensions/). +You can find more information in our [docs](/docs/vscode-extensions/). diff --git a/src/blog/open-vsx.md b/src/blog/open-vsx.md index 9bff55a1f..315d43832 100644 --- a/src/blog/open-vsx.md +++ b/src/blog/open-vsx.md @@ -19,7 +19,7 @@ While all the projects above support VS Code extensions, only Microsoft products Gitpod employs a workaround where users can upload .vsix files to install extensions. This causes unnecessary friction as users have to download those files directly from GitHub, just to re-upload them to Gitpod. Downloading from the Microsoft Marketplace for any use other than in Microsoft products is prohibited, too. -Most extensions are developed by the community and published under permissive Open Source Licenses. Having to distribute and access these community-owned extensions in a system with such restrictive terms of services does not seem right. We want to fix this and host an open-source extension registry at the vendor-neutral [Eclipse Foundation](https://www.eclipse.org/org/foundation/). +Most extensions are developed by the community and published under permissive Open Source Licenses. Having to distribute and access these community-owned extensions in a system with such restrictive terms of services does not seem right. We want to fix this and host an open-source extension registry at the vendor-neutral [Eclipse Foundation](https://www.eclipse.org/org/foundation/). ## You Can Host Your Own Registry diff --git a/src/blog/prebuilds.md b/src/blog/prebuilds.md index 0044f0526..c78d05f19 100644 --- a/src/blog/prebuilds.md +++ b/src/blog/prebuilds.md @@ -9,7 +9,7 @@ image: /compiling-xkcd.png Once your development environment is freed from manual setup procedures it can do work even while you are not. We call this continuous development. -A while ago Sven described the idea of [development environment as code](/blog/dev-env-as-code/). His main point: instead of using outdated README files that describe how to set up our development environment we should have executable, replicable and version-controlled descriptions thereof. In such a dev-environment as code world, on-boarding new team members/contributors is dead easy, going back to an old branch becomes a breeze (that old setup you had a year ago is now easy to restore) and playing with a new project becomes a joy. All those situations are very much *direct use* scenarios; you set up a dev-environment using code which you as a developer use straight away. +A while ago Sven described the idea of [development environment as code](/blog/dev-env-as-code/). His main point: instead of using outdated README files that describe how to set up our development environment we should have executable, replicable and version-controlled descriptions thereof. In such a dev-environment as code world, on-boarding new team members/contributors is dead easy, going back to an old branch becomes a breeze (that old setup you had a year ago is now easy to restore) and playing with a new project becomes a joy. All those situations are very much _direct use_ scenarios; you set up a dev-environment using code which you as a developer use straight away. However, a machine-reproducible version of your development setup enables another powerful capability: your dev-environment can already checkout the latest code, download dependencies and build everything. Once you actually open your IDE, everything’s ready for you. No more siting there and watching ~~paint dry~~ yarn download the internet. @@ -20,13 +20,14 @@ However, a machine-reproducible version of your development setup enables anothe Turns out we don’t actually have to be present for those things to happen. What if we had a system that would use our dev-environment description, check out the repo, build everything and then make it available to us? Sounds an awful lot like continuous integration (CI). Except there’s a subtle difference: CI checks if everything still fits together, i.e. does the code still build and do the tests still pass? The result of continuous integration is a test report and a bunch of built binaries/Docker images/update sites/APK files/you get the point. A CI build does not give you a ready-to-code workspace. But it tells you that the next time you want to build your software things will likely be fine. + > Continuous Development means that your code is built before you even open it. Once you open an IDE on your project, everything is ready to go. -The result of *continuous development* is a ready-to-code workspace. The second you open your IDE you can start working because all dependencies have been downloaded, indices updated, code generated and compiled, ~~and coffee has been brewed~~. Your dev environment has done all the things you’d otherwise do manually, except you didn’t have to trigger them or watch them finish. +The result of _continuous development_ is a ready-to-code workspace. The second you open your IDE you can start working because all dependencies have been downloaded, indices updated, code generated and compiled, ~~and coffee has been brewed~~. Your dev environment has done all the things you’d otherwise do manually, except you didn’t have to trigger them or watch them finish. ## How could we build this? -![Hands with paint on them. Photo by [Amaury Salas](https://unsplash.com/photos/IhXrWDckZOQ?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)](./prebuilds/colored-hands.jpg)*Photo by [Amaury Salas](https://unsplash.com/photos/IhXrWDckZOQ?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)* +![Hands with paint on them. Photo by [Amaury Salas](https://unsplash.com/photos/IhXrWDckZOQ?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)](./prebuilds/colored-hands.jpg)_Photo by [Amaury Salas](https://unsplash.com/photos/IhXrWDckZOQ?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_ To build a continuous development system we need three things: @@ -57,7 +58,7 @@ Using for example Jenkins or GitHub Actions we can then build a ready-to-code en Once we’re ready to start working on a new feature, or want to review a PR, we just find the previously built Docker image and have everything ready to go. No faffing with git clone, waiting for the code to build or anything of the sorts. We have reduced many minutes of our time to a simple docker run. -A similar way of implementing this is the way [gitpod.io](https://gitpod.io) does it (full disclosure: I am one of the folks working on this project). Gitpod comes with a GitHub app that triggers *workspace prebuilds* which in essence take your dev-environment as code (Dockerfile), execute a set of commands in there and associate the results with the particular commit that triggered it all. When you open a workspace on that commit, you’ll get the results of the prebuild instead of waiting for everything to complete. +A similar way of implementing this is the way [gitpod.io](https://gitpod.io) does it (full disclosure: I am one of the folks working on this project). Gitpod comes with a GitHub app that triggers _workspace prebuilds_ which in essence take your dev-environment as code (Dockerfile), execute a set of commands in there and associate the results with the particular commit that triggered it all. When you open a workspace on that commit, you’ll get the results of the prebuild instead of waiting for everything to complete. ## Is this new? diff --git a/src/blog/status-page.md b/src/blog/status-page.md index faeac7a27..400f132b6 100644 --- a/src/blog/status-page.md +++ b/src/blog/status-page.md @@ -11,11 +11,11 @@ A core value at Gitpod is transparency: a lot of what we do is out in the open, We had three main requirements for our status page: -* It had to be **rock solid** because if your status page is not available, how am I going to trust your product? +- It had to be **rock solid** because if your status page is not available, how am I going to trust your product? -* It should **present the status of our service, nothing else**. We already have an extensive monitoring setup (based on Prometheus/Grafana/InfluxDB) that watches over our infrastructure. No need to introduce yet another monitoring solution. A surprising amount of status page projects also do monitoring/health checks on the side. +- It should **present the status of our service, nothing else**. We already have an extensive monitoring setup (based on Prometheus/Grafana/InfluxDB) that watches over our infrastructure. No need to introduce yet another monitoring solution. A surprising amount of status page projects also do monitoring/health checks on the side. -* It had to **integrate into our existing infrastructure**. If we could use Git, our existing cloud infrastructure and Gitpod to update/manage our incident reports, all the better. We already have this infrastructure in place, so if we could avoid setting up a brand new website deployment, that is a plus. +- It had to **integrate into our existing infrastructure**. If we could use Git, our existing cloud infrastructure and Gitpod to update/manage our incident reports, all the better. We already have this infrastructure in place, so if we could avoid setting up a brand new website deployment, that is a plus. Our [documentation](https://github.com/gitpod-io/gitpod-docs) and website are statically generated from Markdown which we edit using Gitpod, push to GitHub and build/deploy using Jenkins. This pattern works well for us, it would be nice if we could use the same process for our status page. diff --git a/src/blog/update-december-2019.md b/src/blog/update-december-2019.md index 07f040062..de7f4150a 100644 --- a/src/blog/update-december-2019.md +++ b/src/blog/update-december-2019.md @@ -10,19 +10,21 @@ teaserImage: /winter.jpeg Ho ho ho! Christmas came early! We’ve just released a bunch of exciting new features and I'm not talking about [Gitpod Enterprise](/enterprise/) which was announced last week or the [GitLab support](/blog/gitlab-support/) we've shipped the week before. - - [Try with Your Private Repositories For Free](#private-project-trial) - - [Get Your Projects Setup with an Assistant](#setup-assistant) - - [New, Cheaper Plans with More Features](#new-plans) - - [Light and Dark Theme](#light-theme) - - [Automatic Garbage Collection](#garbage-collection) - - [New Community Forum](#new-community-home) +- [Try with Your Private Repositories For Free](#private-project-trial) +- [Get Your Projects Setup with an Assistant](#setup-assistant) +- [New, Cheaper Plans with More Features](#new-plans) +- [Light and Dark Theme](#light-theme) +- [Automatic Garbage Collection](#garbage-collection) +- [New Community Forum](#new-community-home) ## 🔓 Private Project Trial -Users can now try Gitpod on their private GitHub and GitLab projects for one month for free without providing payment information or automatic subscription start afterward. -To get started, simply prefix your private repository’s GitHub or GitLab URL with __gitpod.io/#__ and go through the OAuth flow. To fully get the hang of Gitpod, you need to configure your project accordingly. You can either [schedule a call](https://calendly.com/gitpod/onboarding) with an engineer, study the [documentation](/docs/configuration/), or use the new and shiny setup assistant. +Users can now try Gitpod on their private GitHub and GitLab projects for one month for free without providing payment information or automatic subscription start afterward. + +To get started, simply prefix your private repository’s GitHub or GitLab URL with **gitpod.io/#** and go through the OAuth flow. To fully get the hang of Gitpod, you need to configure your project accordingly. You can either [schedule a call](https://calendly.com/gitpod/onboarding) with an engineer, study the [documentation](/docs/configuration/), or use the new and shiny setup assistant. ## 🛠 Setup Assistant + Although setting up a project for Gitpod is usually a one-off effort, it can be a little involving depending on the complexity of the project's structure. With the arrival of a new setup assistant configuring Gitpod has become a whole lot easier now. The assistant informs you through a small notification when your project lacks a `.gitpod.yml` and guides you through a 5 step process to create, test and propose a proper Gitpod configuration. @@ -32,34 +34,37 @@ You can of course try it out on an arbitrary open-source project, too. We want t `youtube: IRzCR0r7DSE` ## 🤗 New Plans -We have reworked the plans and added a bunch of features to them as well. + +We have reworked the plans and added a bunch of features to them as well. ### Free for Open Source ❤️ + So far Gitpod has been free to use on public repositories for up to 100hours/month. We analyzed how people have been using Gitpod and found out that while a lot of people use it regularly for open-source work and reach the 100 hours limit, there are others using the free plan to run their expensive processes and builds (miners and the like are automatically killed, btw, and are violating our terms) which is not what we had in mind when offering a generous open-source plan. To protect us from such miss-use and at the same time better support open-source work, we made the following two changes: -1) Add a __free, unlimited hours for professional open-source developers__. -2) Reduce the free plan to 50h/month, which is still plenty for part-time contributors and trying Gitpod. +1. Add a **free, unlimited hours for professional open-source developers**. +2. Reduce the free plan to 50h/month, which is still plenty for part-time contributors and trying Gitpod. Please [apply](/contact/) for the unlimited open-source plan, once you ran against the 50 hours limit. We'll check your track record and get you going within one business day. ### Personal Plan -The Personal Plan got a change in that it __can now be used commercially__ as well. This hasn’t changed the price of €8 / $9. + +The Personal Plan got a change in that it **can now be used commercially** as well. This hasn’t changed the price of €8 / \$9. ### Professional Plan 🆕 -We added a plan in the middle that offers __unlimited usage hours for €23 / $25__. +We added a plan in the middle that offers **unlimited usage hours for €23 / \$25**. ### Unlimited Plan -The Unlimited plan got a couple of cool upgrades. +The Unlimited plan got a couple of cool upgrades. -Most importantly, __Unlimited users enjoy a 60min timeout with an additional 3 hours booster__. For regular users the timeout is strict 30 minutes. The additional booster can be triggered from within a workspace. Simply press the hourglass sign in the status bar (only visible if you are an unlimited users) +Most importantly, **Unlimited users enjoy a 60min timeout with an additional 3 hours booster**. For regular users the timeout is strict 30 minutes. The additional booster can be triggered from within a workspace. Simply press the hourglass sign in the status bar (only visible if you are an unlimited users) ![Timeout Booster](./update-december-2019/timeout-boost.png) -Furthermore, with Unlimited you can __start up 16 workspaces in parallel__. +Furthermore, with Unlimited you can **start up 16 workspaces in parallel**. Checkout the [pricing page](/pricing/) for an overview. @@ -73,11 +78,11 @@ Gitpod comes with a dark theme by default. You can now switch to light and the s With prebuilt, disposable workspaces, Gitpod encourages to start fresh workspaces for every task. Whenever I need to code, do a review or just want to try something, I simply spin up a fresh workspace, do my thing and forget about it afterward. -__But what happens to all those old workspaces?__ +**But what happens to all those old workspaces?** Well, in order to really be able to forget about it, we have implemented an automatic garbage collection. It automatically deletes old workspaces after an inactivity of 30 days. You can exclude workspace from being garbage collected by manually pinning them in the workspaces list on the dashboard (see belows screenshot). -__Garbage collection starts on January 20th.__ +**Garbage collection starts on January 20th.** ![Pin Workspaces](./update-december-2019/pin-gc.jpg) @@ -89,6 +94,6 @@ We've moved the support forum to [community.gitpod.io](https://community.gitpod. ## 🥂Have a Great Holiday Season! -That's all for now. I hope you have a great time with your families and friends. Many thanks to everyone supporting us in our quest to simplify and streamline developer's daily live. +That's all for now. I hope you have a great time with your families and friends. Many thanks to everyone supporting us in our quest to simplify and streamline developer's daily live. See you online & happy coding! diff --git a/src/blog/visual-studio-online-vs-gitpod.md b/src/blog/visual-studio-online-vs-gitpod.md index 257e51819..696ebddcd 100644 --- a/src/blog/visual-studio-online-vs-gitpod.md +++ b/src/blog/visual-studio-online-vs-gitpod.md @@ -32,7 +32,7 @@ For that we eliminated any ‘create environment’-wizards and dashboards stand In the launch post for VSO disposable dev environments are mentioned, which is an important part of our vision, but unfortunately VSO doesn’t embrace it in the actual product. After getting through the account creation of VSO, you land on a dashboard and create a dev environment through a form based configuration dialog. Due to the lack of prebuilds, creating fresh dev environments all the time is tedious, as you need to wait for the build, downloading dependencies and running tests. This dashboard-centric approach encourages people to reuse their workspaces instead of relying on a well-working, automated setup continuously. -Gitpod, on the other hand, builds your branches similar to a CI build *before* you open a dev environment. This way you are really ready-to-code whenever you open a workspace. Disposable dev environments really need such a feature as you’d otherwise waste your time on [watching your build](/blog/prebuilds/). +Gitpod, on the other hand, builds your branches similar to a CI build _before_ you open a dev environment. This way you are really ready-to-code whenever you open a workspace. Disposable dev environments really need such a feature as you’d otherwise waste your time on [watching your build](/blog/prebuilds/). # Self Hosting @@ -47,6 +47,7 @@ A list of checkboxes doesn’t make a good product, although in terms of feature That said, VSO is still in beta and they have features on their agenda that are also not yet supported on Gitpod, such as starting Windows VMs. Anyhow, the Gitpod team is not striving for an ever growing feature list. Instead, + > we are focussing on a coherent developer experience (DX) that doesn’t get into your way, but lets you focus on coding. # Microsoft Monopoly? @@ -58,10 +59,10 @@ For GitHub, GitLab seems to be the only real competitor and Azure DevOps is tryi # Conclusion In this post I covered the most important differences between Gitpod and Visual Studio Online. In a nutshell: -on the IDE feature level there are not many differences, __but__ - - regarding how dev environments are provisioned, Gitpod’s approach is clearly leading the pack. - - Self-hosting is not really supported by VSO and - - Microsoft is growing a little too dominant in the developer world these days. +on the IDE feature level there are not many differences, **but** - Please reach out if you have further questions. +- regarding how dev environments are provisioned, Gitpod’s approach is clearly leading the pack. +- Self-hosting is not really supported by VSO and +- Microsoft is growing a little too dominant in the developer world these days. +Please reach out if you have further questions. diff --git a/src/blog/vscode-extension-in-online-ide.md b/src/blog/vscode-extension-in-online-ide.md index 49f1be94c..e31be338d 100644 --- a/src/blog/vscode-extension-in-online-ide.md +++ b/src/blog/vscode-extension-in-online-ide.md @@ -25,7 +25,7 @@ Here is how it works: ## Installing an Extension -Installing extensions is a matter of dragging and dropping a *.vsix file into the extension view. Gitpod will automatically install and activate the new extension, and add an entry to the .gitpod.yml file. You can now test the experience and if you are happy with it share this new experience with your team by pushing the change to your remote Git repository. +Installing extensions is a matter of dragging and dropping a \*.vsix file into the extension view. Gitpod will automatically install and activate the new extension, and add an entry to the .gitpod.yml file. You can now test the experience and if you are happy with it share this new experience with your team by pushing the change to your remote Git repository. Here’s a small screencast: `youtube: hEqmXM62cjo` diff --git a/src/blog/when-code-reviews-lgtm.md b/src/blog/when-code-reviews-lgtm.md index bfd53af68..302cdcd21 100644 --- a/src/blog/when-code-reviews-lgtm.md +++ b/src/blog/when-code-reviews-lgtm.md @@ -36,9 +36,9 @@ I feel your pain, but you should not take that shortcut. It will fire back event [Gitpod](https://www.gitpod.io) gives you a full development environment with a single click for any pull request on GitHub. You don’t have to manually setup or even change anything on your local development environment. Just click a button and you have the best of both worlds: -* a full development environment (similar to VS Code) +- a full development environment (similar to VS Code) -* a great code review experience (similar to GitHub) +- a great code review experience (similar to GitHub) ## Code Review in Gitpod diff --git a/src/blog/workspace-snapshots.md b/src/blog/workspace-snapshots.md index 5c9c8469e..148a57e63 100644 --- a/src/blog/workspace-snapshots.md +++ b/src/blog/workspace-snapshots.md @@ -32,14 +32,14 @@ However, instead of laying out the steps in prose, an automated solution would b Before we are taking the snapshot, we want to make sure everything is in the state we want it to be. So the maintainers get pointed to the culprit immediately. For this example I made sure -* the build ran through, +- the build ran through, -* the right editors are opened -(I choose to open the two files mentioned in the issue in split mode), +- the right editors are opened + (I choose to open the two files mentioned in the issue in split mode), -* the sample application is started automatically +- the sample application is started automatically -Taking care of the first two items is easy. For the third, you need to add a ***.gitpod.yml*** to the root of the project containing the tasks you want to start. +Taking care of the first two items is easy. For the third, you need to add a **_.gitpod.yml_** to the root of the project containing the tasks you want to start. In the case of this project I added a task to start the failing Java process: @@ -49,9 +49,10 @@ In the case of this project I added a task to start the failing Java process: -Dexec.executable=java \ -Dexec.args=”-cp %classpath com.example.beanoverriding.EmbeddedApplication” \ -Dexec.classpathScope=”test” + > Btw. to figure out how to start that damn thing using Maven, I had to ask the community on StackOverflow. Of course, by providing a Gitpod Snapshot :-) -[**Run main from test scope in Maven: "The parameters 'mainClass' for goal…** -*Thanks for contributing an answer to Stack Overflow! Some of your past answers have not been well-received, and you're…*stackoverflow.com](https://stackoverflow.com/questions/53536751/run-main-from-test-scope-in-maven-the-parameters-mainclass-for-goal-org-code) +> [**Run main from test scope in Maven: "The parameters 'mainClass' for goal…** +> *Thanks for contributing an answer to Stack Overflow! Some of your past answers have not been well-received, and you're…*stackoverflow.com](https://stackoverflow.com/questions/53536751/run-main-from-test-scope-in-maven-the-parameters-mainclass-for-goal-org-code) With the **.gitpod.yml **configured and the editors and views laid out as needed, we are ready to take a snapshot. Simply click on the avatar on the top right: diff --git a/src/browser.ts b/src/browser.ts index af41e94af..8d818dee6 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -1,3 +1 @@ - - -export const isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor); +export const isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor) diff --git a/src/components/ActionCard.tsx b/src/components/ActionCard.tsx index 9a3c77850..31e300c91 100644 --- a/src/components/ActionCard.tsx +++ b/src/components/ActionCard.tsx @@ -5,50 +5,49 @@ import { colors, borders } from '../styles/variables' import link from '../utils/link' const StyledActionCard = styled.section` - display: block; - max-width: 60rem; - margin: 8rem auto; - padding: 5rem 3rem; - text-align: center; - background: ${colors.offWhite}; - border: ${borders.light2}; - border-radius: 3px; - - h2 { - font-size: 2.8rem; - } - - p { - margin: -3rem 0 4rem; - } - - .btn-wrapper { - justify-content: center; - } + display: block; + max-width: 60rem; + margin: 8rem auto; + padding: 5rem 3rem; + text-align: center; + background: ${colors.offWhite}; + border: ${borders.light2}; + border-radius: 3px; + + h2 { + font-size: 2.8rem; + } + + p { + margin: -3rem 0 4rem; + } + + .btn-wrapper { + justify-content: center; + } ` interface Anchor { - text: string - href: string - subject?: string + text: string + href: string + subject?: string } interface ActionCardProps { - title: string - text: string | JSX.Element - anchors: Anchor[] + title: string + text: string | JSX.Element + anchors: Anchor[] } - const ActionCard: React.SFC = ({ title, text, anchors }) => ( - -

{title}

- {typeof text === 'string' ?

{text}

: text} -
- {link(anchors[0].href, anchors[0].text, anchors[0].subject)} - {anchors[1] ? link(anchors[1].href, anchors[1].text, anchors[1].subject) : null} -
-
+ +

{title}

+ {typeof text === 'string' ?

{text}

: text} +
+ {link(anchors[0].href, anchors[0].text, anchors[0].subject)} + {anchors[1] ? link(anchors[1].href, anchors[1].text, anchors[1].subject) : null} +
+
) export default ActionCard diff --git a/src/components/Arrow.tsx b/src/components/Arrow.tsx index e347c37d8..2ee45bbe3 100644 --- a/src/components/Arrow.tsx +++ b/src/components/Arrow.tsx @@ -5,41 +5,36 @@ import { Global, css } from '@emotion/core' import { colors } from '../styles/variables' const StyledArrow = styled.svg` - display: inline-block; - fill: ${colors.offWhite1}; - transition: all .2s; - height: 4rem; + display: inline-block; + fill: ${colors.offWhite1}; + transition: all 0.2s; + height: 4rem; ` interface ArrrowProps { - styles?: CSSProperties + styles?: CSSProperties } const Arrow = ({ styles }: ArrrowProps) => ( - - - - + + + + ) export default Arrow diff --git a/src/components/BackToTopButton.tsx b/src/components/BackToTopButton.tsx index 424ff822a..6602075ef 100644 --- a/src/components/BackToTopButton.tsx +++ b/src/components/BackToTopButton.tsx @@ -5,48 +5,45 @@ import { shadows, colors } from '../styles/variables' import Arrow from './Arrow' const StyledScrollToTopButton = styled.a` - position: fixed; - right: 4%; - bottom: 2rem; - display: flex; - justify-content: center; - align-items: center; - box-shadow: ${shadows.light1}; - border-radius: 50%; - z-index: 100; - transition: transform .3s, opacity .2s, background-color .2s ease-in-out; - background: ${colors.white}; + position: fixed; + right: 4%; + bottom: 2rem; + display: flex; + justify-content: center; + align-items: center; + box-shadow: ${shadows.light1}; + border-radius: 50%; + z-index: 100; + transition: transform 0.3s, opacity 0.2s, background-color 0.2s ease-in-out; + background: ${colors.white}; ` - class ScrollToTopButton extends React.Component { - - state = { - shouldBeRendered: false - } - - componentDidMount() { - window.addEventListener('scroll', () => { - if ( window.scrollY > 800) { - this.setState({shouldBeRendered: true}) - } - else { - this.setState({shouldBeRendered: false}) - } - }) - } - - render() { - return ( - - - - ) - } + state = { + shouldBeRendered: false + } + + componentDidMount() { + window.addEventListener('scroll', () => { + if (window.scrollY > 800) { + this.setState({ shouldBeRendered: true }) + } else { + this.setState({ shouldBeRendered: false }) + } + }) + } + + render() { + return ( + + + + ) + } } export default ScrollToTopButton diff --git a/src/components/Banner.tsx b/src/components/Banner.tsx index 5d98d3f77..341a32614 100644 --- a/src/components/Banner.tsx +++ b/src/components/Banner.tsx @@ -4,84 +4,83 @@ import styled from '@emotion/styled' import link from '../utils/link' const StyledBanner = styled.header` - /* ------------------------------------------- */ - /* ----- Banner ----- */ - /* ------------------------------------------- */ - - display: flex; - justify-content: space-between; - align-items: center; - padding: 14rem 0 10rem; - - @media(max-width: 960px) { - flex-direction: column-reverse; - padding: 5rem 0; + /* ------------------------------------------- */ + /* ----- Banner ----- */ + /* ------------------------------------------- */ + + display: flex; + justify-content: space-between; + align-items: center; + padding: 14rem 0 10rem; + + @media (max-width: 960px) { + flex-direction: column-reverse; + padding: 5rem 0; + } + + @media (max-width: 960px) { + flex-direction: column-reverse; + padding: 1rem 0 5rem; + } + + .para { + margin-top: 3rem; + + @media (min-width: 961px) { + max-width: 50rem; } + } - @media(max-width: 960px) { - flex-direction: column-reverse; - padding: 1rem 0 5rem; - } + .btn { + margin: 5rem 2rem 2rem 0; - .para { - margin-top: 3rem; - - @media(min-width: 961px) { - max-width: 50rem; - } + @media (max-width: 960px) { + margin-top: 3rem; } + } - .btn { - margin: 5rem 2rem 2rem 0; + p + .btn { + margin-top: 3rem; + } - @media(max-width: 960px) { - margin-top: 3rem; - } - } + object, + img { + display: block; + height: 35rem; - p + .btn { - margin-top: 3rem; + @media (min-width: 961px) { + margin-left: 3rem; } - - object, img { - display: block; - height: 35rem; - - @media(min-width: 961px) { - margin-left: 3rem; - } - - @media(max-width: 960px) { - height: 20rem; - margin: 5rem 0; - } + @media (max-width: 960px) { + height: 20rem; + margin: 5rem 0; } - + } ` interface BannerProps { - subtitle: string - title: JSX.Element - paragraph?: string | JSX.Element - linkPath: string - linkText: string - img: JSX.Element + subtitle: string + title: JSX.Element + paragraph?: string | JSX.Element + linkPath: string + linkText: string + img: JSX.Element } -const Banner: React.SFC = ({subtitle, title, paragraph, linkPath, linkText, img, children}) => ( -
- -
-

{subtitle}

- {title} - { paragraph ?

{paragraph}

: null } - {link(linkPath, linkText,'', true, false)} - {children} -
- {img} -
-
+const Banner: React.SFC = ({ subtitle, title, paragraph, linkPath, linkText, img, children }) => ( +
+ +
+

{subtitle}

+ {title} + {paragraph ?

{paragraph}

: null} + {link(linkPath, linkText, '', true, false)} + {children} +
+ {img} +
+
) export default Banner diff --git a/src/components/Bg.tsx b/src/components/Bg.tsx index 983d5e88a..088fe42ad 100644 --- a/src/components/Bg.tsx +++ b/src/components/Bg.tsx @@ -4,26 +4,25 @@ import styled from '@emotion/styled' import { sizes } from '../styles/variables' const StyledBg = styled.img` - display: block; - width: 100%; - max-height: 40rem; - max-width: 100rem; - margin: 7rem auto; + display: block; + width: 100%; + max-height: 40rem; + max-width: 100rem; + margin: 7rem auto; - @media(max-width: ${sizes.breakpoints.md}) { - margin: 6rem auto; - } + @media (max-width: ${sizes.breakpoints.md}) { + margin: 6rem auto; + } ` interface BgProps { - url: any + url: any } -const Bg: React.SFC = ({url}) => ( -
-
+const Bg: React.SFC = ({ url }) => ( +
+
) - export default Bg diff --git a/src/components/Circle.tsx b/src/components/Circle.tsx index ae645c1df..ee685eb37 100644 --- a/src/components/Circle.tsx +++ b/src/components/Circle.tsx @@ -1,7 +1,7 @@ import React from 'react' const Circle: React.SFC<{}> = () => ( - + ) diff --git a/src/components/DropDown.tsx b/src/components/DropDown.tsx index f0011312e..70518d427 100644 --- a/src/components/DropDown.tsx +++ b/src/components/DropDown.tsx @@ -110,105 +110,79 @@ const StyledDropDown = styled.div` ` interface Anchor { - text: string - to: string - target?: boolean + text: string + to: string + target?: boolean } interface DropDownProps { - title: string - links: Anchor[] + title: string + links: Anchor[] } class DropDown extends React.Component { - - state = { - isRendered: false - } - - handleClick = () => { - this.setState({isRendered: !this.state.isRendered}) - } - - handleMouseEnter = () => { - this.setState({isRendered: true}) - } - - handleMouseLeave = () => { - this.setState({isRendered: false}) - } - - render () { - const { title, links } = this.props - const { isRendered } = this.state - - return ( - -
{title}
- Arrow - - -
    - { - links.map(({text, to, target}, i) => - target ? - ( -
  • - -
  • - ) - : - ( -
  • - { - i == links.length - 1 ? - - {text} - - : - - {text} - - } -
  • - ) - ) - } - -
- - ) - } + state = { + isRendered: false + } + + handleClick = () => { + this.setState({ isRendered: !this.state.isRendered }) + } + + handleMouseEnter = () => { + this.setState({ isRendered: true }) + } + + handleMouseLeave = () => { + this.setState({ isRendered: false }) + } + + render() { + const { title, links } = this.props + const { isRendered } = this.state + + return ( + + + +
    + {links.map(({ text, to, target }, i) => + target ? ( +
  • + +
  • + ) : ( +
  • + {i === links.length - 1 ? ( + + {text} + + ) : ( + + {text} + + )} +
  • + ) + )} + +
+
+ ) + } } export default DropDown diff --git a/src/components/ExternalLink.tsx b/src/components/ExternalLink.tsx index 7334c3658..a4f05b9da 100644 --- a/src/components/ExternalLink.tsx +++ b/src/components/ExternalLink.tsx @@ -4,39 +4,45 @@ import styled from '@emotion/styled' import { colors, sizes } from '../styles/variables' const StyledExternalLink = styled.a` - .external { - height: 1.5rem; - transform: translate(.6rem, .3rem); - transition: all .2s; - opacity: 0; - fill: ${colors.text}; + .external { + height: 1.5rem; + transform: translate(0.6rem, 0.3rem); + transition: all 0.2s; + opacity: 0; + fill: ${colors.text}; - @media(max-width: ${sizes.breakpoints.md}) { - opacity: 1; - } + @media (max-width: ${sizes.breakpoints.md}) { + opacity: 1; } + } - &:hover, - &:active { - .external { - opacity: 1; - fill: ${colors.link}; - } + &:hover, + &:active { + .external { + opacity: 1; + fill: ${colors.link}; } + } ` interface ExternalLinkProps { - text: string - href: string - tabIndex?: number - className?: string, - onBlur?: any + text: string + href: string + tabIndex?: number + className?: string + onBlur?: any } -const ExternalLink: React.SFC = ({href, text, tabIndex, className, onBlur}) => ( - - {text} - +const ExternalLink: React.SFC = ({ href, text, tabIndex, className, onBlur }) => ( + + {text}{' '} + + + + ) export default ExternalLink diff --git a/src/components/FeatureCard.tsx b/src/components/FeatureCard.tsx index a5cabe72e..b2f5acf69 100644 --- a/src/components/FeatureCard.tsx +++ b/src/components/FeatureCard.tsx @@ -1,261 +1,244 @@ -import React, { useState, useRef, useEffect } from 'react' +import React, { useState } from 'react' import styled from '@emotion/styled' import { sizes } from '../styles/variables' import Pattern from '../resources/pattern-2.jpg' import IconTick from '../resources/icon-tick.svg' -const Styled = styled.div<{ direction?: string, flexDirectionColumnForImgContainer?: boolean }>` - display: flex; - justify-content: space-between; - position: relative; - - &:not(:last-child) { - margin-bottom: 18rem; - } +const Styled = styled.div<{ direction?: string; flexDirectionColumnForImgContainer?: boolean }>` + display: flex; + justify-content: space-between; + position: relative; - @media(max-width: ${sizes.breakpoints.sm}) { - text-align: center; - } + &:not(:last-child) { + margin-bottom: 18rem; + } - [id] { - position: absolute; - top: -25vh; - } - + @media (max-width: ${sizes.breakpoints.sm}) { + text-align: center; + } + [id] { + position: absolute; + top: -25vh; + } - @media(max-width: 1140px) { - flex-direction: column; - max-width: 740px; - } + @media (max-width: 1140px) { + flex-direction: column; + max-width: 740px; + } + + h2 + p { + margin: 0; + } - h2 + p { - margin: 0; + &:nth-of-type(2n) { + @media (min-width: 1141px) { + flex-direction: row-reverse; } - &:nth-of-type(2n) { - @media(min-width: 1141px) { - flex-direction: row-reverse; + @media (min-width: 1141px) { + .why-gitpod__img-container { + padding-left: 8rem; + &::before { + left: 0; } - @media(min-width: 1141px) { - .why-gitpod__img-container { - padding-left: 8rem; - &::before { - left: 0; - } - - &:hover::before { - transform: translateX(-5rem); - } - } + &:hover::before { + transform: translateX(-5rem); } + } } + } - .text { - display: flex; - flex-direction: column; - justify-content: center; - min-width: 28rem; - - @media(min-width: 1141px) { - flex: 0 0 38%; - } + .text { + display: flex; + flex-direction: column; + justify-content: center; + min-width: 28rem; - @media(max-width: 1150px) { - padding: 0 4rem; - } + @media (min-width: 1141px) { + flex: 0 0 38%; + } - @media(max-width: ${sizes.breakpoints.md}) { - padding: 0 2rem; - } + @media (max-width: 1150px) { + padding: 0 4rem; + } - @media(max-width: ${sizes.breakpoints.sm}) { - padding: 0 1rem; - } + @media (max-width: ${sizes.breakpoints.md}) { + padding: 0 2rem; } - img { - width: 100%; - max-height: 440px; + @media (max-width: ${sizes.breakpoints.sm}) { + padding: 0 1rem; + } + } - @media(max-width: 1140px) { - max-height: 400px; - } + img { + width: 100%; + max-height: 440px; - @media(max-width: 500px) { - max-height: 300px; - } + @media (max-width: 1140px) { + max-height: 400px; } - .img-container { - display: flex; - flex-direction: ${ - ({ flexDirectionColumnForImgContainer }) => - flexDirectionColumnForImgContainer ? 'column' : '' - }; - justify-content: center; - align-items: ${ - ({ flexDirectionColumnForImgContainer }) => - flexDirectionColumnForImgContainer ? '' : 'center' - };; - width: 100%; - position: relative; + @media (max-width: 500px) { + max-height: 300px; + } + } - &::before { - content: ""; - position: absolute; - display: block; - height: 100%; - width: 100%; - background: url(${Pattern}); - background-size: cover; - background-repeat: repeat; - z-index: -1; - opacity: .1; - border-radius: 3px; - } + .img-container { + display: flex; + flex-direction: ${({ flexDirectionColumnForImgContainer }) => (flexDirectionColumnForImgContainer ? 'column' : '')}; + justify-content: center; + align-items: ${({ flexDirectionColumnForImgContainer }) => (flexDirectionColumnForImgContainer ? '' : 'center')}; + width: 100%; + position: relative; - @media(min-width: 1141px) { - padding-right: ${({ direction }) => (direction === 'right') ? '8rem' : ''}; - padding-left: ${({ direction }) => !(direction === 'right') ? '8rem' : ''}; - min-height: 520px; - max-height: 500px; - flex: 0 0 52%; - - &::before { - left: ${({ direction }) => (direction === 'right') ? '' : 0}; - right: ${({ direction }) => !(direction === 'right') ? '' : 0}; - width: 60vw; - } - } + &::before { + content: ''; + position: absolute; + display: block; + height: 100%; + width: 100%; + background: url(${Pattern}); + background-size: cover; + background-repeat: repeat; + z-index: -1; + opacity: 0.1; + border-radius: 3px; + } - @media(max-width: 1140px) { - min-height: 240px; - padding: 5rem; - margin-bottom: 2.5rem; + @media (min-width: 1141px) { + padding-right: ${({ direction }) => (direction === 'right' ? '8rem' : '')}; + padding-left: ${({ direction }) => (!(direction === 'right') ? '8rem' : '')}; + min-height: 520px; + max-height: 500px; + flex: 0 0 52%; - &::before { - left: 0; - right: 0; - } - } + &::before { + left: ${({ direction }) => (direction === 'right' ? '' : 0)}; + right: ${({ direction }) => (!(direction === 'right') ? '' : 0)}; + width: 60vw; + } + } - @media(max-width: 560px) { - padding: 3rem; - } + @media (max-width: 1140px) { + min-height: 240px; + padding: 5rem; + margin-bottom: 2.5rem; - @media(max-width: 450px) { - padding: 2rem; - } + &::before { + left: 0; + right: 0; + } } - @keyframes slideInLeft { - 100% { - transform: translateX(5rem); - } + @media (max-width: 560px) { + padding: 3rem; } - @keyframes slideInRight { - 100% { - transform: translateX(-5rem) - } + @media (max-width: 450px) { + padding: 2rem; } + } - .in-view::before { - @media(min-width: 1141px) { - animation: ${({ direction }) => direction === 'right' ? 'slideInLeft' : 'slideInRight'} 0.6s cubic-bezier(0.16, 1, 0.3, 1) 1 normal forwards; - } + @keyframes slideInLeft { + 100% { + transform: translateX(5rem); } + } - .buttons { - margin-top: 4rem; + @keyframes slideInRight { + 100% { + transform: translateX(-5rem); } + } - ul { - margin-top: 5rem; - font-size: 1.9rem; + .in-view::before { + @media (min-width: 1141px) { + animation: ${({ direction }) => (direction === 'right' ? 'slideInLeft' : 'slideInRight')} 0.6s cubic-bezier(0.16, 1, 0.3, 1) 1 normal + forwards; + } + } - @media(max-width: 500px) { - font-size: 1.6rem; - } + .buttons { + margin-top: 4rem; + } - @media(max-width: 320px) { - font-size: 1.5rem; - } + ul { + margin-top: 5rem; + font-size: 1.9rem; - @media(max-width: 290px) { - font-size: 1.4rem; - } + @media (max-width: 500px) { + font-size: 1.6rem; } - li { - display: flex; - &::before { - content: url(${IconTick}); - transform: scale(1.4); - display: block; - margin: 0 2rem 0 1rem; - left: -.5rem; - - @media(max-width: 500px) { - margin: 0 1rem 0 0; - } - } + @media (max-width: 320px) { + font-size: 1.5rem; } - img { - border-radius: 3px; + @media (max-width: 290px) { + font-size: 1.4rem; } + } + + li { + display: flex; + &::before { + content: url(${IconTick}); + transform: scale(1.4); + display: block; + margin: 0 2rem 0 1rem; + left: -0.5rem; + + @media (max-width: 500px) { + margin: 0 1rem 0 0; + } + } + } + + img { + border-radius: 3px; + } ` export interface FeatureCardProps { - src?: string - alt?: string - Graphic?: any - title: string | JSX.Element - text: string | JSX.Element - direction?: string - id?: string - featuresList?: string[], - Buttons?: any + src?: string + alt?: string + Graphic?: any + title: string | JSX.Element + text: string | JSX.Element + direction?: string + id?: string + featuresList?: string[] + Buttons?: any } const FeatureCard = ({ src, alt, Graphic, title, text, direction, id, featuresList, Buttons }: FeatureCardProps) => { - const [renderedGraphic, setRenderedGraphic] = useState('') - - return ( - -
- {Graphic ? : null} - {src ? {alt} : null} - {featuresList && featuresList.length ? (
    - {featuresList.map( - (feat, i) =>
  • {feat}
  • - )} -
) : null} -
-
-

{title}

- {text} - { Buttons ? : null} -
- { - id &&
- } -
- ) + const [renderedGraphic, setRenderedGraphic] = useState('') + + return ( + +
+ {Graphic ? : null} + {src ? {alt} : null} + {featuresList && featuresList.length ? ( +
    + {featuresList.map((feat, i) => ( +
  • {feat}
  • + ))} +
+ ) : null} +
+
+

{title}

+ {text} + {Buttons ? : null} +
+ {id &&
} + + ) } export default FeatureCard diff --git a/src/components/FeatureCards.tsx b/src/components/FeatureCards.tsx index 5642442f2..930aad6f2 100644 --- a/src/components/FeatureCards.tsx +++ b/src/components/FeatureCards.tsx @@ -1,32 +1,25 @@ import React from 'react' import styled from '@emotion/styled' -import { FeatureCardProps } from './FeatureCard' -import FeatureCard from './FeatureCard' +import FeatureCard, { FeatureCardProps } from './FeatureCard' const Styled = styled.section` - display: flex; - flex-direction: column; - padding-bottom: 5rem; - position: relative; + display: flex; + flex-direction: column; + padding-bottom: 5rem; + position: relative; ` const FeatureCards = ({ features }: { features: FeatureCardProps[] }) => { - return ( - -
- { - features.map((feature: FeatureCardProps, i) => ( - - )) - } -
-
- ) + return ( + +
+ {features.map((feature: FeatureCardProps, i) => ( + + ))} +
+
+ ) } export default FeatureCards diff --git a/src/components/FeatureItem.tsx b/src/components/FeatureItem.tsx index 8902385c0..3e63c3c2d 100644 --- a/src/components/FeatureItem.tsx +++ b/src/components/FeatureItem.tsx @@ -45,20 +45,20 @@ const StyledFeatureItem = styled.div` ` export interface FeatureItemProps { - title: string - text: string - img: string - alt?: string + title: string + text: string + img: string + alt?: string } const FeatureItem = ({ title, text, img, alt }: FeatureItemProps) => ( - - {alt -
-

{title}

-

{text}

-
-
+ + {alt +
+

{title}

+

{text}

+
+
) export default FeatureItem diff --git a/src/components/FeaturesSection.tsx b/src/components/FeaturesSection.tsx index c64c07c4a..8e49e4559 100644 --- a/src/components/FeaturesSection.tsx +++ b/src/components/FeaturesSection.tsx @@ -5,36 +5,31 @@ import FeatureItem, { FeatureItemProps } from './FeatureItem' import { sizes } from '../styles/variables' const StyledFeatures = styled.div` - display: flex; - flex-wrap: wrap; - justify-content: space-between; - - @media(max-width: ${sizes.breakpoints.lg}) { - margin-top: -5rem; - } + display: flex; + flex-wrap: wrap; + justify-content: space-between; + + @media (max-width: ${sizes.breakpoints.lg}) { + margin-top: -5rem; + } - @media(max-width: 900px) { - flex-direction: column; + @media (max-width: 900px) { + flex-direction: column; - & > div { - max-width: 400px; - } + & > div { + max-width: 400px; } + } ` const FeaturesSection = ({ features }: { features: FeatureItemProps[] }) => ( -
- - { - features.map( - (feature: FeatureItemProps, i) => - ) - } - -
+
+ + {features.map((feature: FeatureItemProps, i) => ( + + ))} + +
) export default FeaturesSection diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 6f5010678..b9c46923f 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -6,211 +6,221 @@ import { Link } from 'gatsby' import ExternalLink from './ExternalLink' const StyledFooter = styled.footer` - background: ${colors.offWhite}; - padding: 7rem 0 4rem; - font-size: 1.4rem; - - .links { - display: flex; - justify-content: space-around; - flex-wrap: wrap; - - @media(max-width: 650px) { - justify-content: space-between; - - ul { - padding-bottom: 4rem; - border-bottom: 1px solid #ddd; - width: 48%; - text-align: center; - - &:not(:last-child) { - margin-bottom: 5rem; - } - - &:last-child { - transform: translateX(50%); - - img { - transform: translateX(1rem); - } - } - } - } - } - - li { + background: ${colors.offWhite}; + padding: 7rem 0 4rem; + font-size: 1.4rem; + + .links { + display: flex; + justify-content: space-around; + flex-wrap: wrap; + + @media (max-width: 650px) { + justify-content: space-between; + + ul { + padding-bottom: 4rem; + border-bottom: 1px solid #ddd; + width: 48%; + text-align: center; &:not(:last-child) { - margin-bottom: 1.6rem; + margin-bottom: 5rem; } - &:first-of-type { - font-size: 1.7rem; - font-weight: 600; - } + &:last-child { + transform: translateX(50%); + img { + transform: translateX(1rem); + } + } + } } + } - a { - color: ${colors.text}; - font-weight: 400; - transition: all .2s; + li { + &:not(:last-child) { + margin-bottom: 1.6rem; + } - &:hover, - &:focus { - color: ${colors.link}; + &:first-of-type { + font-size: 1.7rem; + font-weight: 600; + } + } - svg { - fill: ${colors.link}; - } + a { + color: ${colors.text}; + font-weight: 400; + transition: all 0.2s; - .mail { - stroke: ${colors.link}; - } - } + &:hover, + &:focus { + color: ${colors.link}; - } + svg { + fill: ${colors.link}; + } - svg { - fill: #b5b5b5; - height: 2.9rem; - transition: all .2s; + .mail { + stroke: ${colors.link}; + } } - - .contact { - li:not(:first-child) { - display: inline-block; - margin-left: 2rem; - transform: translateX(-2rem); - - @media(max-width: 650px) { - transform: translateX(-1rem); - } - } + } + + svg { + fill: #b5b5b5; + height: 2.9rem; + transition: all 0.2s; + } + + .contact { + li:not(:first-child) { + display: inline-block; + margin-left: 2rem; + transform: translateX(-2rem); + + @media (max-width: 650px) { + transform: translateX(-1rem); + } } + } - .info { - text-align: center; - margin: 5rem 0 0; + .info { + text-align: center; + margin: 5rem 0 0; - p { - margin-bottom: 2rem; - } + p { + margin-bottom: 2rem; } - + } ` const Footer: React.SFC<{}> = () => ( - -
-
-
    -
  • Gitpod
  • -
  • Features
  • -
  • Pricing
  • -
  • Blog
  • -
  • Self-Hosted
  • -
  • Log In
  • -
-
    -
  • Solutions
  • -
  • Education
  • -
  • Recruiting
  • -
  • Vendor
  • -
-
    -
  • Developer
  • -
  • Getting started
  • -
  • Documentation
  • -
  • - -
  • -
  • - -
  • -
-
    -
  • Company
  • -
  • About
  • -
  • - Careers -
  • -
  • Media Kit
  • -
- -
-
-

Copyright © TypeFox

-
Imprint | Terms of Service | Privacy Policy
-
+ +
+
+
    +
  • Gitpod
  • +
  • + Features +
  • +
  • + Pricing +
  • +
  • + Blog +
  • +
  • + Self-Hosted +
  • +
  • + + Log In + +
  • +
+
    +
  • Solutions
  • +
  • + Education +
  • +
  • + Recruiting +
  • +
  • + Vendor +
  • +
+
    +
  • Developer
  • +
  • + Getting started +
  • +
  • + Documentation +
  • +
  • + +
  • +
  • + +
  • +
+
    +
  • Company
  • +
  • + About +
  • +
  • + Careers +
  • +
  • + Media Kit +
  • +
+ +
+
+

+ Copyright ©{' '} + + TypeFox + +

+
+ Imprint | Terms of Service |  + Privacy Policy
- +
+
+
) export default Footer diff --git a/src/components/InfoCard.tsx b/src/components/InfoCard.tsx index af02bd52c..54cc3d816 100644 --- a/src/components/InfoCard.tsx +++ b/src/components/InfoCard.tsx @@ -8,79 +8,83 @@ import styled from '@emotion/styled' import { sizes } from '../styles/variables' const StyledInfoCard = styled.section` - /* --------------------------------------- */ - /* ----- Info ----- */ - /* --------------------------------------- */ + /* --------------------------------------- */ + /* ----- Info ----- */ + /* --------------------------------------- */ - section { - padding-top: 0; - } + section { + padding-top: 0; + } - .info { - @media(min-width: 831px) { - flex: 0 0 44%; + .info { + @media (min-width: 831px) { + flex: 0 0 44%; - &:last-of-type { - margin-left: auto; - } - } + &:last-of-type { + margin-left: auto; + } + } - @media(max-width: 830px) { - &:not(:last-of-type) { - margin-bottom: 5rem; - } - } + @media (max-width: 830px) { + &:not(:last-of-type) { + margin-bottom: 5rem; + } + } - &-container { - display: flex; + &-container { + display: flex; - @media(max-width: 830px) { - flex-direction: column; - } - } + @media (max-width: 830px) { + flex-direction: column; + } + } - p:last-of-type { - margin-bottom: 2rem; - } + p:last-of-type { + margin-bottom: 2rem; + } - a { - &:not(:last-of-type) { - margin-right: 2rem; - } - } + a { + &:not(:last-of-type) { + margin-right: 2rem; + } + } - @media(max-width: ${sizes.breakpoints.md}) { - &:not(:last-child) { - margin-bottom: 8rem; - } - } + @media (max-width: ${sizes.breakpoints.md}) { + &:not(:last-child) { + margin-bottom: 8rem; + } } + } ` const InfoCard: React.SFC<{}> = () => ( - -
-
-

Getting Started with Gitpod

-

You can simply start coding in Gitpod by prefixing any GitHub URL with gitpod.io/#

-

For a more detailed description of Gitpod and its IDE, Theia, please have a look at our documentation.

- Gitpod Docs -
-
-

Do You Need Help?

-

If you have any question, issue or feedback, please get in touch. We love to hear your feedback and help you out.

- - Mail Logo - - - Discourse Logo - - - Twitter Logo - -
-
-
+ +
+
+

Getting Started with Gitpod

+

+ You can simply start coding in Gitpod by prefixing any GitHub URL with gitpod.io/# +

+

For a more detailed description of Gitpod and its IDE, Theia, please have a look at our documentation.

+ + Gitpod Docs + +
+
+

Do You Need Help?

+

If you have any question, issue or feedback, please get in touch. We love to hear your feedback and help you out.

+ + Mail Logo + + + Discourse Logo + + + Twitter Logo + +
+
+
) export default InfoCard diff --git a/src/components/LayoutMain.tsx b/src/components/LayoutMain.tsx index 4241ea142..199c98f41 100644 --- a/src/components/LayoutMain.tsx +++ b/src/components/LayoutMain.tsx @@ -14,7 +14,9 @@ interface LayoutMainProps { } const LayoutMain: React.SFC = ({ children, className }) => ( - {children} + + {children} + ) export default LayoutMain diff --git a/src/components/Linkset.tsx b/src/components/Linkset.tsx index dacbb1984..86325a4df 100644 --- a/src/components/Linkset.tsx +++ b/src/components/Linkset.tsx @@ -5,67 +5,59 @@ import { colors } from '../styles/variables' import { Link } from 'gatsby' const StyledLinkSet = styled.div` - - &:not(:last-child) { - margin-bottom: 2rem; + &:not(:last-child) { + margin-bottom: 2rem; + } + + a { + display: inline-block; + font-size: 1.5rem; + border-left: solid 1px transparent; + color: ${colors.text}; + font-weight: 400; + + &:hover { + color: ${colors.lightBlue}; } - a { - display: inline-block; - font-size: 1.5rem; - border-left: solid 1px transparent; - color: ${colors.text}; - font-weight: 400; - - &:hover { - color: ${colors.lightBlue}; - } - - &.active { - color: ${colors.lightBlue}; - border-left: solid 1px ${colors.lightBlue}; - } - - &.caption { - margin-bottom: .4rem; - font-weight: 400; - font-size: 1.7rem; - padding-left: 1.0rem; - } + &.active { + color: ${colors.lightBlue}; + border-left: solid 1px ${colors.lightBlue}; + } - &:not(.caption) { - padding-left: 1.8rem; - } + &.caption { + margin-bottom: 0.4rem; + font-weight: 400; + font-size: 1.7rem; + padding-left: 1rem; + } + &:not(.caption) { + padding-left: 1.8rem; } + } ` interface LinkSetProps { - caption: string - path: string + caption: string + path: string } class Linkset extends React.Component { - - render() { - - const { caption, path, children } = this.props - - return ( - -
  • - - {caption} - -
  • - {children} -
    - ) - } + render() { + const { caption, path, children } = this.props + + return ( + +
  • + + {caption} + +
  • + {children} +
    + ) + } } export default Linkset diff --git a/src/components/MoreInfo.tsx b/src/components/MoreInfo.tsx index 9a6a3e7d4..b73557aee 100644 --- a/src/components/MoreInfo.tsx +++ b/src/components/MoreInfo.tsx @@ -6,102 +6,99 @@ import { Link } from 'gatsby' import MapGrey from '../resources/map-grey.svg' const StyledPricingLinks = styled.section` - max-width: 850px; - display: flex; - align-items: center; - margin: 0 auto; - - @media(max-width: ${sizes.breakpoints.md}) { - padding-bottom: 8rem; - } + max-width: 850px; + display: flex; + align-items: center; + margin: 0 auto; + + @media (max-width: ${sizes.breakpoints.md}) { + padding-bottom: 8rem; + } - @media(max-width: 720px) { - flex-direction: column; - text-align: center; - max-width: 550px; + @media (max-width: 720px) { + flex-direction: column; + text-align: center; + max-width: 550px; - .btn-wrapper { - justify-content: center; - } + .btn-wrapper { + justify-content: center; } + } - img { - flex: 1; - height: 12rem; + img { + flex: 1; + height: 12rem; - @media(max-width: 720px) { - max-width: 10rem; - margin-bottom: 2rem; - } + @media (max-width: 720px) { + max-width: 10rem; + margin-bottom: 2rem; } - - div { - flex: 0 0 75%; - padding-left: 4rem; - border-left: ${borders.bold}; + } - @media(max-width: 720px) { - border-left: none; - padding-left: 0; - } - } + div { + flex: 0 0 75%; + padding-left: 4rem; + border-left: ${borders.bold}; - h2 { - margin-bottom: 5rem; + @media (max-width: 720px) { + border-left: none; + padding-left: 0; } + } - h3 { - font-size: 110%; - margin-bottom: .5rem; - } + h2 { + margin-bottom: 5rem; + } + h3 { + font-size: 110%; + margin-bottom: 0.5rem; + } ` export interface PricingLinksProps { - img?: JSX.Element - title?: JSX.Element - text?: JSX.Element - links?: JSX.Element + img?: JSX.Element + title?: JSX.Element + text?: JSX.Element + links?: JSX.Element } -const PricingLinks = ({ - img, - title, - text, - links -}: PricingLinksProps) => { - let Img = img - let Title = title - let Text = text - let Links = links - if (!(img && title && text && links)) { - Img = Explore Gitpod - Title = <>Explore Gitpod - Text = (<> - Learn about collaboration, workspace sharing, reproducible snapshots, supported language features, and much more. - ) - Links = (<> - See Features - See Blog - ) - } - return ( -
    - - {Img} -
    -

    {Title}

    -

    - {Text} -

    - - {Links} - -
    -
    -
    +const PricingLinks = ({ img, title, text, links }: PricingLinksProps) => { + let Img = img + let Title = title + let Text = text + let Links = links + if (!(img && title && text && links)) { + Img = Explore Gitpod + Title = ( + <> + Explore Gitpod + + ) + Text = <>Learn about collaboration, workspace sharing, reproducible snapshots, supported language features, and much more. + Links = ( + <> + + See Features + + + See Blog + + ) + } + return ( +
    + + {Img} +
    +

    {Title}

    +

    {Text}

    + {Links} +
    +
    +
    + ) } export default PricingLinks - diff --git a/src/components/Nav.tsx b/src/components/Nav.tsx index 00393ad1b..4fb8f2ed9 100644 --- a/src/components/Nav.tsx +++ b/src/components/Nav.tsx @@ -209,103 +209,126 @@ const StyledNav = styled.nav` ` const Nav = () => { - const [isNavRendered, setIsNavRendered] = useState(false) + const [isNavRendered, setIsNavRendered] = useState(false) - const unLock = () => { - if (window.innerWidth >= 1240) { - setIsNavRendered(false) - } + const unLock = () => { + if (window.innerWidth >= 1240) { + setIsNavRendered(false) } + } - useEffect(() => { - window.addEventListener('resize', unLock) - - return () => { - window.removeEventListener('resize', unLock) - } - }) + useEffect(() => { + window.addEventListener('resize', unLock) - const toggleNavigation = () => { - setIsNavRendered(!isNavRendered) + return () => { + window.removeEventListener('resize', unLock) } - - return ( -
    - -
    - -
    - Gitpod Logo -
    - Log In -
    - -
    -
    -
    - - -
      -
    • Features
    • -
    • Self-Hosted
    • -
    • Pricing
    • -
    • - -
    • -
    • Log In
    • -
    - -
    + }) + + const toggleNavigation = () => { + setIsNavRendered(!isNavRendered) + } + + return ( +
    + +
    + +
    + + Gitpod Logo + +
    + + Log In + +
    + +
    -
    - ) +
    + +
      +
    • + + Features + +
    • +
    • + + Self-Hosted + +
    • +
    • + + Pricing + +
    • +
    • + +
    • +
    • + + Log In + +
    • +
    + +
    +
    + ) } export default Nav diff --git a/src/components/NewsletterForm.tsx b/src/components/NewsletterForm.tsx index 296753959..9f98b4f31 100644 --- a/src/components/NewsletterForm.tsx +++ b/src/components/NewsletterForm.tsx @@ -4,50 +4,49 @@ import styled from '@emotion/styled' import { sizes, borders } from '../styles/variables' const StyledNewsletterForm = styled.section` - /* ------------------------------------------- */ - /* ----- Section Newsletter ----- */ - /* ------------------------------------------- */ - - .newsletter { - padding: 12rem 0; - - @media(max-width: ${sizes.breakpoints.md}) { - padding: 8rem 0; - } - - &__input { - margin: 0 1.5rem 3rem 0; - padding: 1.2rem 2.5rem; - border: ${borders.light1}; - border-radius: 100px; - - @media(max-width: ${sizes.breakpoints.sm}) { - width: 100%; - } - } - - &__text { - margin: -3rem 0 3rem; - } + /* ------------------------------------------- */ + /* ----- Section Newsletter ----- */ + /* ------------------------------------------- */ + + .newsletter { + padding: 12rem 0; + + @media (max-width: ${sizes.breakpoints.md}) { + padding: 8rem 0; + } + + &__input { + margin: 0 1.5rem 3rem 0; + padding: 1.2rem 2.5rem; + border: ${borders.light1}; + border-radius: 100px; + + @media (max-width: ${sizes.breakpoints.sm}) { + width: 100%; + } + } + + &__text { + margin: -3rem 0 3rem; } + } ` const NewsletterForm: React.SFC<{}> = () => ( -
    - -

    Never Miss a Blog Post

    -

    Sign up for the newsletter and stay informs about the latest news from Gitpod and its community.

    -
    { - e.preventDefault() - }}> - - -
    -
    -
    +
    + +

    Never Miss a Blog Post

    +

    Sign up for the newsletter and stay informs about the latest news from Gitpod and its community.

    +
    { + e.preventDefault() + }} + > + + +
    +
    +
    ) export default NewsletterForm diff --git a/src/components/Offers.tsx b/src/components/Offers.tsx index 445016384..2f7c4c3d8 100644 --- a/src/components/Offers.tsx +++ b/src/components/Offers.tsx @@ -5,81 +5,74 @@ import styled from '@emotion/styled' import { sizes } from '../styles/variables' const StyledOffers = styled.section` - /* --------------------------------------- */ - /* ----- Offers ----- */ - /* --------------------------------------- */ + /* --------------------------------------- */ + /* ----- Offers ----- */ + /* --------------------------------------- */ - .offers { - display: flex; - justify-content: center; - margin-top: 15rem; + .offers { + display: flex; + justify-content: center; + margin-top: 15rem; - @media(max-width: ${sizes.breakpoints.md}) { - flex-direction: column; - align-items: center; - } + @media (max-width: ${sizes.breakpoints.md}) { + flex-direction: column; + align-items: center; } + } - .btn-container { - margin: 5rem 0; - text-align: center; - } - - @media(max-width: ${sizes.breakpoints.md}) { - h2 { - margin-bottom: 5rem; - } + .btn-container { + margin: 5rem 0; + text-align: center; + } - br { - display: none; - } + @media (max-width: ${sizes.breakpoints.md}) { + h2 { + margin-bottom: 5rem; } + br { + display: none; + } + } ` interface OffersProps { - title: string - offers: PricingBoxProps[], - para: JSX.Element + title: string + offers: PricingBoxProps[] + para: JSX.Element } - const Offers: React.SFC = ({ offers, title, para }) => ( - -
    -
    -

    {title}

    - { para } -
    -
    - { - offers.map( - (offer, i) => ( - - ) - ) - } -
    -
    -
    + +
    +
    +

    {title}

    + {para} +
    +
    + {offers.map((offer, i) => ( + + ))} +
    +
    +
    ) - export default Offers diff --git a/src/components/OnBoarding.tsx b/src/components/OnBoarding.tsx index be58168e1..63c6f6fd4 100644 --- a/src/components/OnBoarding.tsx +++ b/src/components/OnBoarding.tsx @@ -4,18 +4,20 @@ import styled from '@emotion/styled' import { sizes } from '../styles/variables' const StyledOnBoarding = styled.section` - text-align: center; + text-align: center; - @media(max-width: ${sizes.breakpoints.md}) { - padding: 7rem 0; - } + @media (max-width: ${sizes.breakpoints.md}) { + padding: 7rem 0; + } ` -const OnBoarding: React.SFC<{link: string}> = ({ link }) => ( - -

    Would You Like to Have an Onboarding Session?

    - Schedule a Call -
    +const OnBoarding: React.SFC<{ link: string }> = ({ link }) => ( + +

    Would You Like to Have an Onboarding Session?

    + + Schedule a Call + +
    ) export default OnBoarding diff --git a/src/components/PopOver.tsx b/src/components/PopOver.tsx index c879a54ac..e5ca2d2f1 100644 --- a/src/components/PopOver.tsx +++ b/src/components/PopOver.tsx @@ -64,42 +64,41 @@ const StyledDescripion = styled.span` } ` -class Description extends React.Component<{description: string, textPosition?: string}, {}> { - - state={ - isRendered: false - } - - handleClick = () => { - this.setState({isRendered: !this.state.isRendered}) - } - - handleMouseEnter = () => { - this.setState({isRendered: true}) - } - - handleMouseLeave = () => { - this.setState({isRendered: false}) - } - - render() { - const { isRendered } = this.state - const { description } = this.props - const positionBottom = this.props.textPosition === 'bottom' - - return ( - - - { isRendered ?
    { description }
    : null } -
    - ) - } +class Description extends React.Component<{ description: string; textPosition?: string }, {}> { + state = { + isRendered: false + } + + handleClick = () => { + this.setState({ isRendered: !this.state.isRendered }) + } + + handleMouseEnter = () => { + this.setState({ isRendered: true }) + } + + handleMouseLeave = () => { + this.setState({ isRendered: false }) + } + + render() { + const { isRendered } = this.state + const { description } = this.props + const positionBottom = this.props.textPosition === 'bottom' + + return ( + + + {isRendered ?
    {description}
    : null} +
    + ) + } } export default Description diff --git a/src/components/PricingBox.tsx b/src/components/PricingBox.tsx index d3f19511d..552ec537b 100644 --- a/src/components/PricingBox.tsx +++ b/src/components/PricingBox.tsx @@ -5,13 +5,13 @@ import { colors, sizes } from '../styles/variables' import IconTick from '../resources/icon-tick.svg' interface StyledPricingBoxProps { - transform?: string - background?: boolean - hideButton?: boolean - banner?: string - bannerColor?: string - btnBackground?: boolean - isTitleOutside?: boolean + transform?: string + background?: boolean + hideButton?: boolean + banner?: string + bannerColor?: string + btnBackground?: boolean + isTitleOutside?: boolean } const StyledPricingBox = styled.div` @@ -19,34 +19,34 @@ const StyledPricingBox = styled.div` margin: 2rem 1rem; padding: 3rem 2.8rem; font-size: 95%; - min-height: ${({ isTitleOutside }) => isTitleOutside ? '35rem' : '48rem'}; + min-height: ${({ isTitleOutside }) => (isTitleOutside ? '35rem' : '48rem')}; min-width: 20rem; max-width: 26rem; width: 25%; text-align: center; - color: ${({ background }) => background ? colors.white : null}; - background: ${({ background }) => background ? 'url("https://www.gitpod.io/galaxy.jpg")' : colors.white}; - background-size: ${({ background }) => background ? 'cover' : null}; - background-position: ${({ background }) => background ? 'left' : null}; + color: ${({ background }) => (background ? colors.white : null)}; + background: ${({ background }) => (background ? 'url("https://www.gitpod.io/galaxy.jpg")' : colors.white)}; + background-size: ${({ background }) => (background ? 'cover' : null)}; + background-position: ${({ background }) => (background ? 'left' : null)}; border: 1px solid ${colors.offWhite2}; background-color: ${colors.offWhite}; border-radius: 3px; - margin-top: ${({ isTitleOutside }) => isTitleOutside ? '6rem' : '2rem'}; - z-index: ${({ isTitleOutside }) => isTitleOutside ? '1000' : 'none'};; + margin-top: ${({ isTitleOutside }) => (isTitleOutside ? '6rem' : '2rem')}; + z-index: ${({ isTitleOutside }) => (isTitleOutside ? '1000' : 'none')};; @media(min-width: calc(${sizes.breakpoints.md} + 1px)) { - z-index: ${({ transform }) => transform ? '1' : null}; + z-index: ${({ transform }) => (transform ? '1' : null)}; } @media(min-width: calc(${sizes.breakpoints.lg} + 1px)) { - transform: ${({ transform }) => transform ? transform : null}; + transform: ${({ transform }) => (transform ? transform : null)}; } @media(max-width: ${sizes.breakpoints.lg}) { min-height: 50rem; padding: 3rem 2rem; margin-bottom: 5rem; - min-height: ${({ isTitleOutside }) => isTitleOutside ? '35rem' : '51rem'}; + min-height: ${({ isTitleOutside }) => (isTitleOutside ? '35rem' : '51rem')}; } @media(max-width: 1096px) { @@ -54,11 +54,11 @@ const StyledPricingBox = styled.div` } @media(max-width: 860px) { - margin-top: ${({ banner }) => banner ? '4rem' : ''}; + margin-top: ${({ banner }) => (banner ? '4rem' : '')}; } @media(max-width: ${sizes.breakpoints.md}) { - min-height: ${({ isTitleOutside }) => isTitleOutside ? '35rem' : '51rem'}; + min-height: ${({ isTitleOutside }) => (isTitleOutside ? '35rem' : '51rem')}; min-width: 30rem; padding: 2rem 3rem; } @@ -78,7 +78,7 @@ const StyledPricingBox = styled.div` h4 { font-size: 1.8rem; - margin: ${({ isTitleOutside }) => isTitleOutside ? '-7rem 0 6rem' : '' } + margin: ${({ isTitleOutside }) => (isTitleOutside ? '-7rem 0 6rem' : '')} } img, object { @@ -87,7 +87,7 @@ const StyledPricingBox = styled.div` height: 8rem; width: 8rem; - display: ${({ isTitleOutside }) => isTitleOutside ? 'none' : '' }; + display: ${({ isTitleOutside }) => (isTitleOutside ? 'none' : '')}; @media(max-width: ${sizes.breakpoints.md}) { margin: 1.5rem 0 1rem; @@ -164,7 +164,7 @@ const StyledPricingBox = styled.div` } @media(min-width: calc(${sizes.breakpoints.lg} + 1px)) { - bottom: ${({ transform }) => transform ? '2rem' : '1.5rem'}; + bottom: ${({ transform }) => (transform ? '2rem' : '1.5rem')}; } } @@ -179,7 +179,7 @@ const StyledPricingBox = styled.div` } .is-hidden { - display: ${({ hideButton }) => hideButton ? 'none' : ''}; + display: ${({ hideButton }) => (hideButton ? 'none' : '')}; } .banner { @@ -195,7 +195,7 @@ const StyledPricingBox = styled.div` width: 20ch; margin: 0 auto; padding: .8rem 0; - color: ${({ bannerColor }) => bannerColor ? bannerColor : ''}; + color: ${({ bannerColor }) => (bannerColor ? bannerColor : '')}; font-size: 90%; font-weight: 600; } @@ -212,13 +212,13 @@ const StyledPricingBox = styled.div` } .btn { - background: ${({ btnBackground }) => btnBackground ? colors.link : ''}; - color: ${({ btnBackground }) => btnBackground ? colors.white : ''}; - border-color: ${({ btnBackground }) => btnBackground ? colors.link : ''}; + background: ${({ btnBackground }) => (btnBackground ? colors.link : '')}; + color: ${({ btnBackground }) => (btnBackground ? colors.white : '')}; + border-color: ${({ btnBackground }) => (btnBackground ? colors.link : '')}; &:hover { - background: ${({ btnBackground }) => btnBackground ? colors.lightBlue : ''}; - border-color: ${({ btnBackground }) => btnBackground ? colors.lightBlue : ''}; + background: ${({ btnBackground }) => (btnBackground ? colors.lightBlue : '')}; + border-color: ${({ btnBackground }) => (btnBackground ? colors.lightBlue : '')}; } } @@ -234,79 +234,82 @@ const StyledPricingBox = styled.div` ` export interface PricingBoxProps { - title: string - img: JSX.Element - price?: string | JSX.Element - duration?: string - feature?: string | JSX.Element - features?: (string | JSX.Element)[] - transform?: string - background?: boolean - btnText?: string - btnBackground?: boolean - link?: string - hideButton?: true - btn?: JSX.Element - text?: string - banner?: string - bannerColor?: string - subAction?: JSX.Element - isTitleOutside?: boolean + title: string + img: JSX.Element + price?: string | JSX.Element + duration?: string + feature?: string | JSX.Element + features?: (string | JSX.Element)[] + transform?: string + background?: boolean + btnText?: string + btnBackground?: boolean + link?: string + hideButton?: true + btn?: JSX.Element + text?: string + banner?: string + bannerColor?: string + subAction?: JSX.Element + isTitleOutside?: boolean } const PricingBox: React.SFC = ({ - title, - img, - price, - duration, - feature, - features, - btnText, - btnBackground, - transform, - background, - link, - hideButton, - btn, - text, - banner, - bannerColor, - subAction, - isTitleOutside + title, + img, + price, + duration, + feature, + features, + btnText, + btnBackground, + transform, + background, + link, + hideButton, + btn, + text, + banner, + bannerColor, + subAction, + isTitleOutside }) => ( - -

    {title}

    - {img ? img : null} - {price ?
    {price}
    : null} - {duration ?
    {duration}
    : null} - {feature ?
    {feature}
    : null} - {features && features.length ? -
      - {features.map((f, i) =>
    • {f}
    • )} -
    - : null} -
    - - {btnText ? btnText : 'Start for Free'} - -
    - {text ?

    {text}

    : null} - {btn ? btn : null} - {subAction ? subAction : } -
    - {banner ?

    {banner}

    : null} -
    - ) + +

    {title}

    + {img ? img : null} + {price ?
    {price}
    : null} + {duration ?
    {duration}
    : null} + {feature ?
    {feature}
    : null} + {features && features.length ? ( +
      + {features.map((f, i) => ( +
    • {f}
    • + ))} +
    + ) : null} +
    + + {btnText ? btnText : 'Start for Free'} + +
    + {text ?

    {text}

    : null} + {btn ? btn : null} + {subAction ? subAction : + {banner ? ( +
    +

    {banner}

    +
    + ) : null} + +) export default PricingBox diff --git a/src/components/PricingTable.tsx b/src/components/PricingTable.tsx index 234dd41c8..041fc0d08 100644 --- a/src/components/PricingTable.tsx +++ b/src/components/PricingTable.tsx @@ -4,118 +4,115 @@ import styled from '@emotion/styled' import { colors, sizes } from '../styles/variables' const StyledPricingTable = styled.section` - padding-bottom: 0; - margin-bottom: 5rem; + padding-bottom: 0; + margin-bottom: 5rem; - th { - - span { - display: block; - } + th { + span { + display: block; + } - img { - height: 2rem; - transform: translateY(5px); - margin-right: 1rem; + img { + height: 2rem; + transform: translateY(5px); + margin-right: 1rem; - @media(max-width: ${sizes.breakpoints.md}) { - height: 1.7rem; - transform: translateY(3px); - margin-right: .5rem; - } + @media (max-width: ${sizes.breakpoints.md}) { + height: 1.7rem; + transform: translateY(3px); + margin-right: 0.5rem; + } - @media(max-width: ${sizes.breakpoints.md}) { - height: 1.5rem; - } - } + @media (max-width: ${sizes.breakpoints.md}) { + height: 1.5rem; + } } + } - .header { - th { - text-align: center; - font-weight: 600; - font-size: 2rem; - padding: 3rem; - width: 25%; - - @media(max-width: ${sizes.breakpoints.md}) { - padding: 2rem; - } - - @media(max-width: ${sizes.breakpoints.md}) { - padding: 1.5rem; - } - - span { - font-size: 1.6rem; - font-weight: 400; - - @media(max-width: ${sizes.breakpoints.md}) { - font-size: 1.4rem; - } - - @media(max-width: ${sizes.breakpoints.md}) { - font-size: 1.2rem; - } - - span { - display: inline; - color: ${colors.link}; - font-weight: 600; - } - } + .header { + th { + text-align: center; + font-weight: 600; + font-size: 2rem; + padding: 3rem; + width: 25%; + + @media (max-width: ${sizes.breakpoints.md}) { + padding: 2rem; + } + + @media (max-width: ${sizes.breakpoints.md}) { + padding: 1.5rem; + } + + span { + font-size: 1.6rem; + font-weight: 400; + + @media (max-width: ${sizes.breakpoints.md}) { + font-size: 1.4rem; } - } - .buttons { - th, td { - background: none; - border: none; + @media (max-width: ${sizes.breakpoints.md}) { + font-size: 1.2rem; } - .btn { - margin-top: 2rem; + span { + display: inline; + color: ${colors.link}; + font-weight: 600; } + } } + } - .description { - display: inline-block; - transform: translateY(-.5rem); - - &__text { - position: absolute; - top: 0; - left: 3rem; - width: 25rem; - min-width: 15rem; - - @media(max-width: ${sizes.breakpoints.md}) { - width: 18rem; - } - } + .buttons { + th, + td { + background: none; + border: none; } + .btn { + margin-top: 2rem; + } + } + + .description { + display: inline-block; + transform: translateY(-0.5rem); + + &__text { + position: absolute; + top: 0; + left: 3rem; + width: 25rem; + min-width: 15rem; + + @media (max-width: ${sizes.breakpoints.md}) { + width: 18rem; + } + } + } ` interface PricingTableProps { - title: string - paragraph: JSX.Element | string - id?: string - rows?: number + title: string + paragraph: JSX.Element | string + id?: string + rows?: number } const PricingTable: React.SFC = ({ title, paragraph, children, id, rows }) => ( -
    - -

    {title}

    -

    {paragraph}

    -
    - - {children} -
    -
    -
    -
    +
    + +

    {title}

    +

    {paragraph}

    +
    + {children}
    +
    +
    +
    ) export default PricingTable diff --git a/src/components/Quote.tsx b/src/components/Quote.tsx index fe8cb17d7..0475a1698 100644 --- a/src/components/Quote.tsx +++ b/src/components/Quote.tsx @@ -5,81 +5,84 @@ import QuoteIcon from '../resources/quote.svg' import { colors, sizes } from '../styles/variables' const StyledQuote = styled.section` - padding: 12rem 0; - margin: 0 auto; + padding: 12rem 0; + margin: 0 auto; + + @media (max-width: ${sizes.breakpoints.md}) { + padding: 8rem 0; + } + + h4 { + position: relative; + display: flex; + justify-content: center; + align-items: center; + text-align: center; + color: ${colors.text}; + font-size: 2.5rem; + font-weight: 400; + + @media (max-width: ${sizes.breakpoints.sm}) { + font-size: 2.3rem; + } + + span { + max-width: 80rem; + + @media (max-width: 560px) { + padding: 0 1rem; + } + + @media (max-width: ${sizes.breakpoints.sm}) { + width: 100%; + } + } + + object { + height: 7rem; + + &:first-of-type { + transform: rotate(-180deg); + margin-right: 3rem; + } + + &:last-of-type { + margin-left: 3rem; + } + + @media (max-width: ${sizes.breakpoints.md}) { + height: 5rem; + margin: 0 2rem; + } - @media(max-width: ${sizes.breakpoints.md}) { - padding: 8rem 0; + @media (max-width: 580px) { + display: none; + } } - h4 { - position: relative; - display: flex; - justify-content: center; - align-items: center; - text-align: center; - color: ${colors.text}; - font-size: 2.5rem; - font-weight: 400; - - @media(max-width: ${sizes.breakpoints.sm}) { - font-size: 2.3rem; - } - - span { - max-width: 80rem; - - @media(max-width: 560px) { - padding: 0 1rem; - } - - @media(max-width: ${sizes.breakpoints.sm}) { - width: 100%; - } - } - - object { - height: 7rem; - - &:first-of-type { - transform: rotate(-180deg); - margin-right: 3rem; - } - - &:last-of-type { - margin-left: 3rem; - } - - @media(max-width: ${sizes.breakpoints.md}) { - height: 5rem; - margin: 0 2rem; - } - - @media(max-width: 580px) { - display: none; - } - } - - i { - @media(min-width: 581px) { - display: none; - } - } + i { + @media (min-width: 581px) { + display: none; + } } + } ` interface QuoteProps { - title: string | JSX.Element + title: string | JSX.Element } -const Quote: React.SFC = ({title}) => ( - -

    - - {title} - - - +const Quote: React.SFC = ({ title }) => ( + +

    + + + {title} + + + + + ) export default Quote diff --git a/src/components/TextBox.tsx b/src/components/TextBox.tsx index baeddb43a..44345ba3a 100644 --- a/src/components/TextBox.tsx +++ b/src/components/TextBox.tsx @@ -4,46 +4,44 @@ import styled from '@emotion/styled' import { colors, borders } from '../styles/variables' const StyledTextBox = styled.div` - font-size: 90%; - - .box { - max-width: 75rem; - margin: 10rem auto; - padding: 8rem 5rem; - background: ${colors.white}; - border-radius: 3px; - border: ${borders.light2}; - } - - h1 { - margin-bottom: 6rem; - } - - h2 { - margin: 6rem 0 5rem; - } - - h3 { - margin-top: 4rem; - } - - li + li { - margin-top: 2rem; - } - - .model { - padding: 2rem 3rem; - border: ${borders.light}; - font-size: 95%; - } + font-size: 90%; + + .box { + max-width: 75rem; + margin: 10rem auto; + padding: 8rem 5rem; + background: ${colors.white}; + border-radius: 3px; + border: ${borders.light2}; + } + + h1 { + margin-bottom: 6rem; + } + + h2 { + margin: 6rem 0 5rem; + } + + h3 { + margin-top: 4rem; + } + + li + li { + margin-top: 2rem; + } + + .model { + padding: 2rem 3rem; + border: ${borders.light}; + font-size: 95%; + } ` const TextBox: React.SFC<{}> = ({ children }) => ( - -
    - { children } -
    -
    + +
    {children}
    +
    ) export default TextBox diff --git a/src/components/TextCard.tsx b/src/components/TextCard.tsx index 94635a6f5..f3e3ac7ca 100644 --- a/src/components/TextCard.tsx +++ b/src/components/TextCard.tsx @@ -12,13 +12,13 @@ import Theia from '../resources/theia-ide.svg' import Docker from '../resources/docker.svg' const Logos: any = { - Bitbucket: Bitbucket, - Github: Github, - Gitlab: Gitlab, - Git: Git, - VSC: VSC, - Theia: Theia, - Docker: Docker + Bitbucket, + Github, + Gitlab, + Git, + VSC, + Theia, + Docker } const StyledTextCard = styled.div` @@ -69,21 +69,27 @@ const StyledTextCard = styled.div` ` interface TextCardProps { - title: string - paragraphs: (string | JSX.Element)[] - more?: JSX.Element - logos?: string[] + title: string + paragraphs: (string | JSX.Element)[] + more?: JSX.Element + logos?: string[] } -const TextCard: React.SFC = ({title, paragraphs, more, logos}) => ( - -

    {title}

    - { paragraphs.map((p, i) =>

    {p}

    ) } - { more ? more : null } - {logos && logos.length ?
    - {logos.map((logo, i) => {`${logo})} -
    : null} -
    +const TextCard: React.SFC = ({ title, paragraphs, more, logos }) => ( + +

    {title}

    + {paragraphs.map((p, i) => ( +

    {p}

    + ))} + {more ? more : null} + {logos && logos.length ? ( +
    + {logos.map((logo, i) => ( + {`${logo} + ))} +
    + ) : null} +
    ) export default TextCard diff --git a/src/components/TextCards.tsx b/src/components/TextCards.tsx index 434aabcb9..bbe8b582e 100644 --- a/src/components/TextCards.tsx +++ b/src/components/TextCards.tsx @@ -3,7 +3,7 @@ import React from 'react' import styled from '@emotion/styled' import { sizes } from '../styles/variables' -const StyledTextCards = styled.section` +const StyledTextCards = styled.section` .text-cards { display: flex; flex-wrap: wrap; @@ -20,18 +20,16 @@ const StyledTextCards = styled.section` ` interface TextCardsProps { - title?: string + title?: string } const TextCards: React.SFC = ({ title, children }) => ( -
    - - { title ?

    {title}

    : null } -
    - {children} -
    -
    -
    +
    + + {title ?

    {title}

    : null} +
    {children}
    +
    +
    ) export default TextCards diff --git a/src/components/blog/PostBanner.tsx b/src/components/blog/PostBanner.tsx index 8d1ef76ab..c8bf7205d 100644 --- a/src/components/blog/PostBanner.tsx +++ b/src/components/blog/PostBanner.tsx @@ -4,89 +4,91 @@ import styled from '@emotion/styled' import { colors } from '../../styles/variables' const StyledPostBanner = styled.header` - position: relative; - overflow-x: hidden; + position: relative; + overflow-x: hidden; + border-top-left-radius: 2px; + border-top-right-radius: 2px; + + .bg { + display: block; + background-size: cover; + background-position: center; + height: 40rem; border-top-left-radius: 2px; border-top-right-radius: 2px; + } - .bg { - display: block; - background-size: cover; - background-position: center; - height: 40rem; - border-top-left-radius: 2px; - border-top-right-radius: 2px; - } + .contents { + display: flex; + flex-direction: column; + align-items: flex-start; + } - .contents { - display: flex; - flex-direction: column; - align-items: flex-start; - } - - h1 { - margin-top: 2rem; - } + h1 { + margin-top: 2rem; + } - h3 { - margin: 0; - color: ${colors.text}; - font-weight: 200; - } + h3 { + margin: 0; + color: ${colors.text}; + font-weight: 200; + } - .info { - display: flex; - width: 100%; - justify-content: space-between; - } + .info { + display: flex; + width: 100%; + justify-content: space-between; + } - .author { - display: flex; - flex-direction: column; - } + .author { + display: flex; + flex-direction: column; + } - .share { - display: flex; - } + .share { + display: flex; + } - span + span { - margin-top: 1rem; - } + span + span { + margin-top: 1rem; + } - span:last-of-type { - &::after { - content: ''; - display: block; - margin-top: 2rem; - height: 5px; - width: 12rem; - background: ${colors.offWhite4}; - border-radius: 5px; - } + span:last-of-type { + &::after { + content: ''; + display: block; + margin-top: 2rem; + height: 5px; + width: 12rem; + background: ${colors.offWhite4}; + border-radius: 5px; } + } ` interface PostBannerProps { - teaserImage?: string - title: string - subtitle: string - date: JSX.Element - author: JSX.Element - shareButtons: JSX.Element + teaserImage?: string + title: string + subtitle: string + date: JSX.Element + author: JSX.Element + shareButtons: JSX.Element } const PostBanner: React.SFC = ({ title, subtitle, teaserImage, date, author, shareButtons }) => ( - -