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, 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.


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.
  • 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 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 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

  1. First of all, read the project README 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 ( 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.

Jitesh Doshi

Profile picture for user Jitesh Doshi
Managing Partner & CTO
  • A seasoned technology entrepreneur and enthusiast
  • A regular speaker at industry conferences and universities
  • Host and organizer of technology user groups
  • Active in management of non-profit organizations serving the local community
  • Leader and contributor for multiple open-source projects
  • Expert in cloud, application integration, web and mobile technologies
  • Author of open-source projects, including on - Popular Tags and PRLP.
  • Developed several highly successful software platforms and frameworks for clients