The code of web applications can be divided between product and platform. Product code solves end user problems; platform code enables correct and efficient delivery. Product code differs greatly between applications, but platform code can often be reused. This repository contains my generalizable platform code for web applications; boilerplate in essence.
Each of the libraries consisting the platform tightly integrate with each other to eliminate friction during product delivery.
This repository contains a superset of features; most applications will find some of them unnecessary. It is intended that features be cherry-picked and copy-pasted from this repository into specific projects.
The common code in this repository covers infrastructure, backend, frontend, and design.
- Nix for developer environments.
- Nomad for service orchestration.
- Github Actions for CI pipeline.
- Github Actions for CD pipeline with Nomad and Tailscale.
The backend is a Python monolith with Postgres database.
- Language: Python
- Type Checker: Pyright
- Builds: Nix
- Package Manager: Nix
- Database: Postgres
- ORM: sqlc (w/ psycopg engine)
- Web Framework: Quart & Hypercorn
- Migrations: pgmigrate
- Background Jobs: Procrastinate (TODO)
- Logging/Tracing: OpenTelemetry (TODO)
- Data Validation: pydantic
- Linters: ruff & Semgrep
- Formatter: ruff
- Test Runner: pytest
Features:
- Lazy test fixtures for concise test setup.
- Parallelized tests with shared database.
- Multi-tenant account system.
- Row Level Security for secure multi-tenancy.
- RPC framework with TypeScript type codegen.
- Vault abstraction for basic encrypted storage.
- Database conventions and tests to enforce them.
- Developer CLI for service operations and developer tooling.
- Environment variable configuration.
The frontend is a Typescript React SPA (CDNs đź’¸).
- Language: TypeScript
- Builds: Turborepo & Vite (SWC)
- Package Manager: pnpm
- UI Framework: React
- Headless Components: React Aria
- CSS-in-JS: vanilla-extract
- Module State Management: Jotai
- Server State Management: Tanstack Query
- Router: Wouter
- Linters: ESLint & Semgrep
- Formatter: dprint
- Component Stories: Ladle
- Test Runner: Vitest
- Visual Test Runner: Playwright & Ladle
- E2E Test Runner: Playwright (TODO)
Features:
- Light and dark themes.
- RPC framework with imperative, Jotai, and Tanstack Query bindings.
- Custom errors with rich metadata and stacktraces.
- Icons with tokenized colors and sizes, and lazy-loading.
- Forms for convenience.
- Page layout primitives optimizing consistency and flexibility.
- Loader components for easy loading states.
- Page routing with code splitting and prefetching.
- RPC mocks with msw for Ladle stories and Vitest testing.
The design system currently has some random colors and fonts. Each application should change them.
- Figma Tokens file.
- Figma component library.
- Figma color palette & theme libraries.
We use Nix to manage developer environments. All tools we use are declaratively defined in nix/
.
To bootstrap the developer environment and get started:
- Follow the Linux or MacOS guide to install Nix.
- Enable Nix Flakes.
- Install
direnv
and rundirenv allow
in the root of the monorepo.
After installing Nix and activating the developer environment, all tools and commands should work.
The monorepo is organized at the top-level by service type. Examples of service types are frontend, backend, nix, and nomad. Each service type has its own internal organization.
The application services (the backend and frontend services) are organized as packages. Each package solves one class of problems or feature and contains a README that document its purpose, context, and usage.
Packages are sorted into package groups. While every application service will have its own set of package groups, mainstays are:
foundation/
contains platform packages.product/
contains the product packages.codegen/
contains the packages that are produced from codegen tooling.
Inside each package group, packages are arranged in a flat structure. All package directories are direct children of a package group directory.
Note: The platform packages live in foundation
instead of platform
because
platform
is a Python standard library package.
Infrastructure is structured similarly. The top level is organized by type of infrastructure.
flake.nix
aggregates all of Nix outputs derivations into a single flake.docker-compose.yaml
defines all services used in the local environment.nix/
contains Nix derivations for our packages, toolchains, and builds.nomad/
contains Nomad service definitions..github/workflows/
contains the CI/CD pipeline configurations.
We try to avoid having multiple local services occupy the same port. The current allocations of services -> ports are:
- 40851: Backend
- 40852: Postgres
- 40853: Frontend
- 40854: Ladle
- 40855: Visual Tests
Copyright 2023 blissful <blissful@sunsetglow.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.