Skip to content

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.

  1. GET /api/instance resolves the default API or a verified custom instance and returns browser-safe information such as the correct public Turnstile site key.
  2. GET /api/session checks the HttpOnly pinchana_web_session cookie by calling API GET /web/session.
  3. If no valid session exists, Web renders Turnstile with action turnstile-spin-v1.
  4. The one-use token is posted to /api/verify. The BFF forwards it to API POST /web/verify.
  5. API calls Cloudflare Siteverify with its private Turnstile secret and, on success, returns a signed browser-session token.
  6. Web stores that token in pinchana_web_session with HttpOnly, SameSite=Strict, path /, and Secure in production.

Browser JavaScript receives session status/expiry metadata, not the bearer token itself.

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.

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.

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 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.