Mike (@mikerb95)CodeByMike
Back
/architectureSystems design

How this is built.

This site is a system in production: a private panel, a client portal, real payments, in-house monitoring and security, and AI agents. Here is its anatomy, from the visitor request down to the database, and the reason behind each piece. Most of them can be seen running.

Pick who arrives and watch how far they really get. The path comes from the same functions the middleware runs, so it cannot tell a different story.

First visitGET /status
  1. SSR HTML + islandsThe browser asks for the page.
  2. Vercel WAFThe Vercel WAF sees nothing odd and lets it through.
  3. Cached CDNThe CDN has no fresh copy (MISS): the page has to be built.
  4. Node functionsA Vercel Node function wakes up.
  5. One canonical pathThe middleware strips the language and trailing slash: every guard sees the canonical path.
  6. Micro-SIEMThe micro-SIEM sensor classifies it: normal traffic.
  7. Public siteAstro renders the public page on the server.
  8. Reads on a budgetIt reads the daily monitor summary, not raw rows: Turso bills rows scanned.

200 · MISSThe response stays in the CDN for 5 minutes: this request paid for the SSR of the next ones.

Within the next 5 minutesGET /status
  1. SSR HTML + islandsThe browser asks for the page.
  2. Vercel WAFThe Vercel WAF sees nothing odd and lets it through.
  3. Cached CDNThe CDN holds a copy under 5 minutes old (HIT) and answers by itself.

200 · HITNo function, no database: the SSR was paid once and served many times.

With a known toolGET /
  1. Vercel WAFThe user-agent belongs to an attack tool: the WAF cuts it at the edge, without waking any function.

403It dies before costing a single invocation.

Disguised as a browserGET /.env
  1. Vercel WAFThe path smells like probing, but that WAF rule only logs: blocking here would blind the in-house sensor.
  2. Cached CDNNothing to serve from cache.
  3. Node functionsA Vercel Node function wakes up.
  4. One canonical pathThe middleware strips the language and trailing slash: every guard sees the canonical path.
  5. Micro-SIEMThe sensor recognises a hunt for secrets and logs it in the micro-SIEM.
  6. Public siteNothing lives at that path: 404.

404It gets a 404 and is on record. If it insists, rate limiting and escalating blocks do the rest.

GET /en/admin
  1. SSR HTML + islandsThe browser asks for the page.
  2. Vercel WAFThe Vercel WAF sees nothing odd and lets it through.
  3. Cached CDNNothing to serve from cache.
  4. Node functionsA Vercel Node function wakes up.
  5. One canonical pathAn /en/ in front of a private route has no translation: 404 before anything else.

404Neither the sensor nor the session check gets to run: the panel has no English copy.

GET /admin
  1. SSR HTML + islandsThe browser asks for the page.
  2. Vercel WAFThe Vercel WAF sees nothing odd and lets it through.
  3. Cached CDNPrivate route: the CDN keeps no copy and lets it through.
  4. Node functionsA Vercel Node function wakes up.
  5. One canonical pathThe middleware strips the language and trailing slash: every guard sees the canonical path.
  6. Micro-SIEMThe micro-SIEM sensor classifies it: normal traffic.
  7. Panel authGitHub session on the allowlist and, according to Turso, not revoked.
  8. /admin panelThe panel is rendered, cached nowhere.
  9. Two databasesQueries go to the production database.

200Private 200, uncached and with hardened headers.

GET /portal/facturas
  1. SSR HTML + islandsThe browser asks for the page.
  2. Vercel WAFThe Vercel WAF sees nothing odd and lets it through.
  3. Cached CDNPrivate route: the CDN keeps no copy and lets it through.
  4. Node functionsA Vercel Node function wakes up.
  5. One canonical pathThe middleware strips the language and trailing slash: every guard sees the canonical path.
  6. Micro-SIEMThe micro-SIEM sensor classifies it: normal traffic.
  7. Client portalThe portal has its own cookie, checked against its own sessions table.
  8. Two databasesEvery query filters by the client in the session, never by one coming from the URL.

200The client only sees what is theirs.

Reading the panelGET /admin/finances
  1. SSR HTML + islandsThe browser asks for the page.
  2. Vercel WAFThe Vercel WAF sees nothing odd and lets it through.
  3. Cached CDNPrivate route: the CDN keeps no copy and lets it through.
  4. Node functionsA Vercel Node function wakes up.
  5. One canonical pathThe middleware strips the language and trailing slash: every guard sees the canonical path.
  6. Micro-SIEMThe micro-SIEM sensor classifies it: normal traffic.
  7. Panel authNo session, but a signed demo pass (HMAC): it gets in read-only.
  8. Public demoThe real panel is rendered, in demo mode.
  9. Two databasesQueries come from the demo database, a separate one, with made-up data.

200The real panel, with made-up data.

Asking for the vaultGET /api/admin/services/7/secrets
  1. SSR HTML + islandsThe browser asks for the page.
  2. Vercel WAFThe Vercel WAF sees nothing odd and lets it through.
  3. Cached CDNPrivate route: the CDN keeps no copy and lets it through.
  4. Node functionsA Vercel Node function wakes up.
  5. One canonical pathThe middleware strips the language and trailing slash: every guard sees the canonical path.
  6. Micro-SIEMThe micro-SIEM sensor classifies it: normal traffic.
  7. Panel authThe vault reveals secrets and it is a GET: the demo bans it by pattern. 403.

