MolinoPro

human-layer-closure-doc

Master Codebase Guidebook
Markdown + HTML Dev-Docs Renderer - Frontend Client Module

Default Index
Open README.md
Root: README.md_PRD
Milestones
H1Human Layer Closure Doc — Shipped Features

Canonical record of completed features. When a feature is done, it moves here from human-layer-doc.md.


H2🟢 Shipping (Production-Ready)
H3Phase 1: Prisma Schema Updates ✅

Completed: May 2026
Status: 🟢 Shipping (verified on staging, build passes)

  • Added enums: SpaceStatus, SpaceVisibility, SpaceRouteKind, SpaceSectionValidationStatus
  • Added projectionMeta Json? to Trip, Offer, Order
  • Added Stripe fields to Order (stripePaymentIntentId, stripeCustomerId)
  • Added Payment model with relations to Order
  • Added Space models: Space, Section, SpaceRouteAlias
  • Schema validated and pushed to database (npx prisma db push)
  • Zod schemas auto-generated

Verification: Build passes, all routes compile (npm run build successful)


H3Phase 2: Apps Script API Endpoints ✅

Completed: May 2026
Status: 🟢 Shipping (code complete, ready for GAS deployment)

  • Created OfficeServer_GWS-Automation-Framework.gs with doPost() router
  • Implemented handlers: docs.create, docs.exportPdf, calendar.create, drive.share, gmail.send
  • Added legacy compatibility: coreOffice.generateTemplates, coreOffice.generateEntityDocs
  • Auth check via PropertiesService.getScriptProperties().getProperty("AVATAR_SECRET")
  • Response envelope: { ok, action, requestId, timestamp, result, error, meta }

Next: Deploy to Google Apps Script, set AVATAR_SECRET script property, configure APPS_SCRIPT_WEBAPP_URL env var


H3Phase 3: Next.js Projection Actions ✅

Completed: May 2026
Status: 🟢 Shipping (code complete, build passes)

  • Created app/trips/actions/exportTrip.ts (exportTripToDocs, exportTripToPdf)
  • Created app/offers/actions/exportOffer.ts (exportOfferToDocs, exportOfferToPdf)
  • Updated app/api/office-server/route.ts with new action types
  • Added export buttons to TripDetailClient.tsx:
    • "Export to Google Docs" button
    • "Export to PDF (GAS)" button
  • Build successful, all routes compiled

Verification: npm run build passes (exit code 0)


H2🟡 Pending Verification

(None currently — all completed phases verified via build)


H2🔮 Future Stages (Post-Revenue, Not Blocking)
H3External Channel Tracking
  • Etsy Sales Dashboard
  • Shopify Integration
  • Centralized storefront for all products

Note: These depend on reaching 30-50 consistent sales or €500+ revenue validation.



H3Phase 4: Content Stack Factory — Auto-Generated Editable Content for Trips & Experiences ✅

Completed: May 2026
Status: 🟢 Shipping (schema pushed, build passes, factory integrated)

What it does: Every new Trip or Experience automatically spawns a standard editable content structure (SessionStack + ConceptGroups + ConceptCards) that can be rearranged and extended through the existing content layer.

Schema changes:

  • Added contentStackId + contentStack relation to Trip and Experience models
  • Added reverse relations tripContent and experienceContent to SessionStack
  • Enforced unique constraint on contentStackId per Trip/Experience

Factory: lib/factories/contentStackFactory.ts

  • Creates SessionStack (type: GROUP) titled "Content: {trip/experience name}"
  • Creates 3 canonical ConceptGroups: Overview, Logistics, Experience Flow
  • Creates 7 starter ConceptCards with real metadata (promise, boundaries, steps, materials)
  • Links everything via SessionConceptGroup and ConceptGroupItem join tables
  • Auto-attaches to the owner Trip or Experience

Integration points:

  • app/trips/new/actions/tripPlanner.create.actions.ts — calls factory after trip creation
  • app/experiences/actions.ts — calls factory after saveExperienceDraft
  • app/experiences/actions/projectExperiences.ts — calls factory in createExperience
  • app/api/projects/[projectId]/experiences/route.ts — calls factory on POST

UI surfaces:

  • Trip detail page (app/trips/[tripId]/page.tsx + TripDetailClient.tsx) — shows content stack groups/cards with "Edit content" → /session-stacks/{id} and "Manage groups" → /concept-groups
  • Experience detail page (app/experiences/[experienceId]/page.tsx) — same content stack display

