GigFin helps gig workers keep a simple, reliable ledger of their overall income across platforms alongside monthly trends and platform breakdowns. Because the app focuses on platform-level income totals, it currently does not track individual line items per platform. Recent updates add customizable dashboards, built-in expense tracking, and vehicle profiles while keeping the same responsive Next.js dashboard, Better Auth–powered credential login, 2FA, and fast SQLite + Drizzle ORM backend so you can log earnings securely from any device.
A hosted instance is available at https://gigfin.me, but GigFin is designed for self-hosting, and deploying your own instance is the recommended way to keep your data private and under your control.
- Customizable, feature-rich dashboard: Totals, average‑per‑day, and platform mix charts plus recent daily summaries pair with configurable cards, metric prioritization, and saved layouts.
- Detailed expense tracking: Capture receipts, tag costs to gigs, and keep deductible-ready summaries beside your income totals.
- Vehicle profiles & maintenance: Track each bike or car with fuel, mileage, and service notes so every trip stays tied to the right ride.
- Log & filter entry history: Add income per platform and filter by months or platforms to compare runs.
- Local persistence: Drizzle + SQLite stores every entry in
/app/data/db.sqlite, so the Docker stack keeps state in a named volume. - Security-first auth: Credential login, signup, and optional 2FA flows powered by Better Auth keep sessions locked down.
- Theming & accessibility: Adaptive light/dark styles bring clarity to the hero copy, quick add forms, and stats view.
- Next.js 16 (App Router) & React 19
- Drizzle ORM / Drizzle-Kit for migrations and SQLite helpers
- better-auth for token management, signup/login, and Two-Factor Auth
- TanStack Query & Table, Recharts, and DaisyUI/Tailwind for the UI surfaces
- Node.js (LTS recommended) for local development
- Docker + Docker Compose for production/self-hosting
GigFin expects the following values at runtime (set them via Coolify, another secrets manager, or a local .env file loaded with dotenv):
BETTER_AUTH_SECRET(required): a secure string that Better Auth uses for signing. Generate one withnpx @better-auth/cli@latest secretoropenssl rand -base64 32, then keep it out of version control.BETTER_AUTH_URL(required): the public URL where your GigFin instance is reached (for examplehttps://gigfin.meor your custom domain). It must match the redirect URL configured in Better Auth.DB_FILE_NAME(optional): connection string for SQLite (default:file:./data/db.sqlite). If you override it, make sure the path matches the named Docker volume or host directory you that want to persist.INTERNAL_API_BASE(optional): internal API endpoint that GigFin pings (default:http://localhost:3000). Change it only if you run the frontend and backend on different hosts.ANALYTICS_SCRIPT_URL(optional): URL to an external analytics script (e.g. Rybbit, Plausible, Umami). When set together withANALYTICS_SITE_ID, the script is injected into every page.ANALYTICS_SITE_ID(optional): site identifier passed asdata-site-idto the analytics script. BothANALYTICS_SCRIPT_URLandANALYTICS_SITE_IDmust be set for analytics to load.
Bake these values into .env before running npm scripts or supply them through your orchestration platform so they are available to both the build and runtime environments.
-
Build and run the containerized stack:
docker compose up --build
-
The multi-stage
Dockerfileseeds/app/data/db.sqliteby runningnpx drizzle-kit migratewhen the file is absent and copies/app/datainto the runner stage. -
docker-compose.ymlbinds thegigfin-datavolume to/app/data, so the SQLite database survives restarts. -
Docker Compose sources runtime environment variables from
.env(see theenv_filesection indocker-compose.yml); store secrets there or inject them from your deployment platform.
Bring it down with docker compose down when you need to rebuild.
A multi-platform Docker image (linux/amd64 and linux/arm64) is published to GHCR on every push to main:
docker pull ghcr.io/sayedhfatimi/gigfin:latestTo run it directly:
docker run -d \
-p 3000:3000 \
-v gigfin-data:/app/data \
-e BETTER_AUTH_SECRET=your-secret \
-e BETTER_AUTH_URL=https://your-domain.com \
ghcr.io/sayedhfatimi/gigfin:latestPin a specific version for stability (e.g. ghcr.io/sayedhfatimi/gigfin:1.2.3).
- Fork the repo and add it as a new service in Coolify, picking the private repository option if you want automatic builds on updates.
- In Coolify select the docker-compose deployment option, provide the required environment variables, and deploy—no extra build configuration is needed once the stack starts.
This section explains how to set up a local development environment for hacking on GigFin or contributing changes. If you only need to run a production instance, skip ahead to Docker & Compose or Deployment guidance.
-
Install dependencies:
npm install
-
Copy
.env.example(if it exists) to.envor create your own file with the recommended values and add any additional secrets you need.DB_FILE_NAME=file:./data/db.sqlite BETTER_AUTH_SECRET=your-secret BETTER_AUTH_URL=http://localhost:3000
-
Generate or refresh the SQLite schema whenever you change database definitions:
npx drizzle-kit migrate
-
Start the dev server:
npm run dev
Next.js watches your changes and reloads automatically. Open http://localhost:3000 in a browser to log in or sign up as a gig worker.
Once you have a working dev environment, run npm run lint and npm run build to verify there are no formatting or compilation issues before opening a PR.
- Run
npm run buildto compile the app for production; the Docker build stage already runs this. - Run
npm run lintto validate formatting and coding standards via Biome.
PRs welcome. Before opening one:
- Fork the repo, create a feature branch, and keep commits focused (squash or rebase before merging).
- Follow Getting started (local development), then refresh migrations and run
npm run lintplusnpm run buildto confirm the changes pass checks. - Link relevant issues in the PR description, explain your approach, and note any follow-up work or deployment steps.
When the branch is ready, open a PR targeting main, include screenshots or recordings if you touched the UI, and wait for CI to pass before merging.
This project is MIT licensed. See LICENSE for the full text.



