This web app template is suitable for mid-sized projects. The project repo is designed to be shallow, yet group code semantically. With this template, your project should remain maintainable in the ballpark of:
- Team of up to 10-20 people
- Up to lower hundreds of database tables / objects
- Multi-year project up to 3-5 years
- Webhooks (e.g. receive webhook events from Paddle)
- Multi-factor authentication
- Email (mailserver)
- Send emails (nodemailer)
- Receive emails (STMP server + SendGrid (mail relay server))
- email-based webhook (run code on received email)
- E.g. forward email to private email address when server receives email
- Deduplication of incoming email
- User authentication
- User session
- Forms
- Validated, typed
- Submission confirmation sent to submitter + us
- CI/CD - test, build, deploy flow in Gitlab CI
- Database
- Read / write and version mgmt with Prisma
- Automatic daily/weekly/monthly backups into S3 bucket
- Trigger database update and/or restore through Gitlab CI jobs
- Client
- Vuetify 3 UI lib
- Support for all - Server-side rendering (SSR), static site generator (SSG), or single page application (SPA)
- Smart queue management for system-wide components like modals, snackbars, etc.
- Declarative and fully-typed forms
- Separation of design system (component library) and "business logic" components
- Telemetry
- Usage analytics with Mixpanel with fully-typed events
- Error tracking with Sentry
- Both Mixpanel and Sentry tunnelled through the server to avoid ad blockers
- Type safety
- Fully typed, from users' input, through server-client communication (Apollo), to database connectors
- Cron jobs
- Used for creating database backups regularly
- Legal
- Server
- virtual machine - DigitalOcean Droplet + Ubuntu + docker-compose
- deployment - container registry + deployment jobs via Gitlab CI
- TypeScript
- Fast compilation with swc (see https://typestrong.org/ts-node/docs/swc/)
- Apollo GraphQL
- Schema definition + resolvers split across files by resources they relate to
- Scalar validation with graphql-scalars
- Pagination - GraphQL Cursor Connections Specification
- Auth directive - define GraphQL schema paths that require authentication to access
- GraphQL types and composables autogenerated with @graphql-codegen GraphQL syntax linting and intellisense with apollographql.vscode-apollo
- Prisma with PostgreSQL
- Redis for transient storage
- User sessions
- Multi-factor authentication challenges
- Email cache
- Express server
- Authentication layer (passport.js)
- User sessions with Redis
- CI/CD pipeline with test & build stages Gitlab +
gitlab-ci.yml
- Containerized - App built and deployed as a docker container (docker-compose)
- Reverse proxy (Nginx) + SSL cert (Let's encrypt + certbot)
- Client
- Vue3 + Nuxt3
- Payment gateway (Paddle)
- Dev tooling / dev exp
- Eslint linting
- Prettier
- DigitalOcean - Cloud server machine
- Netlify - Frontend deployment (as static site) + some forms
- Gitlab - source mgmt + CI/CD pipelines + container registry
- AWS S3 - Database backups
- Paddle - Payment gateway
- Sentry - Error tracking
- Mixpanel - User analytics
- Termly - User consent mgmt + legal documents for web
- Sendgrid - Email delivery
- Namecheap - domain purchase
Some examples:
-
Product purchase flow (Paddle):
- Fetch and store products defined in Paddle UI
- Display and trigger Checkout flow on frontend
- Listen for Paddle events on webhook
- Store transaction event and generate license code on order_fulfillment webhook event
-
Forward email to private email address on receiving email
-
Form submission (optionally with user confirmation)
- User fills in a form on the frontend
- Form is received and validated on the server
- If valid, form is added to the database
- Confirmation email is sent.
If the form submission requires user confirmation:
- At step 3, a multi-factor authentication (MFA) challenge is created.
- A URL is created that points to our MFA verification endpoint.
- The confirmation email mention in step 4 includes this verification URL.
- When the user clicks the verification URL, they hit our MFA endpoint.
- If MFA verification succeeds, the action started in step 1 is completed.
- Meanwhile, the user is redirected to our frontend with result of the MFA verification in query params.
- Frontend detects the MFA query parameter, and displays success or failure message.