Verification: npm run build passes, npx prisma db push succeeded


H3Phase 5: Commercial Content Rewrite — Experiences & Trips Surface ✅

Completed: May 2026
Status: 🟢 Shipping (live on staging, build passes)

Experiences page (app/experiences/page.tsx):

  • Complete rewrite with traveler-facing commercial copy from alandalus-experience.com reference
  • Hero: "Experience Al-Andalus" with value proposition
  • Pathways: Guided Tours, Custom Routes, Gift Cards, Local Sessions
  • Featured experiences: Mezquita, Alhambra, Medina Azahara
  • How it works: 4-step visual journey
  • Cities: Córdoba, Granada, Madrid, Seville, Málaga
  • Trips bridge + Collaborate CTA
  • Footer bridge back to /studio

Trips registry (app/trips/registry/TripsSectionRegistry.ts):

  • Default commercial content updated for all section types
  • Removed system-mechanics language in favor of traveler invitations

Session detail pages (app/(home)/studio/travel/[id]/page.tsx):

  • Body content, highlights, related public experience with booking link
  • Deliverables placeholder, FareHarbor booking card
  • Navigation back to session list

Schema fix:

  • Removed latitude/longitude from TripCity model (belong on City)
  • Updated hotel-actions.ts to query coordinates through city relation

H3Phase 6: Trip → Offer → Order Pipeline ✅

Completed: May 2026
Status: 🟢 Shipping (code complete, build passes)

Core loop locked:

  • createOfferFromTrip() in trip-offer.actions.ts — creates offer from trip with line items
  • checkoutOffer() in app/orders/actions/checkoutOffer.ts — converts Offer → Order (manual payment)
  • Server component fetches associatedOffer and passes offerId to client
  • Manual payment modes: bank transfer / PayPal / cash

Status: Flow implemented end-to-end; ready for browser verification with real project data.


H3Phase 7: FareHarbor Booking Sync — Two-Hook Operational Architecture ✅

Completed: May 2026
Status: 🟢 Shipping (schema pushed, build passes, all routes compile)

What it does: Closes the loop between FareHarbor Lightframe bookings and Molino's internal state. Two distinct concerns: initiation (open modal) and confirmation (poll for webhook result).

Schema:

  • ExternalBooking model — tracks external bookings from any source (FH, Etsy, Stripe)
  • Fields: source, externalId, status, customerEmail, itemId, itemName, flowId, total, currency, bookingDate, rawPayload
  • Unique by (source, externalId) and indexed by (customerEmail, createdAt), status

Client hooks:

  • hooks/useBookingModal.ts — Opens FH Lightframe modal via autolightframe script. Only handles initiation; does NOT trust booking completed.
  • hooks/useBookingSync.ts — Polls GET /api/bookings/pending every 3s for up to 2 min. Returns confirmed booking or timeout.

Server routes:

  • POST /api/webhooks/fareharbor — Receives FH webhooks, upserts ExternalBooking, forwards to GAS (fire-and-forget). Returns 200 so FH doesn't retry.
  • GET /api/bookings/pending — Poll endpoint. Queries ExternalBooking by email + createdAt window + confirmed status.

UI integration:

  • FareHarborBookingCard.tsx — Enhanced with optional sync state. If customerEmail prop provided:
    • Shows spinner: "Checking for booking confirmation…"
    • Shows success: "✅ Booking confirmed!" with item name, total, date
    • Shows error on polling failure

Verification: npm run build passes, npx prisma db push succeeded, new routes /api/webhooks/fareharbor and /api/bookings/pending compiled


H3Phase 8: FareHarbor ICS Calendar API ✅

Completed: May 2026
Status: 🟢 Shipping (route built, no token committed, build passes)

What it does: Fetches the FareHarbor private ICS feed server-side and returns normalized JSON calendar events for future availability/status displays.

Route:

  • GET /api/fareharbor/calendar
  • Optional filters: ?start=<iso-date>&end=<iso-date>
  • Returns: source, fetchedAt, count, and parsed events

Security:

  • Requires FAREHARBOR_ICS_TOKEN in environment
  • The token is not hardcoded in source

Parser fixes:

  • Handles folded ICS lines
  • Parses UID, SUMMARY, DTSTART, DTEND, DESCRIPTION, LOCATION, STATUS
  • Converts UTC, local datetime, and all-day ICS dates to usable strings

Verification: npm run build passes and route /api/fareharbor/calendar compiles


H3Phase 9: FareHarbor Product Catalogue Sheet Import ✅

