recipes for docker-compose, svelte-kit, golang, pocketbase, python, ...
At SpinSpire, every year we take dozens of projects to production. But in order to get there, we have to build dozens of projects per month, only some of which gets released. In this process, we master several tech stacks. After going through this process many times we've made some common observations:
- The diversity of tech stacks is large, so no one person can master them all.
- On each stack we make the usual mistakes and then learn from them.
- This institutional knowledge needs to be codified and saved somewhere, ready to be retrieved and leveraged at a moment's notice.
- A library of foundational components and their bug fixes gets accumulated over time.
- We benefit so much from open source software (it's in our tagline - Open Source High performance Web & Mobile!), so we want to give our learning back to the community.
With those considerations in mind, I would like to introduce SpinSpire Recipes -- A git monorepo designed to kickstart any project with a working foundation of tech stacks involed. The stacks are pre-configured and even have a small library of components.
Features
Docker & Docker Compose
We use Docker and Docker Compose to help provide a highly predictable, controlled, isolated, and hence secure runtime environment for all our apps. docker-compose.yml
file is provided for every container in the stack.
- uses small but battle tested ready-to-use Docker images and avoids building custom images from
Dockerfile
(although sometimes that is exactly what you need for better control; but this method gets you started faster) docker-compose.override.yml
file that includesnetworks
andlabels
config to usetraefik
reverse proxy HTTP requestscommand
override to run in "live dev" mode so that code gets recompiled and reloaded on change.
entrypoint.sh
scripts for various containers to initialize (e.g. compile) a container at the time of startup.
SvelteKit (sk)
Svelte is our (browser) UI technology of choice and SvelteKit adds routing and server-side functionality to it.
svelte.config.js
preconfigured to useadapter-static
in SPA mode (index.html
fallback)+layout.ts
turns off SSR, trailing slashes are on by default- a prebuilt
+error.svelte
page ready to be customized - Uses water.css for default styling and provides SASS &
app.scss
for custom styling - uses
pnpm
for faster dependency management - includes example
vitest
tests for unit testing andplaywright
tests for end-to-end testing - Has a library of components for alerts, modal dialogs, file upload, navbar, animated busy-indication spinners, and PocketBase client functionality.
- Example pages and routes for showing CRUD operations on a PocketBase backend.
PokcetBase & Golang (pb)
PocketBase is a self-hosted BaaS (backend as a service) which is very lightweight but provides a ton of features like a database (sqlite) fronted by a REST API, file uploads, email/3rd party single-sign-on, server push on data change, etc. Although a binary is provided, the best part is that it can be used as a Golang framework and extended without limits.
- a
main.go
that leverages all the power of PocketBase as a framework (as opposed to binary program) - examples of database migrations in both Golang and JavaScript
modd
setup for live development. Watches the code and on every file change to:- recompile
- re-run unit tests
- restart server
hooks
implementation to watch any table in the application and run external programs, webhooks, or send emails on insert/update/delete.auditlog
table and corresponding hooks to keep a record of which user made what change to which table. This is turned off by default, but can be turned on by setting an environment variable.- Go type to TypeScript type generation with
tygo
- PocketBase record to TypeScript type generation with
pocketbase-typegen
- Serve static frontend using
--publicDir ../sk/build
Python / FastAPI (py)
Python is the language of choice for data-science and AI, while FastAPI is the API of choice for async (ASGI) web services.
- Mount Python routes to a configurable prefix (e.g.
/apy
) - More features to be added soon.
Metabase (mb)
Metabase is a power BI (Business Intelligence) and data visualization platform.
- at this point, all we have is a metabase container that could then be used to visualize data from any available database.
How to use
- First of all, read the project README file to understand the technical details.
- Then use the excellent tool
degit
for copying entire repo or a part of it. - It's a monorepo containing probably more than what you need. You can use the entire repo, or some part of it:
- entire repo:
npx degit spinspire/receipes myprj
- some part of it:
npx degit spinspire/receipes/sk myprj/sk
npx degit spinspire/receipes/pb myprj/pb
npx degit spinspire/receipes/mb myprj/mb
npx degit spinspire/receipes/py myprj/py
- entire repo:
- Then copy
.env.example
into.env
and edit it to match your environment. - Delete the folders for the stacks you don't need (e.g.
mb
/py
/pb
/sk
) - Delete their configuration from
docker-compose.yml
file and adjustdocker-compose.override.yml
- Finally run
docker-compose up -d
and watch the logs (docker-compose logs -f
) for a healthy compile and startup.
Browse the code and further delete what you don't need. And only after that, start building on top of it. Of course, reach out to me if any questions.
How it works
- docker-compose downloads and runs containers for NodeJS, Golang, and other technologies used in this.
- Optinally,
traefik
(configlabels
included, but not container definition) runs an HTTPS server exposing your project to the public internet and (reverse) proxies the incoming HTTPS requests as plain HTTP requests to your HTTP listeners (pb
/sk
/py
/etc). In the absence oftraefik
, your servers receive HTTP requests directly from the browsers (e.g. in development)
[traefik https:443] --> [pb:8090]
(prefix /apy) --> [py:8000]
(prefix /mb ) --> [mb:3000]
- If you are doing active development in SvelteKit then make sure the
npm run dev
command entry is uncommented indocker-compose.override.yml
. The client are sent first tosk
's dev server (0.0.0.0:5173) which does HMR (hot module reloading) upon every change in the SvelteKit code. And due to theproxy
configuration invite.config.ts
this dev server can also proxy the/api
and/_
requests to PocketBase backend server. This technique completely sidesteps all CORS issues.
[traefik https:443] --> [sk:5173] --> (prefix /_ || prefix /api) --> [pb:8090]
- If you are ALSO using PocketBase as a framework and active Golang development, then make sure
docker-compose.override.yml
has themodd
command entry uncommented. - If you want to see how this will all work in production, then comment out the
command
entries for bothsk
andpb
in thedocker-compose.override.yml
file and use the one in the maindocker-compose.yml
file. Thesecommand
entries build both SvleteKit and Golang/PocketBase projects in fully compiled, release mode and thus should run faster. There is no vite/SvelteKit dev server and nomodd
watching for changes either. PocketBase then serves the bundled SvelteKit output from../sk/build
directory.
[traefik https:443] --> [pb:8090] + (dynamic /api + static /sk/build)
- If you are using other stacks such as
py
andmb
, then we mount them at/apy
or/mb
paths within your domain by configuringtraefik
to forward those path prefixs to their respective containers.
Coming soon ...
We will keep building up this repo, for our own sake as well as the community's. We will add many library functions and components. Also, other stacks:
rs
: Rustdr
: Drupalng
: Nginxpg
: PostGresmy
: MySQL/MariaDBsd
: SurrealDB
Also, watch this space for a YouTube screencast tutorial video on how to take most benefit out of it.