The aim of this guide is to demonstrate the fastest way to create a client-side web app and get it deployed. I'm writing it for myself in preparation for an upcoming Startup Weekend event. We'll keep it CLI-heavy and automation-friendly as opposed to point-and-clicking our way through web dashboards.
Tech
- GitLab - GitLab's unlimited private repos, amazing CI and free public pages make it an excellent choice for deploying static sites.
- React -
create-react-app
is the quickest way to start hacking on React without messing around with Babel and Webpack configs. - ES6 - we'll use plain ES6 instead of something fancier like TypeScript, ReasonML, or Elm because the focus is speed and simplicity.
Caveats
- We'll eschew typical production concerns like performance, security, configuration, and tests since we're aiming to build an MVP in a weekend.
- Even though a web app will likely need some CRUD we won't spend the time and effort to use an actual database; instead the prototype will use client-side state to simulate how it will work.
Prerequisites
This guide assumes Homebrew but the following packages can be installed by many other means.
_10brew install yarn_10brew install jq_10brew install ruby
GitLab
Let's create a GitLab group so we can collaborate with our teammates.
_29gem install gitlab_29export GITLAB_API_ENDPOINT=https://gitlab.com/api/v4_29_29# visit https://gitlab.com/profile/personal_access_tokens and generate a token_29echo "Enter your GitLab token"_29 read -s gitlab_token_29export GITLAB_API_PRIVATE_TOKEN=$gitlab_token_29_29gitlab user # make sure we're authenticated_29user_id=`gitlab user --json | jq '.result.id'`_29echo $gitlab_user_id # this should be an integer_29_29gitlab help create_group_29# pick your own unique group name and group path_29# these are global on GitLab_29group_json=`gitlab create_group startup-weekend-2019 startup-weekend-2019 --json`_29echo $group_json | jq_29group_id=`echo $group_json | jq '.result.id'`_29echo $group_id # should be an integer_29_29# add your teammates (you'll need their GitLab user IDs)_29gitlab help add_group_member_29# we'll give everyone owner permissions for this exercise_29# see https://docs.gitlab.com/ee/api/access_requests.html for docs_29access_level=50_29gitlab add_group_member $group_id $user_id $access_level_29# the above will fail because we're already a member_29# instead perform this for gitlab users on your team that you want to add_29# you can do this via the web dashboard if you like
Now that our group is setup and members added, let's create the repo under it.
_10gitlab help create_project_10project_json=`gitlab create_project app "{namespace_id: '$group_id'}" --json`_10# confirm it succeeded:_10echo $project_json
Node.js React App
Let's generate a fresh React app:
_10yarn global add create-react-app_10create-react-app startup-weekend_10cd startup-weekend_10yarn install
Now configure the git repo we setup in the previous step and push to it:
_10git remote add origin `echo $project_json | jq -r '.result.ssh_url_to_repo'`_10git push -u origin master
Congratulations, your app source is now safe in GitLab. The next step is to deploy!
Deployment on GitLab Pages
First we need to specify the homepage
property in package.json
so CRA
computes the correct asset paths when it builds assets.
_10group_path=`echo $group_json | jq -r '.result.full_path'`_10project_path=`echo $project_json | jq -r '.result.path'`_10gitlab_pages_url=`echo https://$group_path.gitlab.io/$project_path`_10_10tmp=$(mktemp)_10cat package.json \_10 | jq --arg homepage $gitlab_pages_url '. + {homepage: $homepage}' > $tmp \_10 && mv $tmp package.json_10_10git commit -am 'Add homepage to package.json'
Now we can setup CI. Run this to add a .gitlab-ci.yml
to your repo specifying
how to build in GitLab CI and deploy to GitLab Pages:
_33cat << 'EOF' > .gitlab-ci.yml_33cache:_33 untracked: true_33 key: "$CI_BUILD_REF_NAME"_33 paths:_33 - node_modules/_33 - .yarn-cache_33_33image: node_33_33stages:_33 - deps_33 - test_33 - publish_33_33deps:_33 stage: deps_33 script:_33 - yarn config set cache-folder .yarn-cache_33 - yarn install --pure-lockfile_33_33pages: # must be named pages to publish to GitLab pages!_33 stage: publish_33 script:_33 - yarn build_33 # replace public contents with build - GitLab requires a `public` dir_33 - rm -rf public/*_33 - mv build/* public_33 - ls -al public/_33 artifacts:_33 paths:_33 - public_33EOF
With this in place, GitLab CI will build and deploy our app on every git push
.
Let's try it out:
_10git add .gitlab-ci.yml && git commit -m 'Setup GitLab CI deployments'_10git push
Open up the pipelines dashboard and sit back while your app is built and deployed:
_10open `echo $project_json | jq -r '.result.web_url'`/pipelines
Once it's finished, view your app:
_10open $gitlab_pages_url
At this point you can start developing your app and have it auto deployed any
time someone pushes to master
.
Closing thoughts
One of the Startup Weekend resources is $3k worth of credits on Google Cloud Platform. While GCP is an excellent option for real apps, I opted to keep things as minimal as possible, and it ended up being free.
We could very easily extend this further using the Firebase Realtime Database and Firebase Authentication which gets you Google / Facebook / Twitter / GitHub login and a schemaless data store with very little work. These options change nothing from a deployment standpoint as Firebase usage remains purely client side. And since Firebase is a part of the GCP offering you can use those credits.