Completed: May 2026
Status: 🟢 Shipping (Apps Script helper + Next import route built, build passes)

What it does: Uses the Google Sheet as the human sanity surface for all FareHarbor products, then posts normalized catalogue rows into the Next app.

Apps Script:

  • FareHarborCatalog_readHorizontal(sheetName) — reads the wide/horizontal product catalogue
  • FareHarborCatalog_writeNormalized(sheetName, outputSheetName) — creates one row per product in ⚜️ FH_ProductCatalog_Normalized
  • FareHarborCatalog_refresh() — console shortcut for normalization
  • FareHarborCatalog_postToNext(sheetName, nextEndpoint) — posts normalized products to Next

Next route:

  • POST /api/fareharbor/catalog/import
  • Accepts { products, sourceSheet, secret, createContentStacks }
  • Upserts rows into Experience by slug/productKey
  • Stores the full spreadsheet row as JSON in Experience.content
  • Creates/attaches a content stack when missing

Verification: npm run build passes and route /api/fareharbor/catalog/import compiles


H3Phase 10: GAS↔Next.js Contract Alignment — Office Server 🟡

Completed: May 2026
Status: 🟡 Pending Verification (code complete, needs prisma generate + migration)

What it does: Aligns all Next.js routes (webhooks, catalog import, office-server bridge) with the GAS↔Next.js contract reference for FareHarbor integration.

Prisma schema changes:

  • Added customerPhone, affiliateCode, customFields, customTripRef to ExternalBooking
  • Added relation ExternalBooking.customTrip → CustomTripRequest
  • New model CustomTripRequest — customer trip requests with status workflow
  • New model FareHarborProduct — raw catalog entity storage
  • New model AffiliateCommission — affiliate tracking

Route updates:

  • POST /api/webhooks/fareharbor — x-sync-secret auth (APP_SYNC_SECRET), handles booking.created|cancelled|modified with contract field mapping (affiliate_code, custom_fields, custom_trip_ref, phone)
  • POST /api/fareharbor/catalog/import — x-sync-secret auth (CATALOG_IMPORT_SECRET), upserts both FareHarborProduct and Experience
  • POST /api/office-server — accepts Group C action dispatch: fareharbor.customTrip.create, fareharbor.link.generate, fareharbor.availability.get, fareharbor.manager.action with standard response envelope { ok, action, requestId, timestamp, result, meta }. Legacy bundle handlers preserved.

New file:

  • lib/fareharbor-gas-client.ts — Typed client with 4 exported functions:
    • createCustomTrip(input)GasResponse<{ request_id }>
    • generateBookingLink(input)GasResponse<{ lightframe_url }>
    • getAvailability(input)GasResponse<{ count, availabilities }>
    • managerAction(input)GasResponse

Verification: Code reviewed, all imports resolve (uuid, @prisma/client available). Needs prisma generate + prisma migrate dev + endpoint testing.


H2🟡 Pending Verification
H3CityBlockAssignedContent — Concept Group Card Grid & Session Stack Children

Completed: May 2026
Status: 🟡 Pending Verification (code done, needs browser test)

  • Restored CardGrid + QR hover card style for concept groups in "Concept groups" section
  • Added new "From sessions" section rendering session stack children concept groups as cards
  • Updated page.tsx to fetch sessionConceptGroups with linked session stacks, compute contentStackChildren per city from all assigned session stacks
  • Removed old duplicate inline rendering of contentStack.sessionConceptGroups from TripItineraryCanvas.tsx
  • Added contentStackChildren to TripCityBlockViewModel and TripDetail city types
  • No new type errors, all pre-existing errors unchanged

Files changed:

  • app/trips/[tripId]/CityBlockAssignedContent.tsx
  • app/trips/[tripId]/page.tsx
  • app/trips/[tripId]/TripDetailClient.tsx
  • app/trips/builder/components/TripItineraryCanvas.tsx
  • app/trips/builder/lib/trip-builder.types.ts
  • dev-docs/human-layer-doc.md

Verification: Build compiles, no new TS errors. Needs browser test on a city block with both projectionMeta concept groups and session-stack-linked concept groups.


H2🔮 Future Stages (Post-Revenue, Not Blocking)
H3External Channel Tracking
  • Etsy Sales Dashboard
  • Shopify Integration
  • Centralized storefront for all products

Note: These depend on reaching 30-50 consistent sales or €500+ revenue validation.


H2Archive (Older Completed Features)

(Previous shipped features moved here for reference)