Skip to content

fuongz/subscription-management

Repository files navigation

PhakeSub

A clean, fast subscription tracker built on Cloudflare's edge. Know exactly where your money goes every month.

What it does

  • Track subscriptions β€” Add from built-in templates (Netflix, YouTube, Claude, etc.) or create custom entries
  • Auto-calculate renewals β€” Next billing date updates automatically based on your billing cycle
  • See your spending β€” Monthly/yearly totals, category breakdowns, upcoming renewals at a glance
  • Google sign-in β€” One-click OAuth alongside email/password auth

Tech stack

Layer Tech
Framework TanStack Start + React 19 + TypeScript
Database Cloudflare D1 (SQLite) via Drizzle ORM
Auth Better Auth with Google OAuth
UI shadcn/ui + Tailwind CSS v4
Animations Motion
Validation Zod
Deployment Cloudflare Workers

Getting started

# Install dependencies
bun install

# Set up local secrets (create .dev.vars from example)
cp .env.example .dev.vars
# Then fill in your secrets in .dev.vars

# Run database migrations
bun run db:migrate

# Start dev server
bun run dev

App runs at http://localhost:3002.

Environment variables

Non-secret config goes in .env. Secrets go in .dev.vars (local) or Wrangler secrets (production).

Variable Where Description
BETTER_AUTH_URL .env App URL (http://localhost:3002 for dev)
BETTER_AUTH_SECRET .dev.vars Session signing key
BETTER_AUTH_GOOGLE_CLIENT_ID .dev.vars Google OAuth client ID
BETTER_AUTH_GOOGLE_CLIENT_SECRET .dev.vars Google OAuth client secret

Deploy to Cloudflare

# Set production secrets (encrypted, nobody can read them back)
wrangler secret put BETTER_AUTH_SECRET
wrangler secret put BETTER_AUTH_URL
wrangler secret put BETTER_AUTH_GOOGLE_CLIENT_ID
wrangler secret put BETTER_AUTH_GOOGLE_CLIENT_SECRET

# Run migrations on production D1
bun run db:migrate:prod

# Deploy
bun run deploy

Don't forget to add your production callback URL in Google Cloud Console:

https://<your-worker>.workers.dev/api/auth/callback/google

Project structure

src/
β”œβ”€β”€ routes/              # File-based routing
β”‚   β”œβ”€β”€ index.tsx        # Landing page
β”‚   β”œβ”€β”€ login.tsx        # Sign in
β”‚   β”œβ”€β”€ register.tsx     # Sign up
β”‚   └── _authed/         # Protected routes
β”‚       β”œβ”€β”€ dashboard.tsx
β”‚       └── subscriptions/
β”œβ”€β”€ components/          # UI components
β”œβ”€β”€ server/              # Server functions + DB queries
β”œβ”€β”€ db/                  # Schema + migrations
β”œβ”€β”€ lib/                 # Auth, utils
└── data/                # Subscription templates

Built-in templates

Ready-to-use templates with real pricing for quick entry:

Netflix, YouTube Premium, Claude, 1Password, Duolingo, iCloud+, Google One

Scripts

Command Description
bun run dev Start dev server
bun run build Production build
bun run deploy Build + deploy to Cloudflare
bun run db:generate Generate Drizzle migrations
bun run db:migrate Apply migrations (local)
bun run db:migrate:prod Apply migrations (production)
bun run test Run tests

Security

  • All server functions require authentication
  • Row-level authorization β€” users only see their own data
  • Zod runtime validation on every input
  • CSP, X-Content-Type-Options, and Referrer-Policy headers
  • Secrets stored via Cloudflare encrypted secrets, not in code
  • Parameterized queries via Drizzle ORM β€” no SQL injection

Built with care by @phuongphung and Claude.

About

πŸ€– I vibe coding with Claude for this application!

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors