Skip to main content
COSMICBYTEZLABS
NewsSecurityHOWTOsToolsStudyTraining
ProjectsNewsletterHire MeAbout
Subscribe

Press Enter to search or Esc to close

News
Security
HOWTOs
Tools
Study
Training
Projects
Newsletter
Hire Me
About
RSS Feed
Reading List
Subscribe

Stay in the Loop

Get the latest security alerts, tutorials, and tech insights delivered to your inbox.

Subscribe NowFree forever. No spam.
COSMICBYTEZLABS

Your trusted source for IT intelligence, cybersecurity insights, and hands-on technical guides.

1184+ Articles
136+ Guides

CONTENT

  • Latest News
  • Security Alerts
  • HOWTOs
  • Checklists
  • Projects
  • Exam Prep

RESOURCES

  • Search
  • Browse Tags
  • Newsletter Archive
  • Reading List
  • RSS Feed

COMPANY

  • About Us
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CosmicBytez Labs. All rights reserved.

System Status: Operational
  1. Home
  2. Projects
  3. Subscription Tracker: A 2-Tier Storage PWA for Recurring Expenses
Subscription Tracker: A 2-Tier Storage PWA for Recurring Expenses
PROJECTIntermediate

Subscription Tracker: A 2-Tier Storage PWA for Recurring Expenses

Track subscriptions, utility bills, and payments with auto-payment generation and analytics — one Next.js codebase that runs on Docker with SQLite or on Vercel with localStorage, no per-target branching above the data layer.

Dylan H.

Projects

May 5, 2026
3 min read
3-5 hours

Tools & Technologies

Next.js 14better-sqlite3RechartsDocker

Overview

Subscriptions accumulate quietly. Streaming, software, utilities, the gym you stopped going to in February — by the end of the year it adds up to a number that's surprising in the worst way. This Next.js app catalogs them, generates expected payments on schedule, and surfaces the trends in a dashboard. The interesting bit is the storage layer: the same code runs on Docker with SQLite or on Vercel with localStorage, no environment-specific UI branching.

Stack

  • Framework: Next.js 14.2, React 18, TypeScript (strict)
  • Styling: Tailwind CSS 3.4 with emerald theme + dark mode
  • Database: SQLite (better-sqlite3) for Docker, localStorage fallback for Vercel/demo
  • Cloud Sync: Supabase (optional)
  • Charts: Recharts 2.12
  • Dates: date-fns 3.6
  • Testing: Jest 29 + React Testing Library
  • Deployment: Docker (primary) + Vercel (demo mode)

Key Features

  • Subscription and utility-bill CRUD with a tab bar
  • Auto-payment generation with multi-cycle catchup for missed billing periods
  • Dashboard: stats, due-soon list, recent payments, cost donut chart
  • Analytics: cost trends, category breakdown, price changes, lifetime spend
  • Category management (12 default categories, custom categories supported)
  • Theme system: light/dark + accent color picker
  • Demo data on first visit with a merge strategy (user items first, then filtered demo data)
  • PWA with offline support

2-Tier Storage

  • DATABASE_TYPE=sqlite enables SQLite mode (Docker deployment).
  • Without it, the app falls back to localStorage (Vercel/demo mode).
  • An /api/config endpoint exposes the sqliteEnabled flag to the client.
  • Hooks call isSQLiteMode() and branch accordingly.
  • Row mappers handle SQLite ↔ TypeScript conversions: INTEGER ↔ boolean, TEXT ↔ JSON arrays.

Data Model (4 tables)

TableNotes
categoriesSeeded with 12 defaults via INSERT OR IGNORE on init
subscriptionsFK to categories, tags stored as JSON text
utility_billsFK to categories
paymentsFK to subscriptions or utility_bills; status = paid/pending/missed/skipped

WAL journal mode, foreign keys enabled.

localStorage Keys (fallback mode)

All prefixed with sub-tracker-: subscriptions, utilities, payments, categories, theme, accent-color, plus deleted-*-ids tracking.

State Management

Pure Context API — no Redux, no Zustand. A ThemeProvider for light/dark + accent colors, plus custom hooks for every data operation.

Environment Variables

VariablePurpose
DATABASE_TYPESet to sqlite to enable SQLite backend
DATABASE_PATHDirectory for subscription-tracker.db
NEXT_PUBLIC_SUPABASE_URLOptional cloud sync
NEXT_PUBLIC_SUPABASE_ANON_KEYOptional cloud sync

Lessons Learned

  • All npm commands run from the web-app/ subdirectory, not the project root — bind that to muscle memory or you'll wonder why nothing builds.
  • Next.js 14 needs experimental.serverComponentsExternalPackages: ['better-sqlite3'] for native modules to load.
  • Track deleted demo IDs separately or you'll re-create them every page reload.
  • API routes return 501 when SQLite is disabled. That's intentional — the client uses it as a feature-detection signal.

Testing

112 tests (Jest + React Testing Library). CI runs lint → test → build on every PR.

#Next.js#PWA#SQLite#localStorage#Recharts#Personal Finance

Related Articles

Orbit: An Offline-First Fitness PWA with Dual Storage Backend

A household fitness PWA with weight tracking, meal planning, workouts, and pantry — built on Next.js 15 with a single codebase that runs against either Supabase or local SQLite, plus an IndexedDB mutation queue for offline.

3 min read

Self-Hosted IPTV Manager with HDHomeRun Emulation for Plex

An IPTV stream manager that pretends to be an HDHomeRun tuner so Plex DVR can record over-the-air-style live TV — M3U import, tier-based channel classification, FFmpeg HLS remux, and an XMLTV EPG.

3 min read

How CosmicBytez Labs Is Built: Next.js 16, velite, and Resend

A meta writeup about this site — content pipeline via velite (the contentlayer2 successor), a Resend-backed newsletter wired through a Vercel cron, the IT exam prep with 770 practice questions across 11 cert tracks, and the 8-tool utility suite.

3 min read
Back to all Projects