Prego Web App Standard (Draft v1.0)
This document is the canonical standard for PREGO web applications in the monorepo (apps/www, apps/admin-web, apps/client-web). It is designed for operational stability on Cloudflare, reuse across SaaS surfaces, and predictable behavior for IDE-assisted development.
Related (read together):
| Topic | Document |
|---|---|
| Public API change order | How to add an API |
| Browser → Zuplo vs thin BFF | API gateway & BFF governance — not “Zuplo only” dogma; short exception list |
| Headers, trust zones | Tenant & trust boundaries |
| Repo ownership | Repo responsibility matrix |
| Refactoring program context | Web app standardization plan |
| Safe refactor audit (behavior-preserving) | Web app safe refactor status |
| Cursor copy-paste prompts | Web app refactoring prompt (Cursor) |
| IDE / agents | IDE guide |
1. Objective
This standard applies to all PREGO web apps (www, admin-web, client-web) to achieve:
- Consistent development practices across the product web tier
- Cloudflare-aligned deployment and runtime expectations
- AI IDE (Cursor, etc.) — clear boundaries and shared contracts
- Reusable SaaS platform — shared packages and schema-first contracts
2. Architecture principles
2.1 Layer model
[ User Interface Layer ] → Next.js (www / admin-web / client-web)
[ Edge API Layer ] → Cloudflare Workers (Hono where used for HTTP services)
[ Gateway Layer ] → Zuplo (auth policies, rate limits, header transforms, routing)
[ Data & platform state ] → D1 / R2 / KV / Vectorize (per Worker bindings and product)
[ Domain backend ] → Frappe (ERP)
[ Observability ] → Logpush / Analytics / R2 (as configured per environment)Boundary note: ERP business rules live in Frappe; Retrieval/runtime in prego_ai; orchestration and tenant master data in prego-control-plane. Workers implement edge/API and orchestration — not a duplicate of Frappe domain logic. See the repo responsibility matrix.
2.2 Design principles
- Edge-first — Prefer gateway + Workers for multi-tenant and cross-app APIs.
- Stateless UI — Sessions and secrets follow existing app patterns; no hidden server state in UI packages.
- Schema-first contracts — Zod (and shared types) for inputs/outputs that cross app boundaries.
- Gateway-first public API — Default: browser and external consumers use Zuplo as the public API surface; exceptions (thin BFF, presigned upload, Pages Functions) are documented and minimal. See API gateway & BFF governance.
- Workers own edge/service HTTP behavior — Do not implement Worker-equivalent business APIs inside Next routes; Next orchestrates UI and same-origin needs only.
- Shared package–first — Prefer
packages/*over duplicated components, schemas, or clients.
2.3 Scope — in / out (web tier)
This standard applies to the three Next.js product applications in the monorepo: apps/www, apps/admin-web, apps/client-web.
Out of scope (not governed by this document; use their own repos, runbooks, or doc hubs):
- Documentation sites built with Starlight, VitePress, Docusaurus, or similar static doc frameworks — including the monorepo internal docs tree under
docs/(Starlight) and separate product-documentation repositories (e.g. public docs mirrors). Their stack, routing, and content pipelines are not “web app standard” targets. - Other external documentation or CMS surfaces that are not one of the three Next apps.
- Backend / infra / gateway authoring (Frappe, Pulumi, Ansible, prego-zuplo OpenAPI, Workers-only repos) — see the platform hub and repo responsibility matrix.
Rationale: Mixing Starlight (or any doc framework) with product Next apps in one standard creates false obligations (forms, Zuplo, Cloudflare Pages app patterns). Keep product web tier rules separate from documentation tooling.
3. Web app standard (www / admin / client)
3.1 Common technical stack
| Area | Standard |
|---|---|
| Framework | Next.js — one agreed major across the three apps (upgrade path in standardization plan) |
| Language | TypeScript (strict) |
| UI | Tailwind + shadcn/ui (shared tokens/patterns via packages where applicable) |
| Forms | React Hook Form |
| Validation | Zod — required for user input and shared contracts |
| Server/async data | TanStack Query where the app already uses it; align patterns across apps over time |
| Runtime / deploy | Cloudflare — see §7 (www may remain static export + Pages; admin/client target OpenNext on Workers alignment) |
3.2 Prohibited (web tier)
- Per-app ad hoc validation — no parallel validation stacks for the same flows; use Zod (+ RHF resolvers).
- Bypassing the gateway for public multi-consumer APIs — do not call Worker origins directly from the browser when the contract is meant to go through Zuplo (see BFF exceptions).
- Embedding Worker-grade orchestration or domain logic in Next — keep edge/service logic in Workers (and Frappe for ERP).
- Duplicating UI — extract to
packages/ui(or existing shared packages) instead of copy-paste.
3.3 App roles
| App | Role | Deploy posture (target) |
|---|---|---|
| www | Marketing — SEO, landing, pricing; static-first | Cloudflare Pages (static export) |
| admin-web | Highest-contract surface — onboarding, auth handoff, billing, tenant/plan/region, provisioning entry | OpenNext + Worker |
| client-web | Primary SaaS UI — ERP + assistant features | Cloudflare; align toward same Next-on-Workers strategy as admin-web (see plan) |
3.4 Implementation status (monorepo snapshot)
This is a living snapshot of where the standard is applied in the Prego monorepo — not a completeness claim. Details: Web app safe refactor status.
| Surface | RHF + Zod (email OTP entry) | Notes |
|---|---|---|
@platform/web-auth-schemas — authEmailSchema, authEmailStringSchema, AUTH_EMAIL_RE, signInSchema / signUpSchema (password Hono JSON) | Yes | Shared workspace package: admin-web (/signup, AuthCard, onboarding / step 2), www (TrialEmailGate, manual approval workEmail in manual-approval-verify-schema.ts), client-web auth flows + lib/schemas/onboarding + invoices/create + lib/schemas/auth (re-exports Hono sign-in/up JSON). |
admin-web — OTP verify (EmailOtpVerifyPanel) | Aligned | RHF + zodResolver on z.object({ code: otpCodeSchema }); six inputs sync to code via setValue; verifyOtp / resend errors use setError('root'). |
admin-web — CompanyInfoStep (onboarding step 4) | Aligned | RHF + zodResolver + useFieldArray; Zod (lib/schemas/company-info-step.ts): subdomain via validateSubdomain, company length, invite emails via authEmailStringSchema. |
| client-web | Aligned (auth / email + selected ERP) | package.json has Zod + RHF. SignUpPage, forgot-passcode, SignInForm, verify-email (email in useForm), invoices/create (recipientEmail) use RHF + shared Zod; verify-email CodeEntryForm submits the six-digit code via parsePasscodePinFromInput before POST /auth/otp/verify. Passcode keypad routes (passcode/set, passcode/change, reset-passcode, dedicated /passcode, SignInForm verify step → /auth/verify) use parsePasscodePin and PASSCODE_PIN_LENGTH (lib/schemas/passcode-pin, same six digits as OTP) before gateway calls — not RHF. ERP-style flows use lib/schemas/* (e.g. checklist add, leave request, expense capture validation) with RHF where applicable; expand per-screen. pnpm run verify includes Vitest test:unit (e.g. Assistant UI app/my-ai/page-controller/*.test.ts, lib/schemas/*.test.ts); see apps/client-web/AGENTS.md. Assistant UI @/app/my-ai/page-controller barrel: ESLint no-restricted-imports in eslint.config.mjs (only app/my-ai/page.tsx + app/my-ai/page-controller/**). |
4. API & edge standard
4.1 Request flow (default)
Client (Next) → Zuplo (gateway) → Worker (e.g. Hono in prego_ai / patterns in control-plane) → D1 / R2 / KV / Vectorize (as bound)BFF exception path (allowed when narrow): same-origin Next app/api/*, Pages Functions, or presigned flows — per API gateway & BFF governance.
4.2 Worker standard (HTTP services using Hono)
| Item | Rule |
|---|---|
| Framework | Hono for new HTTP routing in Workers where the repo already standardizes on it |
| Validation | Zod at boundaries |
| Response | JSON, typed |
| Logging | Include request correlation (and tenant/user fields where applicable) |
| Errors | Structured errors — consistent shape for clients |
Existing Workers without Hono may migrate incrementally; new routes should follow repo conventions.
4.3 Zuplo responsibilities
- Authentication and policy enforcement at the edge
- Rate limiting
- Header transforms (e.g. tenant context) per Tenant & trust boundaries
- Usage / routing metadata as configured
No business rules in the gateway — policy and forwarding only.
5. Data layer (Cloudflare)
5.1 Storage roles (illustrative)
| Service | Typical use |
|---|---|
| D1 | Relational metadata (e.g. control-plane) |
| R2 | Files, exports, log sinks |
| KV | Cache, rate-limit windows, small lookups |
| Vectorize | Embeddings / retrieval (prego_ai) |
| Logpush | Centralized logs (operator setup) |
5.2 Multi-tenancy
tenant_idisolation is mandatory for tenant-scoped data paths.- R2 (example layout):
tenants/{tenant_id}/files/{file_id} - Vectorize metadata: include
tenant_id(andproject_id,doc_idas required by the product) — see AI Worker docs and tenant trust.
6. Shared packages (required direction)
Monorepo layout (names may match existing packages/*):
packages/ ui/ # shared components forms/ # shared form primitives + RHF helpers contracts/ # Zod schemas + inferred types (source of truth for cross-app contracts) api-client/ # typed clients for Zuplo-facing calls config/ # shared env-safe config helpers6.1 contracts (core)
- Zod schemas for requests/responses shared by www / admin / client where applicable
- Single place for breaking-change discipline and tests
7. Deployment & CI
- CI: GitHub Actions
- Cloudflare: Wrangler; multi-env (dev / staging / prod)
- Strategy:
| App | Strategy |
|---|---|
| www | Pages — static export (next build --webpack, Next 16.0.x) |
| admin-web | OpenNext + Worker (Next 16.0.x, next.config.mjs) |
| client-web | next-on-pages today; Unify on OpenNext-aligned Cloudflare strategy (recommended; phased — ADR) |
- Next
tsconfighygiene:@platform/next-dev-scriptsexposesprego-strip-next-dev-types-from-tsconfigsotsc --noEmitdoes not follow stale.next/dev/typesentries Next may inject intoinclude. Rootpnpm run verify:next-dev-scripts; CI.github/workflows/next-dev-scripts.yml. See Web app standardization plan §4. - Monorepo integration verify (shared packages + internal Starlight
docs— does not build www / admin-web / client-web production bundles): rootpnpm run build:verify. Starlightdocs/= MDX —docs/README.md· Dependency inspection §7. Ifdocsastro buildfails with missing chunks underdocs/dist(e.g.renderers.mjs), runpnpm run build:docs:cleanfrom the repo root —AGENTS.md. IDE guide · Dependency inspection §8.
8. Repository layout (monorepo vs satellites)
Prego monorepo:
apps/ www/ admin-web/ client-web/packages/ ...Other repositories (prego_ai, prego-control-plane, prego-zuplo) own Workers, gateway, and Frappe is separate — the mental model is still: UI in Prego apps, contracts in shared packages, public APIs via OpenAPI + Zuplo.
Forbidden:
- Performing Worker responsibilities inside an app without going through the agreed gateway/BFF rules
- Duplicate OpenAPI definitions — prego-zuplo remains the merged public contract source
- Undocumented HTTP handlers without schema at the boundary
9. Observability (target shape)
9.1 Log fields (illustrative)
{ "request_id": "...", "tenant_id": "...", "user_id": "...", "endpoint": "...", "latency_ms": 0, "error": null}9.2 Storage
- Logpush → R2 (where enabled)
- Operator/debug UIs — out of band unless explicitly productized
10. Security & auth
- JWT and session patterns follow each app’s existing implementation.
- Zuplo performs edge policy; Workers perform service-level verification consistent with Tenant & trust boundaries.
- URL tenant scope and token claims must agree — no cross-tenant dispatch from mismatched path vs JWT.
11. Documentation rules
- Platform docs:
docs/src/content/docs/(this site). - On change: API contract → update OpenAPI in prego-zuplo first; schema/package changes → update this section or linked runbooks; architecture shifts → update diagrams (Mermaid below).
12. Mermaid diagrams (standard)
API flow
sequenceDiagram participant UI as Next UI participant Z as Zuplo participant W as Worker participant D as D1/R2/KV UI->>Z: HTTPS (public contract) Z->>W: Forward (trusted headers) W->>D: Query / write D-->>W: Result W-->>Z: JSON Z-->>UI: Response
Data flow
flowchart LR UI[Next apps] --> Z[Zuplo] Z --> W[Workers] W --> D1[(D1)] W --> R2[(R2)] W --> KV[(KV)] W --> V[(Vectorize)]
13. Refactoring rules
When touching the web tier:
- Remove duplication; move to shared packages
- Delete dead code
- Move legacy / demo / non-canonical assets to
archive/(or equivalent) and label in README - Align on contracts package for shared types
- Update OpenAPI and platform docs in the same change set when behavior is user-visible
14. IDE optimization
- Every cross-app or external API shape should have a Zod schema (in
contractsor next to the gateway consumer). - Modules — one clear responsibility per folder; no “grab bag” utils.
- Comments — prefer JSDoc on public exports and non-obvious invariants; avoid redundant noise.
15. Five-point summary
- Next — UI and orchestration (not Worker domain logic).
- Workers — edge HTTP and service logic (Hono where standard).
- Zuplo — gateway policy and public routing (BFF exceptions are narrow and documented).
- Zod — center of schema-first contracts for the web tier.
- Shared packages — default for UI, forms, and contracts.
16. Versioning
| Version | Status |
|---|---|
| Draft v1.0 | Initial adopted standard; refine with implementation feedback |
Next review: when Next major, OpenNext, or client-web deployment strategy milestones complete — see Web app standardization plan.
한국어 요약
Prego Web App Standard (Draft v1.0) 은 www / admin-web / client-web 의 공통 규칙입니다. 공개 API는 기본 Zuplo 를 통하고, 쿠키·비밀·동일 출처 등은 API gateway & BFF governance 의 얇은 BFF 예외를 따릅니다. 폼·입력은 RHF + Zod, 공유 계약은 packages/contracts 방향으로 모읍니다. admin-web 은 온보딩·결제·테넌트 등 계약 밀도가 가장 높은 앱으로 다룹니다. 배포는 www = Pages 정적, admin = OpenNext+Worker, client = OpenNext 계열로 수렴을 권장합니다. Next 가 tsconfig include 에 넣는 .next/dev/types 는 @platform/next-dev-scripts (prego-strip-next-dev-types-from-tsconfig)로 정리 — 루트 pnpm run verify:next-dev-scripts, §7·표준화 계획 §4. 모노레포 통합 검증(pnpm run build:verify, 내부 Starlight docs 포함; 세 Next 앱 프로덕션 번들은 아님) — 내부 docs/ 는 MDX — docs/README.md · Dependency inspection §7. astro build chunk 오류 시(예: renderers.mjs) 루트 pnpm run build:docs:clean — AGENTS.md · IDE 가이드 · Dependency inspection §8. 이메일·OTP 스키마는 @platform/web-auth-schemas (authEmailSchema, authEmailStringSchema, otpCodeSchema) — www / admin-web / client-web 에 적용됨(§3.4, safe refactor status). 상세 실행·우선순위는 Web app standardization plan 과 함께 보세요.