Documentation
Self-hosting guide
Costwatch is a Next.js app backed by Supabase (Postgres, Auth and Row Level Security). There is no other server to run. This guide takes you from a fresh clone to a deployed instance.
Requirements
- Node.js 20.9 or newer
- A Supabase project (the free tier is enough), or the Supabase CLI with Docker for a fully local setup
1. Create a Supabase project
Create a project at supabase.com. From Project Settings → API, copy the Project URL and the anon / publishable key.
You will never need the service_role key. Costwatch talks to the database only as the signed-in user, so Row Level Security is always enforced.
2. Set up the database
Clone the repository and push the migrations with the Supabase CLI:
git clone https://github.com/App-Chef/costwatch.git
cd costwatch
npx supabase login
npx supabase link --project-ref <your-project-ref>
npx supabase db pushPrefer not to use the CLI? Open the SQL editor in the Supabase dashboard and run each file in supabase/migrations in order.
For a local database instead, run npx supabase start and then npx supabase db reset. That also loads supabase/seed.sql: a demo account (demo@example.com / costwatch-demo) with made-up example data. Never load the seed into a production project.
3. Environment variables
Copy web/.env.example to web/.env.local and fill it in:
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-or-publishable-key
NEXT_PUBLIC_SITE_URL=http://localhost:3000
NEXT_PUBLIC_AUTH_GOOGLE_ENABLED=falseNEXT_PUBLIC_SITE_URLis used for auth email links, the sitemap and social previews. Set it to your public URL in production.NEXT_PUBLIC_AUTH_GOOGLE_ENABLEDshows the Google button. Only turn it on after configuring the provider (below).
4. Configure authentication
In Authentication → URL Configuration, set the Site URL to your public URL and add these Redirect URLs:
http://localhost:3000/auth/callback
https://your-domain.com/auth/callbackEmail/password and magic links work out of the box. Supabase's built-in email sender is heavily rate limited, so configure a custom SMTP provider before inviting real users.
Google (optional): create an OAuth client in Google Cloud Console with the authorized redirect URI shown in Authentication → Providers → Google, paste the client ID and secret there, then set NEXT_PUBLIC_AUTH_GOOGLE_ENABLED=true.
5. Run it
cd web
npm install
npm run devOpen http://localhost:3000, create an account and add your first product.
6. Deploy
Any host that runs Next.js works. On Vercel, import the repository, set the root directory to web, add the environment variables above, and deploy. Remember to add your production /auth/callback URL to Supabase.
How the numbers work
- Monthly cost is an estimate: the monthly equivalent of every active recurring cost. Yearly costs are divided by 12, quarterly by 3, and custom intervals by their length in months (using 365.25 days per year).
- One-time costs are shown separately and are not part of the monthly cost.
- Paused and inactive costs are kept but not counted.
- Estimated profit = revenue recorded this month − monthly cost. Profit margin = profit ÷ revenue × 100. With no revenue, no margin is shown.
- Currencies are never converted. Each product has a primary currency; costs and revenue in other currencies are listed but left out of totals, with a note saying so.
- Renewals use the next renewal date you enter. If that date has passed, Costwatch projects the next one from your billing cycle and marks it as estimated.
- Cost history is recorded automatically whenever a cost's price, billing cycle or status changes.
What Costwatch is not
Costwatch answers one question: how much does my product actually cost me? It is not accounting software. It does not do invoicing, taxes, payroll or bank connections, and nothing in it is financial advice.