Personal time tracking and invoicing application for independent developers working with multiple clients.
- Backend: Rails 8.1 with Ruby 3.3
- Frontend: React 19 + TypeScript via Inertia.js
- UI: Tailwind CSS + shadcn/ui
- Database: SQLite3
- PDF: Grover (Puppeteer-based)
bundle install
npm install
bin/rails db:preparebin/dev # Start Rails + Vite dev serversAccess the app at http://localhost:5100
Work on multiple features simultaneously with isolated environments.
# Build a new feature with Claude Code
bin/build-feature "feature-name" "Description of what to build"
# Example
bin/build-feature "invoice-reminders" "Add email reminders for unpaid invoices"| Command | Description |
|---|---|
bin/build-feature <name> <prompt> |
Create worktree and start Claude with /build |
bin/worktree-setup <name> |
Create isolated worktree for manual development |
bin/dev-feature <name> |
Run dev server with feature-specific ports (same directory) |
Each parallel environment gets:
- Separate directory:
../invoicing-<feature-name> - Own git branch:
feature/<feature-name> - Isolated database:
storage/development-<feature-name>.sqlite3 - Unique ports: Rails 3001+, Vite 3137+
# Terminal 1 - main development
cd invoicing
bin/dev # Rails: 5100, Vite: 3036
# Terminal 2 - feature work
bin/build-feature "auth" "Add user authentication"
# Creates ../invoicing-auth and starts Claude
# Terminal 3 - another feature
bin/build-feature "reports" "Add monthly revenue reports"
# Creates ../invoicing-reports and starts Claude# List all worktrees
git worktree list
# Remove a worktree when done
git worktree remove ../invoicing-<feature-name>
# Clean up merged branches
git branch -d feature/<feature-name># Backend
bundle exec rspec
# Frontend
npm test # Watch mode
npm run test:run # Single run
npm run typecheck # TypeScript checknpm run build # Production frontend buildThis is a single-user application designed for personal use. It uses Kamal to deploy Docker containers to your own VPS.
- A VPS with SSH access (Ubuntu 22.04+ recommended)
- Docker installed on your local machine
- A container registry (Docker Hub, GitHub Container Registry, or AWS ECR)
- A domain name pointed to your VPS IP address
SSH into your VPS and install Docker:
curl -fsSL https://get.docker.com | shEnsure your user can run Docker without sudo, or use root for deployment.
-
Copy the deploy configuration template:
cp config/deploy.yml.example config/deploy.yml
-
Create a
.envfile with your deployment variables:DEPLOY_SERVER_IP=your.server.ip.address PROXY_HOST=your-domain.com
-
Edit
config/deploy.ymland configure:service: Your application nameimage: Container image nameregistry: Your container registry details- Update the
passwordcommand for your registry (e.g.,aws ecr get-login-passwordfor AWS ECR)
-
Configure secrets in
.kamal/secrets:# For AWS ECR AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY # Rails master key (required) RAILS_MASTER_KEY=$(cat config/master.key)
# First-time setup (provisions server and deploys)
bin/kamal setup
# Subsequent deployments
bin/kamal deployA default admin user is created during deployment with these credentials:
- Email:
admin@example.com - Password:
password
You must change these immediately after deployment:
# Connect to Rails console on the server
bin/kamal console
# In the Rails console, update the user:
user = User.first
user.update!(email_address: "your-email@example.com", password: "your-secure-password")
exitbin/kamal console # Rails console on server
bin/kamal shell # Bash shell in container
bin/kamal logs # Tail application logs
bin/kamal app restart # Restart the applicationKamal automatically provisions SSL certificates via Let's Encrypt when proxy.ssl: true is set. Ensure your domain's DNS is properly configured before the first deployment.






