Fullstack "hello, world!" using PostgreSQL🐘, a RESTful API powered by PostgREST and a frontend build with React. Also starring the craft beers dataset.
Available for your viewing pleasure at hello-parity.koenw.dev.
Live API docs available here.
Run the whole stack locally in docker with docker-compose up
, this makes the
frontend available at http://localhost:8080, the
backend at http://localhost:3000 and the swagger API
docs at http://localhost:8088.
Using PostgREST as a backend comes with some perks. Besides the beautiful RESTful API that comes with it the OpenAPI support leads to some even more important benefits, like automatically generated clients and API documentation.
- just is used as a command runner for project specific commands, both locally and in CI/CD;
- nodejs for npx/bootstrapping of pnpm;
- openapi-generator to generate or update the API client from the spec;
- docker to build, tag and push images;
- docker-compose to run everything locally;
Project specific commands, including CI/CD commands like building of docker
images, are kept in the Justfile
. Run just -l
to get an overview of
available commands/tasks.
Nix users can use nix-shell
or the ./just
wrapper and
not worry about dependencies (which is also what the CI/CD pipeline does).
The frontend is a simple React app using
react-table and
material-ui to make some pretty
tables out of an API. Most of the frontend's API consuming code (in
frontend/src/generated
) is generated with
openapi-generator.
Use just serve
to start a local auto-refreshing development server on
http://localhost:1234 that by default will talk to the
backend started with docker-compose up
.
Since our backend is entirely data agnostic and most of the client is
automatically generated, adding or removing columns is as simple as editing the
column definition in frontend/src/app.tsx
.
If the columns do not yet exists in the database you will have to add them to a migration and re-generate the client API code as described in Adding additional datasets.
Because our backend does not do migrations they (and the initial import) are
instead handled by a separate very simple mgmt container; build from the
mgmt
directory. Place your migrations in datasets/<dataset>/init.sql
,
making sure to keep everything idempotent.
Because so much of the stack is data agnostic, it is actually quite easily adapted to additional datasets:
- Create a directory for the new dataset in the
datasets
directory - Place
.sql
files in it that will create and fill the tables. The SQL files are executed in alphabetical order. I'd suggest to either use oneinit.sql
or multiple files prefixed by a number/date. Make sure to keep them idempotent. - Start the PostgREST backend (e.g.
docker-compose up
) - Generate the frontend API client (
just generate-client http://localhost:3000/
) - Add the API imports and column definitions to
frontend/src/app.tsx
- Make the UI aware of foreign key relations;
- Generate remaining dataset-specific UI code, leaving literally only configuration to specify the database tables and columns
- Add search and/or filter functionality
You'll need Docker🐋 and a PostgreSQL🐘 database. Pre-build Docker images are
available, the docker-compose.yml
file can serve as an example of how they
tie together. If you are aiming to run on kubernetes I suggest running the
mgmt container in the same pod as the
PostgREST backend.
docker pull postgrest/postgrest
Environmental Variable | Description | Example |
---|---|---|
PGRST_DB_URI |
Standard URI to the database. | postgres://user:password@host:5432/dbname |
PGRST_DB_SCHEMA |
PostgreSQL schema to connect to. | public |
PGRST_DB_ANON_ROLE |
PostgreSQL user used for anonymous queries. Make sure you update the migrations (that also create this user) if you change this. | anon |
docker pull ghcr.io/koenw/fullstack-hello-frontend
No configuration needed. If the frontend is access through localhost it will
connect to localhost:3000
, else it will connect to https://api.<frontend domain>
.
docker pull ghcr.io/koenw/fullstack-hello-mgmt
Environmental Variable | Description | Example |
---|---|---|
DB_HOST |
PostgreSQL database hostname | shd-postgres |
DB_PORT |
PostgreSQL database port | 5432 |
DB_USER |
PostgreSQL database user | fullstack-hello |
DB_PASSWORD |
PostgreSQL database password | s3cr#t |
This component provides the live API documentation and is thus optional from a user-functionality perspective.
docker pull swaggerapi/swagger-ui
Environmental Variable | Description | Example |
---|---|---|
URL |
URL to the OpenAPI spec | https://api.hello-parity.koenw.dev/ |
BASE_URL |
Path to serve API docs under | /swagger |
You're free to use, modify and distribute this software under the terms of the MIT or Apache-2.0 license, whichever has your preference.