Skip to content

Latest commit

 

History

History
196 lines (158 loc) · 8.87 KB

TECHNICAL_DECISIONS.md

File metadata and controls

196 lines (158 loc) · 8.87 KB

Technical Decisions in Graphile Starter

Table of contents

Overview

Graphile Starter is a full-stack GraphQL and React project, with server-side rendering (SSR) and routing thanks to Next.js. The backend is a beautiful pairing of Node.js and PostgreSQL running on Express.js, enabled by PostGraphile in library mode. The frontend uses the AntD design framework to accelerate development. The entire stack is written in TypeScript, with autogenerated GraphQL types and operations thanks to graphql-code-generator.

For more details on what Graphile Starter is, see the README.

Initial database

The database is a jumping-off point; we've already committed the initial user system for you. We deliberately do not include functionality that we don't think most users will find useful.

graphile-migrate

We're using the graphile-migrate system of migrations to increase productivity for database-driven development. Should you wish to use another migration framework we recommend you do so; however if you want to stick with graphile-migrate we recommend you read the graphile-migrate docs before progressing as graphile-migrate works in a different way to most other migration frameworks.

You can add idempotent SQL commands to migrations/current.sql and they will run when you save the file. When you're happy with your changes, run yarn db commit to commit these commands and reset migrations/current.sql to a blank state ready for the next batch of changes.

Should you wish to change the initial migration and you do not wish to do so with additional migrations, you can run yarn db uncommit (DESTRUCTIVE!) to move the migration back to migrations/current.sql, wiping your database in the process. Make the changes you desire, and then run yarn db commit.

See the graphile-migrate docs for more.

graphile-worker

We've added a few example workers for you, including the send_email worker which performs email templating for you. See @app/worker/src/tasks for the tasks we've created (and to add your own), and see the graphile-worker docs for more information.

Server

The server entry point is @app/server/src/index.ts; you'll see that it contains documentation and has split the middleware up into a manageable fashion. We use traditional cookie sessions, but you can switch this out for an alternative.

Cypress e2e tests

With thanks to Cypress.io for sponsoring this work, we've added e2e tests covering loading the various pages, registering an account, logging in, verifying and managing your emails. You should be able to easily build on top of these tests to ensure that your project remains rock-solid at all times.

Next.js

We use Next.js (docs) to handle the various common concerns of a React application for us (server-side rendering, routing, bundling, bundle-splitting, etc). The @app/client/src/pages/_app.tsx file is a custom <App> which allows you to add any providers you need to. We've already set it up with withApollo from @app/client/src/lib/withApollo which includes all the Apollo configuration, including the client URL.

AntD

The component library we're using is AntD (docs); we've demonstrated how to use the form validation components on the login/register pages so you can see how to handle errors from the server.

OAuth

If you set GITHUB_KEY and GITHUB_SECRET in your .env file then you can also use GitHub's OAuth social authentication; you can add similar logic to the GitHub logic (in @app/server/src/middleware/installPassport.ts) to enable other social login providers such as Twitter, Facebook, Google, etc. For more information, see the passport.js documentation.

Detailed list of technologies

  • Modern JavaScript and GraphQL development:

    • GraphQL — on the backend through PostGraphile, on the frontend via Apollo client
    • Autogenerated Type-safe GraphQL Hooks — using graphql-code-generator to turn your GraphQL queries and mutations into strongly typed React hooks instantly
    • TypeScript — make your project maintainable by starting with strong typing throughout
    • PostGraphile configured for lean schema — very tidy GraphQL schema, adhering to PostGraphile best practices
    • Hot reloading — edit a component and it's re-rendered immediately (warning: state is not restored, because this typically leads to instability); provided by Next.js
    • SSR with hot reloading — if you turn JS off and reload the page you should be greeted with the same content anyway; provided by Next.js
    • Realtime — PostGraphile is configured with @graphile/pg-pubsub to enable Realtime events from the DB; and Apollo is configured to consume them
  • Increase development velocity:

    • Autoformatting ─ Thanks to prettier and eslint, code can be auto-formatted (and auto-fixed) on save
    • Linting — provided by eslint, prettier and @typescript-eslint. Can be extended with extremely powerful lint rules to protect your project from bugs, bad practices, and inconsistencies; configured with sensible but not too intrusive (hopefully) defaults focused on GraphQL development
    • Debuggability ─ The server, worker, tests and client are all ready to be debugged using VSCode's built in breakpoints
    • Documented error codes — specification of existing error codes, examples of them being used, and space to add more
    • Productive roll-forward migrations — we use graphile-migrate for development speed, but you're welcome to switch to whatever migration library you like
  • Prebuilt user system:

    • Register via email with sensible validation and error handling
    • Register via social
    • Verify email flow
    • Handle errors in email verification flow
    • Login (with mixed case username/email, or via social)
    • Email management (add more, delete old, change primary, resend verification)
    • User.isVerified to check they have at least on verified email (can use this to govern further permissions)
    • Update profile information
    • Change password flow
    • Forgot password flow
    • Unlinking social profiles
  • Sessions — persist login information in the traditional way (with cookies)

  • Form validation — using AntD's Form component

  • Email handling:

    • Responsive email templates — we've added MJML and a templating system to help you format emails; all emails go through the send_email worker task so it's easy to customize
    • Email transport — we've configured Nodemailer to use ethereal.email to catch all development emails, and AWS' SES in production (easy to replace with a different provider thanks to Nodemailer)
    • HTML→Text emails — automated conversion from your pretty templates to plain text emails for users that prefer that
  • Testing:

    • Database tests — Jest configured to test the database, plus initial tests for various database functions and tables
    • GraphQL tests — Jest configured to test the GraphQL schema, plus some initial tests
    • Acceptance tests — implemented with Cypress
  • Ant Design Framework — "A design system with values of Nature and Determinacy for better user experience of enterprise applications"

  • Docker development flow — enables work on this project using Docker (rather than running the Postgres/etc. directly on your machine). See docker/README.md for more info on running in Docker mode.

TODO

Here's some more things we'd like to demonstrate that we've not got around to yet. (If you're interested in helping, reach out on Discord: http://discord.gg/graphile)

  • File uploads — user can change their avatar, but this approach can be extended to other areas