Full stack app deployment with ZEIT Now
This is a step-by-step tutorial for a full stack app, using React as frontend, Node backend with Apollo/GraphQL connected to MongoDB Atlas online database, all deployed using ZEIT Now.
(WARNING very much a work in progress. It is simply stepped notes, with very little explanation. Explanation will be in the write up for each section.)
Roadmap
Part | Title | Next step |
---|---|---|
A | Set up accounts in MongoDB Atlas and ZEIT Now | write up |
B | Set up the React frontend ‘example-users’ | write up |
C | Setup database in MongoDB | write up |
D | Secrets, environment variables & connection strings | write up |
E | Set up the Apollo backend ‘example-server’ | write up |
F | Apollo GraphQL stuff | finish notes |
G | Deploy and check ‘example-server’ in playground | finish notes |
H - Z | … | todo |
split parts into separate pages | todo | |
make stepped github repos? | todo |
Part B: Set up the React front end ‘example-users’
Step 3: Create new repository
- in terminal:
npx create-react-app example-users
- this will create the dependencies
react
,react-dom
andreact-scripts
for you - this will also add build scripts to the package.json
Step 4: Deploy example-users to now
- in terminal:
now
(yes really, just that) - watch it deploy on your ZEIT dashboard at
zeit.co/YourZEITUsername
- dots go green once it’s deployed
- check out your newly deployed website (eg,
example-users.YourZEITUsername.now.sh
)
Step 5: Connect local example-users repo to Github
- on github, add new repository
- give it the same name (eg, here it’s ‘example-users’)
-
in terminal:
git remote add origin git@github.com:YourGithubUsername/example-users.git git push -u origin master
- so whenever you either
push
to github, or just typenow
in terminal, your repo will be deployed to ZEIT.
Part C: Setup database in MongoDB
Step 6: Create database & ‘table’
- on MongoDB Atlas site, go to Clusters on left menu
- click on ‘Collections’ in the Sandbox box
- click on ‘Add my own data’
- create a database called
example
- create a collection (aka ‘table’ in old-fashioned lingo) called
users
- select your example database, and the users collection
- click ‘insert document’ to add some sample data
_id
is created for you- create key:value pairs for:
- Name: ‘Bilbo Baggins’
- Email: ‘bilbo.baggins@hobbiton.me’
- then click ‘Create’
- note the case of the keys (eg,
Name
, notname
)
Step 7: Setup database admin user
- on MongoDB Atlas site, go to ‘Database Access’ on left menu
- click ‘Add new user’
- create an Admin user
Step 8: Setup ZEIT / MongoDB integration
- on ZEIT Now site, go to Integrations, browse Marketplace
- choose MongoDB Atlas
- on the Add MongoDB page, your ZEIT Now account will be showing, click it to add the connection
- on the configuration page, edit the configuration name, perhaps to
MongoDB_connection
- don’t need to create a MongoDB Atlas account, as you already have one
- enter your MongoDB Atlas username (email)
- use the link ‘account settings’ to now go to MongoDB Atlas and set a public API key.
- click your username (on Mongo) to select ‘Preferences’, then choose ‘Public API Access’
Part D: Secrets, environment variables & connection strings
Step 9: Allow any connections to your MongoDB Cluster
- on MongoDB Atlas, go to Clusters on left menu
- click ‘Connect’
- choose ‘Add a different IP address’
- set
0.0.0.0
to allow connection from anywhere, since ZEIT Now does not support static IP addresses[1] (then says ‘You’re ready to connect’) - click ‘Choose a connection method’
- choose ‘Connect your application’
- choose Node.js and latest version
- copy the ‘Connection string only’ string, and note the instructions about swapping out your admin password in the string, save it somewhere, we’ll need it in [STEP WHATEVER]
Step 10: Set programmatic API key in MongoDB Atlas
- click the Context picker in the top-left hand corner and choose your organisation
- pick Settings from the left hand menu
- toggle the ‘Require IP Whitelist for Public API’ setting to ‘On’
- pick Access from left hand menu
- click the tab ‘API keys’
- click ‘Create API key’ button
- add a description, perhaps ‘ZEIT Now connection’
- copy the public key, save it somewhere
- leave the permissions as ‘Organisation member’, click next button
- copy the private key, save it somewhere, click done
Step 11: MongoDB connection string
Part E: Set up the Apollo server ‘example-server’
Step 12: Setup the repository in GitHub
- create new folder in terminal
mkdir example-server
- go into it
cd example-server
- initialise as a node project
npm init -y
- install dependencies
npm install apollo-server dotenv graphql mongoose
-
create
.env
file (empty for now), and put the following in a.gitignore
file:.env /node_modules
-
if using github, now’s the time to initialise this as a new repository:
- still in terminal
git init
- make first commit
- from GitHub website, add repository ‘example-server’
- leave everything default, click Create repository
-
do the “…or push an existing repository from the command line” things eg:
git remote add origin git@github.com:YourGithubUsername/example-server.git git push -u origin master
- still in terminal
Step 13: Configure package.json scripts and now.json
-
add the following to
package.json
:"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node ./index.js", "build": "exit 0" },
-
create a file called
now.json
at the root of ‘example-server’ repo, and add the following:{ "name": "example-server", "version": 2, "builds": [{ "src": "*.js", "use": "@now/node" }] }
Step 14: Connect ‘example-server’ to MongoDB Atlas
-
the following numbered steps allow connection to MongoDB from your local environment and from the deployed ZEIT Now environment. The MongoDB connection string contains your login details, so is kept in a hidden file:
.env
and is used when running the project locally. However once the repo is deployed on ZEIT Now,.env
is no longer available. So as well as this local environment variable, you need to setup a ‘secret’ via the ZEIT Now CLI:-
Create ZEIT Now secret: in terminal type:
now secrets add mongodb-connect mongodb+srv://YourMongoDBAdminUsername:YourPassword@YourClusterName.mongodb.net/YourDatabaseName?retryWrites=true
where ‘mongodb-connect’ here is the name of the secret.
-
Create local environment variable: add this line to your
.env
file:MONGODB_CONNECT=mongodb+srv://YourMongoDBAdminUsername:YourPassword@YourClusterName.mongodb.net/YourDatabaseName?retryWrites=true
-
Add ZEIT Now secret to now.json: add the following to your
now.json
file:"env": { "MONGODB_CONNECT": "@mongodb-connect" }, "build": { "env": { "MONGODB_CONNECT": "@mongodb-connect" } }
-
Step 15: Set up Mongoose to connect to MongoDB
-
create new file at the root called
config.js
with the following:const mongoose = require("mongoose"); require("dotenv").config(); mongoose.Promise = global.Promise; const url = process.env.MONGODB_CONNECT; mongoose.connect(process.env.MONGODB_CONNECT, { useNewUrlParser: true }); mongoose.connection.once("open", () => console.log(`Connected to mongo at ${url}`) );
Part F: Apollo GraphQL
Step 16: Write typeDefs
and resolvers
-
create new file at the root called
index.js
with the following:const { ApolloServer, gql } = require("apollo-server"); require("./config"); const { User } = require("./models"); const typeDefs = gql` type User { id: ID! Name: String Email: String } type Query { getUsers: [User] } type Mutation { addUser(Name: String!, Email: String!): User } `; const resolvers = { Query: { getUsers: async () => await User.find({}).exec() }, Mutation: { addUser: async (_, args) => { try { let response = await User.create(args); return response; } catch (e) { return e.message; } } } }; const server = new ApolloServer({ typeDefs, resolvers, introspection: true, playground: true }); server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); });
Step 17: Write schema
and model
-
create new file at the root called
models.js
with the following:const mongoose = require("mongoose"); const { Schema } = mongoose; const userSchema = new Schema({ Name: String, Email: String }); const User = mongoose.model("user", userSchema); module.exports = { User };
Part G: Deploy and check ‘example-server’ in playground
- push ‘example-server’ to ZEIT, with either
now
on command line, or git commit and push - once it’s deployed (watch it deploying on your ZEIT dashboard) visit your site and hopefully the Apollo playground will appear
- check the schema tab shows sensible things (picture)
-
you may need to wake up the MongoDB Atlas cluster, by simply reloading say the cluster page on the website (it’s really just a testing playground, you’d have to pay for more of an instant response, always on tier)
query { getUsers { Name Email } }
-
try the mutation (adding a user)
mutation { addUser(Name: "Jonty McJilly", Email: "jonty.mcjilly@poshtown.com") { Name Email id } }
[1]: Create and Deploy a MongoDB-Powered Node.js API with ZEIT Now
[2]: Environment Variables and Secrets with ZEIT Now