Web architecture and authentication
Pinchana Web is a Next.js 16 server-backed application. Its route handlers form a backend-for-frontend (BFF): browser JavaScript talks only to the Web origin while the server-side routes communicate with the selected Pinchana API instance.
Browser Pinchana Web BFF Pinchana API │ GET /api/instance ────────────────┼────────────────────────────→ instance configuration / identity │ GET /api/session ─────────────────┼─ bearer from HttpOnly ─────→ GET /web/session │ POST /api/verify + Turnstile ─────┼────────────────────────────→ POST /web/verify │ ├─ Set-Cookie: web session │ POST /api/scrape ─────────────────┼─ bearer + JSON ────────────→ POST /v1/web/scrape │ GET /api/media/... ────────────────┼─ bearer + Range ───────────→ GET /web/media/... │ GET /api/capabilities ────────────┼─ bearer ───────────────────→ GET /web/capabilities └─ /api/dlp/jobs/... ───────────────┼─ bearer + job data ────────→ /web/dlp/jobs/...The current Web client requires the normalized POST /v1/web/scrape API route. Older API instances that only expose legacy /web/scrape are not supported by current Web.
Session gate
Section titled “Session gate”GET /api/instanceresolves the default API or a verified custom instance and returns browser-safe information such as the correct public Turnstile site key.GET /api/sessionchecks the HttpOnlypinchana_web_sessioncookie by calling APIGET /web/session.- If no valid session exists, Web renders Turnstile with action
turnstile-spin-v1. - The one-use token is posted to
/api/verify. The BFF forwards it to APIPOST /web/verify. - API calls Cloudflare Siteverify with its private Turnstile secret and, on success, returns a signed browser-session token.
- Web stores that token in
pinchana_web_sessionwithHttpOnly,SameSite=Strict, path/, andSecurein production.
Browser JavaScript receives session status/expiry metadata, not the bearer token itself.
Server-only configuration
Section titled “Server-only configuration”PINCHANA_API_URL is server-only. Do not turn it into a NEXT_PUBLIC_... value. The same rule applies to PINCHANA_INSTANCE_PUBLIC_KEY, API machine keys, Turnstile secrets, DLP secrets, and signed browser-session values.
NEXT_PUBLIC_TURNSTILE_SITE_KEY is intentionally public because Cloudflare requires the browser to render the widget with a site key.
Same-origin scrape and media proxy
Section titled “Same-origin scrape and media proxy”POST /api/scrape validates the submitted URL, forwards the request to /v1/web/scrape, and rewrites protected /web/media/... paths in the normalized response to /api/media/....
The media route validates path segments, forwards byte-range headers, streams the upstream body, and prevents public caching. This is why authenticated media can be used directly by <img>, <video>, and <audio> without exposing the API session to browser code.
Build and capability metadata
Section titled “Build and capability metadata”GET /api/build proxies the API’s sanitized public build manifest for the About screen. It exposes product/module revisions, not deployment secrets.
GET /api/capabilities feature-detects optional API capabilities. DLP controls are enabled only when the selected API reports protocol v2 as available.
Custom instances
Section titled “Custom instances”Custom origins are stored as project-signed certificate state, not arbitrary local-storage URLs. The BFF verifies the Ed25519 certificate using server-only PINCHANA_INSTANCE_PUBLIC_KEY, derives the exact API origin from certificate claims, and clears the current web session when the selected instance changes.
See Custom API instances for certificate issuance and renewal.