403"Read-only" was not enough: a GET can reveal things too.

A visitor
GET /status200

The response stays in the CDN for 5 minutes: this request paid for the SSR of the next ones.

Break a piece
Services it touchedVercelTurso

The request is sent again with that piece down.

Piece by piece

Client
Visitor browser
SSR HTML + islands
Astro ships rendered HTML; JS only where the page needs it.
RUM web-vitals
Measures real LCP, INP and CLS in the browser and sends them by beacon.
Edge
Vercel: CDN, WAF and functions
Cached CDN
Public pages are cached for 5 minutes at the edge: SSR is paid once and served many times.
Vercel WAF
Three rules that stop known scanners before they reach a function.
Node functions
Dynamic routes and API, within the free plan quota.
Gate
Middleware: security runs before the page
Micro-SIEM
Classifies every request, applies durable rate limiting and escalating blocks. Fails open: if it breaks, the site stays up.
Panel auth
Allowlist checked again on every request and revocable sessions. Revocation fails closed.
One canonical path
The path is normalized before any guard: /en/admin is not an unwatched copy of the panel.
Chaos flags
Failures injected on purpose to rehearse, bounded so they cannot break production.
Application
Astro 7 SSR: three audiences, three doors
Public site
Showcases that publish aggregates, never data that would work as an attack manual.
/admin panel
CRM, finances, encrypted vault, monitors, lab and the security analyst.
Client portal
Its own login and its own cookies. The client comes from the session, never from the URL.
Public demo
The real panel against a separate database, read-only.
Payments
Payment links with idempotency and signed webhooks, sent over WhatsApp without its API.
Data
Turso (libSQL) + Drizzle
Two databases
Production and demo kept apart; demo mode is chosen per request.
Additive migrations
Typed schema in a single file; a column is never dropped unless asked for.
AES-256-GCM vault
Credentials encrypted at rest and revealed only under an admin session.
Reads on a budget
Turso bills scanned rows: whatever is read often is aggregated per day.
Background
Scheduled jobs and agents
Watched cron jobs
Every run leaves a trace and a watchdog alerts when a job goes quiet.
In-house monitor
Probes every 5 minutes, incidents and SLOs without paid services.
Security analyst
A Claude agent that reads the attacks and proposes blocks; a person decides.
Changelog
What changed each week, taken from the real commits.

External services

Vercel
Hosting, CDN, WAF, per-PR previews and automatic rollback from CI.
Turso
The production libSQL database and the demo one, on the free plan.
cron-job.org
Fires the probe every 5 minutes: Vercel free plan only allows daily cron jobs.
GitHub
Public repository, CI with tests and coverage, and the panel login (OAuth).
Claude API
The security analyst, the chat bubble advisor and the weekly summary. API key only; the analyst and the advisor have a daily spending cap.
ntfy
Phone notifications: outages, silent cron jobs, the morning analysis.
Resend
Transactional email, as a secondary channel.
Wompi
Colombian payment gateway for the payment links.
Vercel Blob
Database backups and portal documents, in a private store.

Decisions and trade-offs

→
SSR, but cached at the edge

The panel and the portal need live data and a session per request. Public pages are cached for 5 minutes on the CDN, so SSR is only paid where it adds something.

Watch it happen: A visitor
→
Fail open everywhere, except authorization

If the security sensor, the rate limiter or a notification fails, the request goes on: a defense that can take the site down is a new attack surface. The exception is panel session revocation, which fails closed: it is permission, not observability.

Watch it happen: Me, in the panel · Turso down
→
Stateless JWT, but revocable

Login does not touch the database. The blind spot of a JWT (not being able to revoke it) was closed with a signed session id inside the token and a devices table.

Watch it happen: Me, in the panel
→
Turso instead of Postgres

Managed SQLite, with a simple mental model for a domain without massive concurrency. The price is thinking about every query in scanned rows: whatever is read a lot is aggregated.

Watch it happen: A visitor
→
External cron jobs with a log

A cron job that stops firing does not error: it goes silent. That is why every run is recorded and a watchdog pings the phone when one has been quiet for too long.

→
AI proposes; a person decides

The agents read data through read-only tools and never see an IP. Any action, such as a block, waits for a person to approve it, and the ones that can run many times a day (the analyst and the advisor) have a daily spending cap.

→
Docker for development, not production

Docker pins the Node version and starts the local databases for testing. In production, containerizing would lose the edge, per-PR previews and automatic rollback.

Known limits

  • The CSP still allows inline styles and scripts; removing that needs hashes or nonces on every page.
  • A single database provider: if Turso goes down, the panel goes with it (public pages hold on with the cache and their fallbacks).
  • The 5-minute probe depends on cron-job.org; the silence watchdog keeps an eye on it, but does not replace it.
  • No dedicated staging environment: Vercel previews play that role against throwaway databases.

All the code lives in a public repository. The decisions here are not theory: each one has its commit, its tests and, where it applies, its security finding documented on /security.