← Back to blog
Aug 27, 20265 min readengineeringdevopsci-cdworkflowopen-source

How I ship side projects: the pipeline behind eight repos

Every project gets the same baseline — a five-minute quickstart, CI gates, a license, and a docs page that sells it. Here is the repeatable process I use to take an idea from empty repo to released product while working full time.

At the time of writing I maintain eight public projects: two browser apps, two backend platforms, an encrypted desktop + Android app, a Python CLI, a Kotlin Android app, and a trading journal. None of them have a team. Most were built in the margins of a full-time job and a master's degree.

People ask how. The honest answer is not "discipline" or "grinding at 5 a.m." — it is that I stopped making project-by-project decisions. Every repository gets the same baseline, so starting a new one is mostly filling in the interesting part.

Here is the baseline.

1. The five-minute quickstart is a requirement, not a nicety

If a developer cannot clone, configure, and run the project in five minutes, the project does not exist for them. Every README starts with the same shape:

git clone https://github.com/Pranesh-Selvaraj/<project>.git
cd <project>
# one or two commands max
pnpm dev

Everything that gets in the way of that is a bug:

  • Defaults over configuration. Nexus runs in single-user mode with no auth if you do not set a password. Tempo falls back to embedded PGlite if you don't want to run PostgreSQL. Enclave's defaults are the private ones.
  • One file for environment variables. .env.example is complete and copy-pasteable. No guessing.
  • A seeded database. pnpm setup migrates and seeds so the app has content on first launch.
  • Docker only where it earns its place. docker compose up -d for PostgreSQL is fine. Requiring Kubernetes for a side project is not.

The README is the landing page. Badges, a one-line pitch, a screenshot, a quickstart, and a feature list — in that order.

2. CI gates that make regressions impossible to ignore

Every repo gets a GitHub Actions workflow with the same non-negotiables:

GateWhy
TypecheckTypes are the cheapest tests and the fastest failure
LintStyle arguments end here
BuildThe deploy must be boring
TestsBehavior, especially parsing and state machines
Dependency auditKnown vulnerabilities fail the build, ideally
Secret scanninggitleaks on every push
CodeQLStatic analysis for the bugs I would miss

The exact tools differ — pnpm and Turborepo for TypeScript monorepos, Gradle for Android, a plain Python matrix for Sentinel — but the principle never does: if I can break it from my laptop, CI should have caught it first.

The compounding effect is quiet. Because the gates exist, I can return to a project after three weeks and trust that main still works. That is what makes maintaining many projects psychologically possible.

3. A license, a security policy, and contribution docs

Boring files that signal a project is real:

  • LICENSE — MIT for most, GPL-3.0 for Ratio (inherited from upstream, and it must stay that way).
  • SECURITY.md — how to report a vulnerability privately.
  • CONTRIBUTING.md — branch protection rules, how to run the checks, what a good PR looks like.

These take twenty minutes to write and prevent the two most common open-source conversations: "can I use this?" and "where do I report a bug?"

4. Deployment is part of the feature set

A release should not depend on my laptop being awake.

  • Backends and web apps are containerized and published to GHCR; production is a docker-compose.prod.yml and a .env file.
  • The portfolio you are reading is a static Next.js build deployed on every push.
  • Android builds signed APKs in CI and attaches them to GitHub Releases. Ratio is deliberately not on Google Play.
  • Desktop apps produce Windows/Linux/macOS bundles and a signed Android artifact from the same CI matrix.

When release is automatic, you release more often, which means you get feedback earlier and the delta between versions stays small enough to debug.

5. Write the docs as if explaining to yourself in six months

Every project has a docs/ page or README section for the parts that are not obvious:

  • Enclave documents the full key-derivation and handshake flow.
  • Nexus documents the retrieval weights and how to change models.
  • Sentinel documents exit codes and CI recipes.
  • Tempo documents the authoring model, camera presets, and export pipeline.

Six-months-later me has forgotten every non-obvious decision. The documentation is a gift to that person, and it happens to be the best marketing material a project can have.

6. Ship the smallest useful version, then write about it

The last step is the one most developers skip: writing. Every project gets a blog post explaining what it is, why it exists, and the interesting engineering underneath. That does three things:

  1. It forces clarity. If I cannot explain the architecture, I do not understand it yet.
  2. It is genuinely useful to the next person solving a similar problem.
  3. It gives the project a discoverable home beyond a repository.

This post is the meta version of that habit.

The meta-lesson

The process is not impressive — that is the point. It is a template. Ideas are cheap and abundant; the scarce resource is attention after the initial excitement fades. A baseline pipeline means the boring parts of a project are already solved, so the remaining energy goes into the part that made the idea worth starting.

If you are juggling multiple side projects, my advice is not to work harder. Standardize. Pick the gates, the quickstart shape, and the release path once — then every new repository starts on third base.

The stack, for anyone curious:

  • TypeScript monorepos: pnpm workspaces, Turborepo, tRPC, Drizzle, PostgreSQL 16
  • Frontend: React + Vite or SvelteKit + Tailwind, Three.js when it is 3D
  • Systems: Rust, Tauri v2, SQLCipher, tokio
  • Mobile: Kotlin + Jetpack Compose
  • Scripts and tooling: Python 3.11+ standard library
  • Everything: GitHub Actions, GHCR, CodeQL, gitleaks, Dependabot