Zero-Config CI for Solo Projects: What I Set Up in 20 Minutes
What You’ll Learn
- Why solo developers need CI even more than large teams
- The minimum viable GitHub Actions pipeline I use for every project
- How to automate linting, type checking, and basic tests
- Why I skip complex matrix builds and staging environments for small projects
- The exact
.github/workflows/ci.ymltemplate I copy-paste into every repo
I don’t use complex CI setups for solo projects.
When you work alone, CI is not about coordinating with teammates or enforcing code review policies. It is about catching the stupid mistakes you make when you are tired, moving too fast, or distracted by three other projects.
If a CI pipeline takes more than 20 minutes to set up for a new solo project, I probably won’t do it.
That is why I rely on a zero-config, copy-paste approach that gives me 80% of the value for 5% of the effort.
Why Solo Developers Need CI
When you are the only developer, you are also the only QA tester, the only release manager, and the only person who gets paged when something breaks.
You don’t have a colleague to review your PR and point out that you forgot to run npm run build locally before merging.
A basic CI pipeline acts as a safety net. It ensures that the code you push actually compiles, passes type checks, and doesn’t contain obvious syntax errors. It means you can merge with confidence, even if you just woke up and haven’t had coffee yet.
The Minimum Viable Pipeline
My ideal solo pipeline does exactly three things:
- Installs dependencies
- Runs the linter and formatter
- Runs the type checker (and tests, if they exist)
I don’t bother with matrix builds across five different Node.js versions. I don’t set up dedicated staging environments unless the client explicitly pays for it. I just want to know if the main branch is broken.
The Template
Here is the exact .github/workflows/ci.yml file I use for almost every Node.js or Next.js project.
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run type check
run: npm run typecheck --if-present
- name: Run tests
run: npm test --if-present
- name: Build project
run: npm run build
Why This Works
This workflow is entirely standard, but the specific choices matter:
actions/setup-nodewith caching: Cachingnpmsaves precious seconds on every run. When you push a quick fix, waiting 3 minutes for dependencies to download is agonizing.npm ciinstead ofnpm install: This guarantees a clean install based on thepackage-lock.json. It prevents the classic “it works on my machine” problem where your localnode_modulesis out of sync.--if-presentflags: This is the secret to a reusable template. If I haven’t set up tests yet, the pipeline doesn’t fail. It just skips that step and moves on.
What I Skip
For a solo project, I aggressively avoid:
- Matrix testing: Unless I’m building an open-source library that explicitly needs to support Node 16, 18, and 20, I only test on the current LTS version.
- E2E tests in CI: Cypress and Playwright are great, but they are often flaky and slow down the build. I run them locally before major releases, not on every push.
- Complex deployment scripts: I let Vercel or Cloudflare Pages handle the actual deployment. The CI pipeline’s only job is to verify the code. Deployment is a separate concern.
Setting Up package.json
For the template to work smoothly, your package.json needs to have the corresponding scripts defined. Even if they are basic, they should exist.
{
"scripts": {
"dev": "next dev",
"build": "next build",
"lint": "next lint",
"typecheck": "tsc --noEmit",
"test": "vitest run"
}
}
The typecheck script is crucial. TypeScript is your best friend when working alone, but only if you actually run the compiler. next build usually does this, but having a dedicated typecheck script allows you to fail faster.
The Cost of Skipping CI
I’ve skipped setting this up on “quick weekend projects” before. Invariably, I end up pushing a typo that breaks the production build. Then I have to wait for Vercel to fail, read the logs, fix the typo, push again, and wait for Vercel to rebuild.
The 20 minutes spent adding a .github/workflows/ci.yml file pays for itself the very first time it catches a missing import or a type error.
Closing
That is the entire setup. One YAML file, a few standard npm scripts, and you have a reliable safety net that prevents embarrassing broken builds. It doesn’t require maintaining complex infrastructure, and it scales perfectly from a weekend prototype to a serious freelance project.
Building something similar? VoidCraft takes freelance projects in AI tooling, desktop apps, and automation.