Skip to content

Commit c77ba37

Browse files
committed
Initial commit
0 parents  commit c77ba37

40 files changed

+12044
-0
lines changed

.example.env

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Authentication related secrets
2+
GOOGLE_CLIENT_ID= # Get from the Google dev console
3+
GOOGLE_CLIENT_SECRET= # Get from the Google dev console
4+
SESSION_SECRET= # A random, long string

.github/workflows/main.yml

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: CI
2+
3+
on: [push]
4+
5+
jobs:
6+
test:
7+
name: All the checks
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- name: Checkout repository
12+
uses: actions/checkout@master
13+
14+
- name: Install Node.js 12.x
15+
uses: actions/setup-node@master
16+
with:
17+
version: 12.x
18+
19+
- name: Install yarn 1.17.3
20+
run: npm install -g [email protected]
21+
22+
- name: Install dependencies
23+
run: yarn install --frozen-lockfile
24+
25+
- name: Check formatting
26+
run: yarn prettier --check '**/*.{js,json,ts,tsx,graphql,md}'
27+
28+
- name: Lint
29+
run: yarn lint
30+
31+
- name: Check types
32+
run: yarn web tsc
33+
34+
# TODO: Add tests
35+
# - name: Run tests
36+
# run: yarn web test:ci
37+
38+
- name: Build
39+
run: yarn web build

.gitignore

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
node_modules
2+
.pnp
3+
.pnp.js
4+
5+
.DS_Store
6+
.env*
7+
.next
8+
9+
*.generated.*
10+
web/database/generated
11+
!web/graphql/schema.generated.graphql
12+
13+
npm-debug.log*
14+
yarn-debug.log*
15+
yarn-error.log*

.prettierignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
web/.next
2+
.vscode
3+
4+
*.generated.*
5+
**/generated/**

.prettierrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

.yarnclean

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@types/react-native

README.md

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Nice Boys™️ Product Boilerplate
2+
3+
Quickly ship your apps with the power of code generation.
4+
5+
## Philosophy
6+
7+
> "Speed of developer iteration is the single most important factor in how quickly a technology company can move."
8+
>
9+
> — Paul Biggar, cofounder CircleCI
10+
11+
Product boilerplate is [@brianlovin](https://github.com/brianlovin) and [@mxstbr](https://github.com/mxstbr)'s personal setup to quickly build new apps. It aims to get all the common stuff out of the way and make shipping and subsequently iterating on a product as quick as possible.
12+
13+
There are three important traits in all the included tooling that we pay attention to:
14+
15+
1. **Mastery**: We know most of these tools inside and out and have a lot of experience with them.
16+
2. **Code generation**: The less boilerplate code we need to write, the more we can focus on our app. Code generation allows us to automate the tedious parts.
17+
3. **Type safety**: Counterintuitively, having strict type safety lets you move faster because you get warnings about bugs right in your IDE without having to recompile.
18+
19+
Note that this is our personal boilerplate. You are more than welcome to use it (that's why it's open source), but we cannot give any support when using it. Make sure you understand the tools in it before using it!
20+
21+
## Stack
22+
23+
The entire app (front- and backend) uses [Next.js](https://nextjs.org) in serverless-mode for development, and deployment is powered by [Now](https://now.sh).
24+
25+
### Tools
26+
27+
- [TypeScript](https://typescriptlang.org)
28+
- [Prettier](https://prettier.io)
29+
- [ESLint](https://eslint.org)
30+
- [yarn](https://yarnpkg.com) workspaces for the monorepo support
31+
- [GraphQL Codegen](https://graphql-code-generator.com)
32+
33+
### Frontend
34+
35+
- [React](https://github.com/facebook/react)
36+
- [Next.js](https://github.com/zeit/next.js)
37+
- [styled-components](https://github.com/styled-components/styled-components)
38+
- [rebass](https://rebassjs.org)
39+
- [@nice-boys/components](https://github.com/nice-boys/components)
40+
41+
### Backend
42+
43+
- [GraphQL](https://graphql.org)
44+
- [Apollo Server](http://apollographql.com/docs/apollo-server) for exposing said GraphQL schema through the API
45+
- [GraphQL Nexus](https://nexus.js.org) for creating a type-safe GraphQL API
46+
- [Prisma](https://prisma.io) for type-safe database access
47+
- [Passport](http://www.passportjs.org/) for authentication
48+
49+
## Working with the boilerplate
50+
51+
### Code Generation
52+
53+
There are three code generators at work in this boilerplate:
54+
55+
- [GraphQL Codegen](https://graphql-code-generator.com) automatically generates React components for the frontend that fetch from the API. They are fully typed too, so you know exactly what the shape of the returned data is.
56+
- [Prisma](https://prisma.io) generates a fully type-safe database client from our datamodel.
57+
- [GraphQL Nexus](https://nexus.js.org) (in combination with Prisma) lets us expose a production-ready GraphQL API from the database client.
58+
59+
### Routing
60+
61+
All routing happens via the folder structure in the `web/pages/` folder. Any route under `web/pages/api` will be treated as an [API route](https://nextjs.org/docs#api-routes), all others as React routes.
62+
63+
To add dynamic routing use the Next.js [dynamic routes feature](https://nextjs.org/docs#dynamic-routes).
64+
65+
### Commands
66+
67+
To start the app locally you have to run these two commands:
68+
69+
- `yarn run dev`: Stars the development process for the serverless front- and backend, as well as all generation processes.
70+
- `yarn run db`: Starts the database locally (note: requires Docker to be up and running and docker-compose to be installed)
71+
72+
Further, you will frequently use these commands while developing and they are automatically run whenever you switch branches or pull new code to make sure your generated files are up to date:
73+
74+
- `yarn run db:deploy`: Update your local database with changes you made to the datamodel.
75+
- `yarn run generate`: Runs all the codegeneration commands in sequence. You can also run them manually if necessary:
76+
- `yarn run generate:db`: Generate the Prisma database client for the server.
77+
- `yarn run generate:server`: Generate the `schema.graphql` file for the backend from the Nexus schema
78+
- `yarn run generate:web`: Generate the fetching hooks and types for the frontend from the `.graphql` files contained within it
79+
80+
These are automatically run in a pre-commit hook, so don't worry about calling them manually unless you have a reason to:
81+
82+
- `yarn run prettify`: Prettifies the `src` folder with [Prettier](https://prettier.io).
83+
- `yarn run lint`: Lints the `src` folder with [ESLint](https://eslint.org).
84+
85+
### Deployment
86+
87+
To deploy the database, look at the Prisma docs, e.g. their tutorial on [deploying the database to AWS fargate](https://www.prisma.io/tutorials/deploy-prisma-to-aws-fargate-ct14).
88+
89+
Once that is up and running, to deploy the app you simply run `now`, that's it! We recommend enabling the Now GitHub integration for CD.
90+
91+
## License
92+
93+
Licensed under the MIT License.

graphql-codegen.yml

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
overwrite: true
2+
schema: web/graphql/schema/index.ts
3+
documents: "web/**/*.graphql"
4+
require:
5+
- ts-node/register
6+
generates:
7+
web/graphql/introspection-result.generated.ts:
8+
plugins:
9+
- add: |
10+
// eslint-disable
11+
// ⚠️ DO NOT EDIT ⚠️
12+
// This file is automatically generated, run yarn run graphql:codegen to update
13+
- "fragment-matcher"
14+
web/graphql/schema-types.generated.ts:
15+
plugins:
16+
- typescript
17+
config:
18+
immutableTypes: false
19+
web/:
20+
preset: near-operation-file
21+
presetConfig:
22+
baseTypesPath: "graphql/schema-types.generated.ts"
23+
extension: ".generated.tsx"
24+
plugins:
25+
- add: |
26+
// eslint-disable
27+
// ⚠️ DO NOT EDIT ⚠️
28+
// This file is automatically generated, run yarn run graphql:codegen to update
29+
- "typescript-operations"
30+
- "typescript-react-apollo"
31+
config:
32+
immutableTypes: false
33+
withHOC: false
34+
withComponent: true
35+
withHooks: false
36+
web/graphql/types.generated.d.ts:
37+
plugins:
38+
- add: |
39+
// eslint-disable
40+
// ⚠️ DO NOT EDIT ⚠️
41+
// This file is automatically generated, run yarn run graphql:codegen to update
42+
- "typescript-graphql-files-modules"

now.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version": 2,
3+
"builds": [
4+
{
5+
"src": "web/next.config.js",
6+
"use": "@now/next"
7+
}
8+
],
9+
"routes": [
10+
{
11+
"src": "/(.*)",
12+
"dest": "/web/$1"
13+
}
14+
],
15+
"github": {
16+
"silent": true
17+
}
18+
}

