H1<MODULE / FEATURE NAME> PRD - Molino App
version: 2026.x
status: draft | active | locked | deprecated
owner: <name>
scope: <route/module/system>
last_updated: <YYYY-MM-DD>
H10. Implementation Snapshot
H2Current goal
H3`<single concrete outcome this module should achieve next>`
H2Remaining features
H3`<feature still needed>`
H3`<feature still needed>`
H3`<feature still needed>`
H2Next build steps
H3inspect `<main route/folder/action files>` before editing
H3confirm `<data authority / model / action boundary>`
H3implement `<smallest useful slice>`
H3verify `<route / action / projection / acceptance check>`
Prompt starter summary:
- Add a short prose version of the Prompt starter here so the module intent is visible at a glance before the code block.
Prompt starter:
Implement the next <Feature> PRD slice. Use PRD/<module>/README.md as source of truth. The current goal is <goal>. Preserve these boundaries: page.tsx reads and orchestrates only, actions/ owns mutations, components render typed UI and user intent, api/route.ts is for external systems only, Prisma remains canonical data truth, and projection outputs are derived artifacts. Inspect <files/folders> before editing. Implement <specific slice>, keep <critical acceptance criteria>, and verify <route/action/output>.
H21. Product Identity
H3Name
<Feature / module name>
H3One-line Definition
<One clear sentence defining what this feature does.>
H3User-facing Purpose
This feature exists so users can:
<primary user goal><secondary user goal><conversion or commercial goal><support or operational goal>
H3Internal Platform Purpose
Inside Molino App, this feature exists to:
- preserve canonical data authority
- expose a controlled UI surface
- connect to external projection or booking systems
- avoid duplicated client-side business logic
- keep Offer -> Order -> Projection paths stable
H22. Strategic Context
H3Why This Exists Now
<Current problem, business need, or next milestone.>
H3What This Replaces
This reduces or replaces:
<manual workflow><temporary page><duplicated component><external-only process><spreadsheet/manual step>
H3What This Does Not Replace
This does not replace:
- Prisma as source of truth
- server actions as mutation authority
- Google Workspace projection layer
- external booking providers where applicable
- manual human support where business logic still requires it
H23. Scope
H3In Scope
This PRD covers:
- route:
<route> - module folder:
app/(pages)/<entity>/ - components:
<components> - server actions:
<actions> - types:
<types> - external integrations:
<systems> - database models:
<models> - projection/export behavior:
<outputs> - admin workflow:
<workflow> - public UI behavior:
<behavior>
H3Out of Scope
This PRD does not cover:
<future feature><external system redesign><unrelated module><full automation not yet needed><payment provider replacement><native API integration if current milestone only uses widgets/buttons>
H3Future Scope
Possible later extensions:
<API replacement><dashboard><analytics><automation><multi-language support><admin sync interface>
H24. Users
H3Public Users
Primary public users:
- travellers
- trip planners
- guests joining shared departures
- customers browsing city experiences
- partner referrals
H3Internal Users
Primary internal users:
- admin/operator
- guide/coordinator
- sales/support
- content editor
- trip planner
H25. Authority Model
H3Molino Contract
page.tsx = read-only server orchestrator
actions/ = sole mutation authority
components/ = dumb UI / client intent only
api/route.ts = external integration surface only
context/ = ephemeral client UI state only
types/ = shared domain truth
Prisma = database truth
Apps Script = external Google execution only
H3Non-negotiable Rules
- No Prisma outside
actions/. - No mutations inside
page.tsx. - No internal app workflow should call its own API route.
- API routes are for outsiders, webhooks, CRON, callbacks, and external systems.
- Client components call server actions only.
- Derived views rebuild from canonical truth.
- LineItems are economic truth once generated.
- Projections must not recompute commercial totals independently.
H26. Module Location
H3Target Folder
app/
(pages)/
<entity>/
page.tsx
actions/
components/
context/
types/
api/
route.ts
H3Related Modules
This feature touches or depends on:
<module>
H27. Core Flows
H3Public Flow
User lands on route -> reads section or card -> selects product/session/trip -> clicks CTA -> booking or projection action starts -> external or internal reference is stored -> follow-up path begins.
H3Internal Flow
Admin creates or updates canonical entity -> pricing or line items are generated or reviewed -> public projection renders -> external bridge is attached if needed -> offer, order, or projection can be generated.
H3Error Flow
User attempts action -> missing config, invalid data, or external failure -> UI shows controlled fallback -> system logs issue -> canonical state remains safe.
H28. Functional Requirements
H3Read Requirements
The feature must display:
<field><field><computed value><status><CTA>
H3Mutation Requirements
The feature must allow:
<create action><update action><archive or delete action><sync action><projection action>
All mutations must happen through:
app/(pages)/<entity>/actions/
H3External Integration Requirements
| System | Purpose | Direction | Authority |
|---|---|---|---|
| FareHarbor | Booking modal | outbound/user action | external booking |
| Google Docs | Offer document | outbound projection | generated artifact |
| Google Calendar | Trip calendar | outbound projection | generated artifact |
| Gmail | Sending offer/invite | outbound execution | delivery only |
H29. Data Model
H3Existing Models Used
<ModelName>
H3New Model Required?
Yes | No
H3External References
Store external IDs when needed:
model ExternalRef {
id String @id @default(cuid())
entityType String
entityId String
provider String
externalId String
externalUrl String?
metadata Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
H210. Type Contract
H3Location
app/(pages)/<entity>/types/<entity>.types.ts
H3Example
export type ModuleStatus = "draft" | "active" | "archived" | "published";
H211. Server Actions
H3Required Actions
get<Entity>.ts
create<Entity>.ts
update<Entity>.ts
archive<Entity>.ts
sync<Entity>.ts
project<Entity>.ts
H3Action Rules
- validate input
- access Prisma only inside the action
- avoid UI assumptions
- return a typed result
- revalidate relevant path or tag after mutation
- avoid calling internal API routes
H212. Page Contract
page.tsx must:
- fetch read data
- orchestrate layout
- pass typed props to components
- use Suspense where useful
- never mutate
- never contain Prisma mutation logic
- never contain client-only interaction logic
H213. Component Contract
Components must:
- receive typed props
- render UI
- call server actions only for user intent
- never import Prisma
- never own canonical truth
- never duplicate business rules
- avoid hidden side effects
H214. API Route Contract
Use api/route.ts only for:
- webhooks
- external booking systems
- Apps Script callbacks
- external CRON jobs
- third-party integrations
- machine-to-machine calls
Do not use it for internal component to app communication.
H215. UI / UX Requirements
The UI should:
- look native to Molino App
- preserve mobile usability
- avoid full-page redirects when modal action is possible
- provide fallback links for external booking failures
H216. Business Rules
Define:
- pricing source
- line item behavior
- deposit behavior
- cancellation assumptions
- booking availability
- manual support requirements
- offer expiry
- order confirmation rules
H217. Projection Rules
Canonical entity -> compute view model -> build render payload -> call projection action -> external executor runs -> external ref persisted -> path or tag revalidated
H218. Validation
Every mutation must validate:
- required IDs
- permissions, if applicable
- enum values
- pricing fields
- external provider config
- serializable JSON payloads
H219. Revalidation
After mutation, revalidate only relevant paths.
H220. Permissions / Access
- Public access
- Admin access
H221. Analytics / Tracking
Possible events:
card_viewedcta_clickedbooking_modal_openedenquiry_startedoffer_generatedpdf_generatedorder_created
H222. Testing Plan
- Unit tests
- Integration tests
- UI tests
- Manual QA checklist
H223. Acceptance Criteria
This feature is complete when:
- route renders correctly
- all data comes from canonical source
- server actions own mutations
- components are dumb and typed
- external integrations are isolated
- Prisma is not imported outside actions
- revalidation happens after mutation
- public UI has loading, empty, success, and failure states
- projection outputs preserve canonical data
H224. Implementation Checklist
- define type contract
- confirm Prisma model or existing data source
- create read action
- create page orchestrator
- create dumb UI components
- create mutation actions
- add revalidation
- add external bridge if needed
- add projection logic if needed
- test route manually
- remove temporary duplication
- lock PRD status
H225. Risks / Open Questions
- external widget changes behavior
- pricing duplicated downstream
- client owns too much logic
- projection mismatch
- missing external refs
H226. Locked Summary
When locked, this PRD defines a self-contained Molino module that reads canonical data, renders a native UI surface, sends user intent through server actions, isolates external integrations, stores external references, and preserves the app-wide authority model.