recipes for docker-compose, svelte-kit, golang, pocketbase, python, ...

recipes for docker-compose, svelte-kit, golang, pocketbase, python, ...

Submitted by Jitesh Doshi on Fri, 04/28/2023 - 15:48
At [SpinSpire](https://spinspire.com), 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](https://github.com/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 includes - `networks` and `labels` config to use `traefik` reverse proxy HTTP requests - `command` 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](https://svelte.dev) is our (browser) UI technology of choice and [SvelteKit](https://kit.svelte.dev) adds routing and server-side functionality to it. - `svelte.config.js` preconfigured to use `adapter-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 and `playwright` 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](https://pocketbase.io) 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](https://python.org) is the language of choice for data-science and AI, while [FastAPI](https://fastapi.tiangolo.com/) 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](https://www.metabase.com/) 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 1. First of all, read the project [README](https://github.com/spinspire/recipes/blob/master/README.md) file to understand the technical details. 2. Then use the excellent tool `degit` for copying entire repo or a part of it. 3. 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` 4. Then copy `.env.example` into `.env` and edit it to match your environment. 5. Delete the folders for the stacks you don't need (e.g. `mb`/`py`/`pb`/`sk`) 6. Delete their configuration from `docker-compose.yml` file and adjust `docker-compose.override.yml` 7. 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` (config `labels` 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 of `traefik`, 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 in `docker-compose.override.yml`. The client are sent first to `sk`'s dev server (0.0.0.0:5173) which does HMR (hot module reloading) upon every change in the SvelteKit code. And due to the `proxy` configuration in `vite.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 the `modd` command entry uncommented. - If you want to see how this will all work in production, then comment out the `command` entries for both `sk` and `pb` in the `docker-compose.override.yml` file and use the one in the main `docker-compose.yml` file. These `command` 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 no `modd` 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` and `mb`, then we mount them at `/apy` or `/mb` paths within your domain by configuring `traefik` 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`: Rust - `dr`: Drupal - `ng`: Nginx - `pg`: PostGres - `my`: MySQL/MariaDB - `sd`: SurrealDB Also, watch this space for a YouTube screencast tutorial video on how to take most benefit out of it.
© 2026 SpinSpire All rights reserved.