package.json

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"name": "product",
3+
"version": "1.0.0",
4+
"private": true,
5+
"repository": "https://github.com/nice-boys/product-boilerplate",
6+
"author": "Max Stoiber <[email protected]>",
7+
"workspaces": {
8+
"packages": [
9+
"web"
10+
]
11+
},
12+
"scripts": {
13+
"prettier": "prettier",
14+
"prettify": "prettier --write",
15+
"lint": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx web",
16+
"dev": "concurrently -n web,generate:web,generate:schema,generate:db \"yarn workspace web dev\" \"yarn generate:web --watch\" \"nodemon -w web/graphql -x 'yarn generate:schema'\" \"nodemon -w web/database/datamodel.prisma -x 'yarn run generate:db'\"",
17+
"web": "yarn workspace web",
18+
"db": "yarn workspace web run db",
19+
"db:deploy": "yarn workspace web run db:deploy",
20+
"generate": "yarn run generate:db && yarn run generate:schema && yarn run generate:web",
21+
"generate:web": "graphql-codegen --config graphql-codegen.yml",
22+
"generate:schema": "GENERATE=true ts-node --skip-project web/graphql/schema/index.ts",
23+
"generate:db": "yarn workspace web generate:db",
24+
"postinstall": "yarn run generate"
25+
},
26+
"eslintConfig": {
27+
"parser": "@typescript-eslint/parser",
28+
"parserOptions": {
29+
"project": "./web/tsconfig.json"
30+
},
31+
"extends": [
32+
"eslint:recommended",
33+
"plugin:@typescript-eslint/recommended",
34+
"prettier",
35+
"prettier/@typescript-eslint",
36+
"react-app"
37+
],
38+
"plugins": [
39+
"react-hooks",
40+
"clean-styled-components"
41+
],
42+
"rules": {
43+
"@typescript-eslint/explicit-function-return-type": 0,
44+
"@typescript-eslint/explicit-member-accessibility": 0,
45+
"@typescript-eslint/no-empty-interface": 0,
46+
"@typescript-eslint/no-var-requires": 0,
47+
"@typescript-eslint/no-explicit-any": 2,
48+
"react-hooks/rules-of-hooks": "error",
49+
"react-hooks/exhaustive-deps": "warn",
50+
"clean-styled-components/single-component-per-file": 2,
51+
"no-console": [
52+
"error",
53+
{
54+
"allow": [
55+
"warn",
56+
"error"
57+
]
58+
}
59+
]
60+
}
61+
},
62+
"husky": {
63+
"hooks": {
64+
"pre-commit": "lint-staged && yarn run generate:schema && git add web/graphql/schema.generated.graphql",
65+
"post-checkout": "yarn run generate && yarn run db:deploy"
66+
}
67+
},
68+
"lint-staged": {
69+
"*.{js,ts,tsx}": [
70+
"eslint --fix",
71+
"prettier --write",
72+
"git add"
73+
],
74+
"*.{css,json,md,mdx}": [
75+
"yarn run prettify --write",
76+
"git add"
77+
]
78+
},
79+
"devDependencies": {
80+
"@graphql-codegen/add": "1.2.0",
81+
"@graphql-codegen/cli": "^1.2.0",
82+
"@graphql-codegen/core": "1.6.1",
83+
"@graphql-codegen/fragment-matcher": "1.6.1",
84+
"@graphql-codegen/introspection": "1.6.1",
85+
"@graphql-codegen/near-operation-file-preset": "1.2.0",
86+
"@graphql-codegen/typescript": "1.2.0",
87+
"@graphql-codegen/typescript-graphql-files-modules": "1.6.1",
88+
"@graphql-codegen/typescript-operations": "1.2.0",
89+
"@graphql-codegen/typescript-react-apollo": "1.2.0",
90+
"@typescript-eslint/eslint-plugin": "^1.6.0",
91+
"@typescript-eslint/parser": "^1.6.0",
92+
"babel-eslint": "^10.0.2",
93+
"concurrently": "^4.1.0",
94+
"eslint": "^5.16.0",
95+
"eslint-config-prettier": "^4.1.0",
96+
"eslint-config-react-app": "^3.0.8",
97+
"eslint-loader": "2.1.1",
98+
"eslint-plugin-clean-styled-components": "^0.0.2",
99+
"eslint-plugin-flowtype": "2.50.3",
100+
"eslint-plugin-import": "2.18.2",
101+
"eslint-plugin-jsx-a11y": "6.2.1",
102+
"eslint-plugin-react": "7.14.3",
103+
"eslint-plugin-react-hooks": "^1.6.0",
104+
"husky": ">=1",
105+
"lint-staged": ">=9",
106+
"nodemon": "^1.19.1",
107+
"now": "^15.3.0",
108+
"prettier": "^1.18.2",
109+
"react-dev-utils": "^9.0.1",
110+
"ts-node": "^8.2.0"
111+
},
112+
"resolutions": {
113+
"styled-jsx": "3.0.0",
114+
"@types/styled-components": "4.1.8",
115+
"graphql": "14.3.1"
116+
},
117+
"license": "MIT"
118+
}

web/.babelrc

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"presets": [
3+
"next/babel",
4+
"@zeit/next-typescript/babel"
5+
],
6+
"plugins": [
7+
["styled-components", { "ssr": true }]
8+
]
9+
}

0 commit comments

Comments
 (0)