1The decision
My default stack for small client portals and operational dashboards is Next.js on Vercel, backed by Supabase, with Resend for email. GitHub is the source repository. Hermes, reached through Telegram, is the developer and operator.
This is a default, not a religion. I can replace a component when an app has a real reason. The point is that a new project no longer starts with another week of framework comparison.
Telegram request → Hermes edits the GitHub repo → tests run → Vercel deploys → Supabase enforces data access → Hermes verifies the live app.
2Why it fits how I work
I am not trying to become a full-time maintainer of five bespoke web stacks. I build data products, SAP tools, client dashboards, and internal systems. The interesting part is the domain model and the workflow, not whether I can save a few euros by stitching together a more exotic deployment setup.
The stack fits my operating model for four reasons:
- Agents know the terrain. Next.js, TypeScript, Postgres, and the Supabase and Vercel CLIs have large documentation surfaces and predictable project structures.
- Everything is scriptable. Hermes can create migrations, run tests, manage environment-variable names, deploy, inspect logs, and verify the live URL without needing me to click through every dashboard.
- The backend is mostly assembled. Supabase supplies the database, authentication, file storage, and row-level authorization. That removes a lot of custom infrastructure.
- Production is close to development. The same repository contains the interface and the small amount of server logic. Vercel turns a pushed commit into a preview or production deployment.
That last point matters. A cheaper platform that creates more deployment edge cases is not actually cheaper when every issue turns into another Telegram debugging session.
3The authorization model
My typical app has consultants and customers who may access different projects. That is not a global role problem. It is a membership problem.
users
└── project_members
├── project_id
├── user_id
└── role: consultant | client_admin | client_viewer
projects
├── project A
├── project B
└── project C
Every project-owned row carries a project_id. Supabase Row Level Security checks whether the current user has membership of that project. The frontend may hide buttons, but the database remains the final authority.
This is the main reason I choose Supabase Auth rather than adding Better Auth by default. Supabase Auth already connects user identity to Postgres policies. Adding a separate authentication system would give me another session model while leaving project authorization to solve separately.
4Why I rejected the alternatives
| Alternative | Why it is not my default |
|---|---|
| Better Auth | Good product, but redundant when Supabase already owns authentication and database authorization. I would use it if I moved away from Supabase or needed auth-provider independence. |
| React + Vite | Simpler for a pure browser dashboard, but I routinely need invites, privileged actions, webhooks, exports, or server-only integrations. Next.js keeps those in the same repo. |
| Cloudflare | Potentially cheaper hosting, but Next.js compatibility and platform differences add another seam. I would choose it for a high-volume edge workload, not as the boring default. |
| Firebase | Fast to start, but my work is relational: clients, projects, memberships, datasets, mappings, and audit trails. Postgres is a more natural model. |
| Custom API backend | More control, but also more code, deployment, authentication plumbing, and operational ownership before the product has earned it. |
The critical correction is that I am not selecting the cheapest individual services. I am selecting the lowest-friction complete route from idea to a verified production app.
5The agent contract matters more than the logos
Calling a stack “agent-first” because it uses popular tools is too easy. The repository must make the desired behavior obvious and verifiable.
app/ # screens and server routes
components/ # reusable interface parts
lib/supabase/ # typed clients and auth helpers
supabase/migrations/ # canonical schema and RLS changes
supabase/seed.sql # consultant, customer, and project fixtures
tests/ # authorization and behavior tests
AGENTS.md # build, test, deploy, and safety rules
For every project-owned table, the baseline is simple:
- a project identifier;
- a Row Level Security policy;
- a negative test proving another customer cannot read it;
- generated TypeScript types from the real database schema;
- a live deployment check after push.
Configuration should live in migrations and repository files, not only in web dashboards. Secrets stay in provider environment stores. Hermes receives tooling and scoped credentials, not a license to dump production keys into logs.
6Where free tiers end
This stack is cheap to start, but I do not pretend that a real client system should remain free forever. Vercel's Hobby plan is for personal, non-commercial use. Supabase free projects have limits and may pause after inactivity. Those are fine constraints during development, not a production reliability strategy.
My rule is:
- Prototype: use the free tiers.
- Internal experiment: stay free while the consequences of downtime are small.
- Client dependency: move to paid plans, backups, monitoring, and a tested restore path.
The first paid bill is not failure. It means the app has become important enough that reliability is worth buying. I would rather pay predictable platform costs than spend my own time maintaining a clever free stack.
The relevant provider boundaries are documented by Vercel's Hobby plan, Supabase's production checklist, and Resend's pricing model.
Final choice: Next.js + Vercel + Supabase + Resend, with GitHub as the source and Hermes/Bertus as the Telegram-controlled developer. Boring on purpose. The architecture should leave my attention for project authorization, data quality, and the actual client problem.