Vault is a small personal dashboard for tracking recurring subscriptions and stored balances in one place. It combines subscription renewals, digital credits, and lightweight spending insights in a single React app backed by Firebase Firestore and Firebase Authentication.
- Tracks recurring subscriptions with category, billing cycle, renewal date, status, notes, and icon metadata
- Tracks balances such as gift cards, store credit, ride credits, and reward points
- Shows a dashboard with portfolio totals, monthly recurring cost, upcoming renewals, and quick insights
- Includes dedicated views for subscriptions, balances, analytics, and adding new entries
- Reads and writes data from Firebase Firestore for subscriptions and balances
- React 19
- TanStack Start
- TanStack Router with file-based routes
- Vite
- Tailwind CSS v4
- Firebase Firestore
- Firebase Authentication
src/
components/
Sidebar.tsx
TopBar.tsx
lib/
auth.tsx
firebase.ts
routes/
__root.tsx
index.tsx
subscriptions.tsx
balances.tsx
analytics.tsx
add.tsx
The home screen aggregates the current tracked data and highlights:
- total balance across stored-value accounts
- normalized monthly subscription spend
- upcoming renewals
- recent subscription entries
- static savings insight cards
The subscriptions page includes:
- category filters
- sorting by renewal date, price, or name
- urgent renewal warnings
- a high-cost alert when one subscription dominates monthly spend
The balances page includes:
- total estimated balance
- reward points summary
- expiring credit alerts
- a visual placeholder trend chart
The analytics page includes:
- monthly and yearly spend summaries
- category spend breakdown
- top expenses
- a simple monthly trend visualization
The add page supports creating either:
- a subscription
- a balance
Subscriptions and balances are persisted through Firestore via the helpers in src/lib/firebase.ts.
namecategorycostbillingCycle:monthly | yearly | quarterlynextRenewalstatus:active | paused | cancellediconnotescreatedAt
nametypeamountexpiresAticonnotescreatedAt
Install dependencies and start the dev server:
npm install
npm run devThe app runs on http://localhost:3000.
This app uses Firebase Firestore for data persistence. You need to set up a Firebase project and provision a Firestore database.
- Create a Firebase project at Firebase Console.
- Create a local
.envfile in the project root with these values:
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECT_ID=
VITE_FIREBASE_STORAGE_BUCKET=
VITE_FIREBASE_MESSAGING_SENDER_ID=
VITE_FIREBASE_APP_ID=
VITE_ALLOWED_EMAIL=VITE_ALLOWED_EMAIL is optional. When set, only that Google account can use the app.
- Log in to Firebase CLI:
npx firebase-tools login- Create the Firestore database:
npx firebase-tools firestore:databases:create "(default)" --project <your-project-id> --location=us-east1- Deploy security rules:
npx firebase-tools deploy --only firestore:rules --project <your-project-id>Replace <your-project-id> with the value used in VITE_FIREBASE_PROJECT_ID.
If Firebase is not configured correctly, Firestore reads and writes will fail until the project configuration and rules are set correctly.
- The app uses Google sign-in through Firebase Authentication.
- App data is stored in user-scoped Firestore collections:
users/{uid}/subscriptionsusers/{uid}/balances
- If you previously stored data in top-level
subscriptionsorbalancescollections, move that data into the authenticated user'susers/{uid}namespace before relying on the new locked-down rules.
If you already have data in top-level subscriptions and balances, you can copy it into your authenticated user's namespace with the included script.
- Get your Firebase Auth
uidfromAuthentication > Usersin the Firebase Console. - Download a service account JSON from
Project settings > Service accounts. - Run:
npm run migrate:user-data -- --uid=YOUR_UID --service-account=/absolute/path/to/service-account.jsonOptional:
- Add
--overwriteto replace docs that already exist inusers/{uid}/.... - If you already exported
GOOGLE_APPLICATION_CREDENTIALS, you can omit--service-account.
The script copies:
subscriptions/*->users/{uid}/subscriptions/*balances/*->users/{uid}/balances/*
npm run dev
npm run build
npm run preview
npm run testCreate a production build:
npm run buildRun the test suite:
npm run test- Firestore rules live in firestore.rules.
- Firebase hosting configuration lives in firebase.json.
- The current UI uses generated placeholder visuals in a few places, such as the balance and monthly trend charts.