Vibecode FareHarbor
track this build5 steps, step by step0%The part everyone thinks they are paying for, a calendar with capacity, a checkout, and a manifest the guides can read, is genuinely a weekend build with Stripe doing the hard money parts. The part that is actually load-bearing is everything after that: pushing live availability to Viator, GetYourGuide, Expedia and Booking.com, reconciling reseller commissions, handling refunds and chargebacks on other people's money, and a phone line that answers at 6am when the 7am kayak trip is double-booked. A self-hosted build replaces direct-website bookings cleanly and replaces channel distribution not at all. If most of your volume is direct and you can eat the ops burden, the maths gets interesting fast. If OTAs feed you, you are rebuilding a channel manager, which is not a weekend.
You are building a lean indie version of FareHarbor. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # FareHarbor indie build ## Goal Build the smallest trustworthy replacement for the core FareHarbor workflow for one developer or a tiny team. ## Scope Self-hosted booking site: define tours with dated departures and capacity, take deposits or full payment through Stripe Checkout, and give staff a day-view manifest with check-in and cancellation. ## Quick start 1. Install the documented dependencies. 2. Copy `.env.example` to `.env`. 3. Run the development command chosen during implementation. 4. Complete the acceptance checks in `BUILD_PLAN.md`. ## Honest limits This build deliberately does not replace: - OTA and reseller distribution: live availability pushed to Viator, GetYourGuide, Expedia and dozens of local agents, plus the commission accounting behind it - Someone else owning payment risk: chargebacks, disputes, refund flows, payout timing, PCI scope and multi-currency - 24/7 human support during a season where a broken booking page costs real departures that day - The messy operational features you only miss in August: resource and guide assignment, gear allocation, multi-day and multi-activity itineraries, gift cards, promo codes, waivers, group and private bookings - Mobile check-in that works on a beach with one bar of signal, and the reporting your accountant already knows how to read If those capabilities are essential, use FareHarbor instead of pretending the gap is solved. ===== AGENTS.md ===== # Agent instructions - Optimize for a working, understandable weekend build. - Prefer the fewest moving parts that satisfy the brief. - Do not invent cryptography, security guarantees, APIs, or compliance claims. - Keep secrets out of source control and logs. - Add focused tests for destructive, security-sensitive, and data-loss paths. - Run the project checks before declaring the build complete. - Record any deliberate shortcut in the README under "Tradeoffs". ===== BUILD_PLAN.md ===== # Build plan ## Original build brief Build a self-hosted booking system for a single tour operator. Stack: Next.js 15 with the App Router, TypeScript, Tailwind, Postgres via Prisma, Stripe Checkout. No auth provider, no analytics, no telemetry. Data model: Product (name, slug, description, duration minutes, base price cents, currency, min and max party size, active flag), Departure (product, start datetime, capacity, status: scheduled | cancelled), Booking (departure, lead name, email, phone, party size, amount cents, stripe payment intent id, status: pending | confirmed | cancelled | refunded, notes, waiver accepted at), Passenger (booking, name, age band). Public side: - /tours lists active products, /tours/[slug] shows the next 60 days of departures with seats remaining computed as capacity minus confirmed and pending party sizes. - Booking flow: pick a departure, enter party size and lead contact, tick a waiver checkbox, then redirect to Stripe Checkout. Create the Booking as pending before redirect. Confirm it only in the Stripe webhook handler, never on the return URL. - Overselling is the thing you must get right: take the seat hold inside a serialisable transaction that re-checks remaining capacity, and expire pending bookings older than 20 minutes with a cron route. Operator side at /admin, protected by a single shared password from .env stored in an httpOnly cookie: - Day view manifest: every departure today with lead names, party sizes, phone numbers, waiver status and a check-in toggle. - Create and bulk-generate departures from a weekday recurrence rule with a date range. - Cancel a departure: refunds all confirmed bookings through the Stripe API and emails everyone. - Manual booking entry for phone and walk-up guests, marked as unpaid or cash. - CSV export of bookings for a date range. Email confirmations and cancellations via Resend, plain text, with an .ics attachment. Money in integer cents, one currency, store all times in UTC and render in a single operator timezone from .env. Explicitly out of scope: OTA or reseller channel sync, promo codes, gift cards, multi-day itineraries, guide and equipment assignment, multi-currency, per-user accounts and roles. Secrets in .env: DATABASE_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, RESEND_API_KEY, ADMIN_PASSWORD, OPERATOR_TIMEZONE. Ship a seed script with two products and 30 days of departures, a README with the Stripe CLI webhook command, and a test that proves a departure cannot be oversold under concurrent requests. ## Required capabilities - Stripe account (test mode is fine to build against) - a domain and any Node host, plus a Postgres or SQLite volume - transactional email provider for confirmations - clear rules for your own cancellation, deposit and capacity logic before you start ## Delivery order 1. Scaffold the smallest runnable application and document its commands. 2. Implement the primary data model and core workflow. 3. Add validation, safe failure states, and persistence. 4. Cover the critical path with automated tests. 5. Exercise a clean install from the README and fix every missing step. ## Done when - A new user can go from clone to first successful workflow using only the README. - The core workflow works without paid infrastructure unless the brief requires it. - Tests cover the highest-risk behavior. - Known limitations are explicit rather than hidden. ===== .env.example ===== # Copy to .env and document every variable when it is introduced. # Never put real credentials in this file. APP_ENV=development # Add only values required by the selected implementation.
You are building a lean indie version of FareHarbor. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # FareHarbor indie build ## Goal Build the smallest trustworthy replacement for the core FareHarbor workflow for one developer or a tiny team. ## Scope Self-hosted booking site: define tours with dated departures and capacity, take deposits or full payment through Stripe Checkout, and give staff a day-view manifest with check-in and cancellation. ## Quick start 1. Install the documented dependencies. 2. Copy `.env.example` to `.env`. 3. Run the development command chosen during implementation. 4. Complete the acceptance checks in `BUILD_PLAN.md`. ## Honest limits This build deliberately does not replace: - OTA and reseller distribution: live availability pushed to Viator, GetYourGuide, Expedia and dozens of local agents, plus the commission accounting behind it - Someone else owning payment risk: chargebacks, disputes, refund flows, payout timing, PCI scope and multi-currency - 24/7 human support during a season where a broken booking page costs real departures that day - The messy operational features you only miss in August: resource and guide assignment, gear allocation, multi-day and multi-activity itineraries, gift cards, promo codes, waivers, group and private bookings - Mobile check-in that works on a beach with one bar of signal, and the reporting your accountant already knows how to read If those capabilities are essential, use FareHarbor instead of pretending the gap is solved. ===== AGENTS.md ===== # Agent instructions - Optimize for a working, understandable weekend build. - Prefer the fewest moving parts that satisfy the brief. - Do not invent cryptography, security guarantees, APIs, or compliance claims. - Keep secrets out of source control and logs. - Add focused tests for destructive, security-sensitive, and data-loss paths. - Run the project checks before declaring the build complete. - Record any deliberate shortcut in the README under "Tradeoffs". ===== BUILD_PLAN.md ===== # Build plan ## Original build brief Build a self-hosted booking system for a single tour operator. Stack: Next.js 15 with the App Router, TypeScript, Tailwind, Postgres via Prisma, Stripe Checkout. No auth provider, no analytics, no telemetry. Data model: Product (name, slug, description, duration minutes, base price cents, currency, min and max party size, active flag), Departure (product, start datetime, capacity, status: scheduled | cancelled), Booking (departure, lead name, email, phone, party size, amount cents, stripe payment intent id, status: pending | confirmed | cancelled | refunded, notes, waiver accepted at), Passenger (booking, name, age band). Public side: - /tours lists active products, /tours/[slug] shows the next 60 days of departures with seats remaining computed as capacity minus confirmed and pending party sizes. - Booking flow: pick a departure, enter party size and lead contact, tick a waiver checkbox, then redirect to Stripe Checkout. Create the Booking as pending before redirect. Confirm it only in the Stripe webhook handler, never on the return URL. - Overselling is the thing you must get right: take the seat hold inside a serialisable transaction that re-checks remaining capacity, and expire pending bookings older than 20 minutes with a cron route. Operator side at /admin, protected by a single shared password from .env stored in an httpOnly cookie: - Day view manifest: every departure today with lead names, party sizes, phone numbers, waiver status and a check-in toggle. - Create and bulk-generate departures from a weekday recurrence rule with a date range. - Cancel a departure: refunds all confirmed bookings through the Stripe API and emails everyone. - Manual booking entry for phone and walk-up guests, marked as unpaid or cash. - CSV export of bookings for a date range. Email confirmations and cancellations via Resend, plain text, with an .ics attachment. Money in integer cents, one currency, store all times in UTC and render in a single operator timezone from .env. Explicitly out of scope: OTA or reseller channel sync, promo codes, gift cards, multi-day itineraries, guide and equipment assignment, multi-currency, per-user accounts and roles. Secrets in .env: DATABASE_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, RESEND_API_KEY, ADMIN_PASSWORD, OPERATOR_TIMEZONE. Ship a seed script with two products and 30 days of departures, a README with the Stripe CLI webhook command, and a test that proves a departure cannot be oversold under concurrent requests. ## Required capabilities - Stripe account (test mode is fine to build against) - a domain and any Node host, plus a Postgres or SQLite volume - transactional email provider for confirmations - clear rules for your own cancellation, deposit and capacity logic before you start ## Delivery order 1. Scaffold the smallest runnable application and document its commands. 2. Implement the primary data model and core workflow. 3. Add validation, safe failure states, and persistence. 4. Cover the critical path with automated tests. 5. Exercise a clean install from the README and fix every missing step. ## Done when - A new user can go from clone to first successful workflow using only the README. - The core workflow works without paid infrastructure unless the brief requires it. - Tests cover the highest-risk behavior. - Known limitations are explicit rather than hidden. ===== .env.example ===== # Copy to .env and document every variable when it is introduced. # Never put real credentials in this file. APP_ENV=development # Add only values required by the selected implementation.
You are building a production product version of FareHarbor. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # FareHarbor product brief ## Problem The part everyone thinks they are paying for, a calendar with capacity, a checkout, and a manifest the guides can read, is genuinely a weekend build with Stripe doing the hard money parts. The part that is actually load-bearing is everything after that: pushing live availability to Viator, GetYourGuide, Expedia and Booking.com, reconciling reseller commissions, handling refunds and chargebacks on other people's money, and a phone line that answers at 6am when the 7am kayak trip is double-booked. A self-hosted build replaces direct-website bookings cleanly and replaces channel distribution not at all. If most of your volume is direct and you can eat the ops burden, the maths gets interesting fast. If OTAs feed you, you are rebuilding a channel manager, which is not a weekend. ## Product outcome Self-hosted booking site: define tours with dated departures and capacity, take deposits or full payment through Stripe Checkout, and give staff a day-view manifest with check-in and cancellation. ## Target user A serious builder who needs a maintainable product foundation rather than a one-off demo. ## Required capabilities - Stripe account (test mode is fine to build against) - a domain and any Node host, plus a Postgres or SQLite volume - transactional email provider for confirmations - clear rules for your own cancellation, deposit and capacity logic before you start ## Explicit non-goals for v1 - OTA and reseller distribution: live availability pushed to Viator, GetYourGuide, Expedia and dozens of local agents, plus the commission accounting behind it - Someone else owning payment risk: chargebacks, disputes, refund flows, payout timing, PCI scope and multi-currency - 24/7 human support during a season where a broken booking page costs real departures that day - The messy operational features you only miss in August: resource and guide assignment, gear allocation, multi-day and multi-activity itineraries, gift cards, promo codes, waivers, group and private bookings - Mobile check-in that works on a beach with one bar of signal, and the reporting your accountant already knows how to read ## Success criteria - The primary workflow is measurable end to end. - Setup is reproducible in a clean environment. - Failure, recovery, and support paths are documented. - Product claims match what the implementation actually guarantees. ===== ARCHITECTURE.md ===== # Architecture ## Starting brief Build a self-hosted booking system for a single tour operator. Stack: Next.js 15 with the App Router, TypeScript, Tailwind, Postgres via Prisma, Stripe Checkout. No auth provider, no analytics, no telemetry. Data model: Product (name, slug, description, duration minutes, base price cents, currency, min and max party size, active flag), Departure (product, start datetime, capacity, status: scheduled | cancelled), Booking (departure, lead name, email, phone, party size, amount cents, stripe payment intent id, status: pending | confirmed | cancelled | refunded, notes, waiver accepted at), Passenger (booking, name, age band). Public side: - /tours lists active products, /tours/[slug] shows the next 60 days of departures with seats remaining computed as capacity minus confirmed and pending party sizes. - Booking flow: pick a departure, enter party size and lead contact, tick a waiver checkbox, then redirect to Stripe Checkout. Create the Booking as pending before redirect. Confirm it only in the Stripe webhook handler, never on the return URL. - Overselling is the thing you must get right: take the seat hold inside a serialisable transaction that re-checks remaining capacity, and expire pending bookings older than 20 minutes with a cron route. Operator side at /admin, protected by a single shared password from .env stored in an httpOnly cookie: - Day view manifest: every departure today with lead names, party sizes, phone numbers, waiver status and a check-in toggle. - Create and bulk-generate departures from a weekday recurrence rule with a date range. - Cancel a departure: refunds all confirmed bookings through the Stripe API and emails everyone. - Manual booking entry for phone and walk-up guests, marked as unpaid or cash. - CSV export of bookings for a date range. Email confirmations and cancellations via Resend, plain text, with an .ics attachment. Money in integer cents, one currency, store all times in UTC and render in a single operator timezone from .env. Explicitly out of scope: OTA or reseller channel sync, promo codes, gift cards, multi-day itineraries, guide and equipment assignment, multi-currency, per-user accounts and roles. Secrets in .env: DATABASE_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, RESEND_API_KEY, ADMIN_PASSWORD, OPERATOR_TIMEZONE. Ship a seed script with two products and 30 days of departures, a README with the Stripe CLI webhook command, and a test that proves a departure cannot be oversold under concurrent requests. ## Boundaries Separate the product into replaceable modules for interface, application logic, persistence, external integrations, and operational concerns. Keep domain logic independent from delivery frameworks and vendors. ## Production baseline - Configuration: validated at startup with safe local defaults where possible. - Security: least privilege, input validation, secret redaction, rate limits on abuse-prone paths, and no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore instructions. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, and timeouts. - Observability: structured logs with request or operation IDs, an error-tracking hook, and health/readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, and one end-to-end critical-path test. ## Decision records For each major dependency, document why it was chosen, its failure mode, and how it can be replaced. Do not introduce infrastructure until a requirement justifies it. ===== AGENTS.md ===== # Agent instructions - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. - Implement milestone by milestone; keep each change reviewable and leave the application runnable. - Treat authentication, payments, encryption, imports, webhooks, and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a test pass. - Use provider interfaces for external services and deterministic fakes in tests. - Add migrations and rollback or recovery notes for persistent data changes. - Log useful operational context without credentials, tokens, passwords, or personal data. - Update documentation and run all checks before completing a milestone. ===== MILESTONES.md ===== # Delivery milestones ## M0 — Decisions and scaffold - Confirm the runtime, persistence model, threat boundaries, and deployment target. - Create a reproducible local environment and continuous checks. ## M1 — Core workflow - Implement the smallest end-to-end product path with validation and tests. - Keep integrations behind interfaces. ## M2 — Trust layer - Add secure failure behavior, recovery paths, audit-relevant events, and data safeguards. - Test abuse cases and destructive operations. ## M3 — Operability - Add structured logs, error reporting hooks, health signals, backup/restore documentation, and deployment configuration. ## M4 — Release gate - Run a clean-install test, critical-path end-to-end test, dependency review, and documented rollback exercise. - Compare the shipped behavior with `PRODUCT.md` and publish remaining limitations. ===== OPERATIONS.md ===== # Operations ## Before release - Validate configuration and secrets at startup. - Define backup, restore, and rollback procedures and test them. - Document logs, error tracking, health signals, and alert ownership. - Set dependency update and vulnerability review expectations. ## Incident checklist 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified source when needed. 5. Document the root cause, remediation, and regression test. ## Launch constraint Do not market omitted FareHarbor capabilities as implemented. The v1 non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# FareHarbor indie build ## Goal Build the smallest trustworthy replacement for the core FareHarbor workflow for one developer or a tiny team. ## Scope Self-hosted booking site: define tours with dated departures and capacity, take deposits or full payment through Stripe Checkout, and give staff a day-view manifest with check-in and cancellation. ## Quick start 1. Install the documented dependencies. 2. Copy `.env.example` to `.env`. 3. Run the development command chosen during implementation. 4. Complete the acceptance checks in `BUILD_PLAN.md`. ## Honest limits This build deliberately does not replace: - OTA and reseller distribution: live availability pushed to Viator, GetYourGuide, Expedia and dozens of local agents, plus the commission accounting behind it - Someone else owning payment risk: chargebacks, disputes, refund flows, payout timing, PCI scope and multi-currency - 24/7 human support during a season where a broken booking page costs real departures that day - The messy operational features you only miss in August: resource and guide assignment, gear allocation, multi-day and multi-activity itineraries, gift cards, promo codes, waivers, group and private bookings - Mobile check-in that works on a beach with one bar of signal, and the reporting your accountant already knows how to read If those capabilities are essential, use FareHarbor instead of pretending the gap is solved.
# Agent instructions - Optimize for a working, understandable weekend build. - Prefer the fewest moving parts that satisfy the brief. - Do not invent cryptography, security guarantees, APIs, or compliance claims. - Keep secrets out of source control and logs. - Add focused tests for destructive, security-sensitive, and data-loss paths. - Run the project checks before declaring the build complete. - Record any deliberate shortcut in the README under "Tradeoffs".
# Build plan ## Original build brief Build a self-hosted booking system for a single tour operator. Stack: Next.js 15 with the App Router, TypeScript, Tailwind, Postgres via Prisma, Stripe Checkout. No auth provider, no analytics, no telemetry. Data model: Product (name, slug, description, duration minutes, base price cents, currency, min and max party size, active flag), Departure (product, start datetime, capacity, status: scheduled | cancelled), Booking (departure, lead name, email, phone, party size, amount cents, stripe payment intent id, status: pending | confirmed | cancelled | refunded, notes, waiver accepted at), Passenger (booking, name, age band). Public side: - /tours lists active products, /tours/[slug] shows the next 60 days of departures with seats remaining computed as capacity minus confirmed and pending party sizes. - Booking flow: pick a departure, enter party size and lead contact, tick a waiver checkbox, then redirect to Stripe Checkout. Create the Booking as pending before redirect. Confirm it only in the Stripe webhook handler, never on the return URL. - Overselling is the thing you must get right: take the seat hold inside a serialisable transaction that re-checks remaining capacity, and expire pending bookings older than 20 minutes with a cron route. Operator side at /admin, protected by a single shared password from .env stored in an httpOnly cookie: - Day view manifest: every departure today with lead names, party sizes, phone numbers, waiver status and a check-in toggle. - Create and bulk-generate departures from a weekday recurrence rule with a date range. - Cancel a departure: refunds all confirmed bookings through the Stripe API and emails everyone. - Manual booking entry for phone and walk-up guests, marked as unpaid or cash. - CSV export of bookings for a date range. Email confirmations and cancellations via Resend, plain text, with an .ics attachment. Money in integer cents, one currency, store all times in UTC and render in a single operator timezone from .env. Explicitly out of scope: OTA or reseller channel sync, promo codes, gift cards, multi-day itineraries, guide and equipment assignment, multi-currency, per-user accounts and roles. Secrets in .env: DATABASE_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, RESEND_API_KEY, ADMIN_PASSWORD, OPERATOR_TIMEZONE. Ship a seed script with two products and 30 days of departures, a README with the Stripe CLI webhook command, and a test that proves a departure cannot be oversold under concurrent requests. ## Required capabilities - Stripe account (test mode is fine to build against) - a domain and any Node host, plus a Postgres or SQLite volume - transactional email provider for confirmations - clear rules for your own cancellation, deposit and capacity logic before you start ## Delivery order 1. Scaffold the smallest runnable application and document its commands. 2. Implement the primary data model and core workflow. 3. Add validation, safe failure states, and persistence. 4. Cover the critical path with automated tests. 5. Exercise a clean install from the README and fix every missing step. ## Done when - A new user can go from clone to first successful workflow using only the README. - The core workflow works without paid infrastructure unless the brief requires it. - Tests cover the highest-risk behavior. - Known limitations are explicit rather than hidden.
# Copy to .env and document every variable when it is introduced. # Never put real credentials in this file. APP_ENV=development # Add only values required by the selected implementation.
# FareHarbor product brief ## Problem The part everyone thinks they are paying for, a calendar with capacity, a checkout, and a manifest the guides can read, is genuinely a weekend build with Stripe doing the hard money parts. The part that is actually load-bearing is everything after that: pushing live availability to Viator, GetYourGuide, Expedia and Booking.com, reconciling reseller commissions, handling refunds and chargebacks on other people's money, and a phone line that answers at 6am when the 7am kayak trip is double-booked. A self-hosted build replaces direct-website bookings cleanly and replaces channel distribution not at all. If most of your volume is direct and you can eat the ops burden, the maths gets interesting fast. If OTAs feed you, you are rebuilding a channel manager, which is not a weekend. ## Product outcome Self-hosted booking site: define tours with dated departures and capacity, take deposits or full payment through Stripe Checkout, and give staff a day-view manifest with check-in and cancellation. ## Target user A serious builder who needs a maintainable product foundation rather than a one-off demo. ## Required capabilities - Stripe account (test mode is fine to build against) - a domain and any Node host, plus a Postgres or SQLite volume - transactional email provider for confirmations - clear rules for your own cancellation, deposit and capacity logic before you start ## Explicit non-goals for v1 - OTA and reseller distribution: live availability pushed to Viator, GetYourGuide, Expedia and dozens of local agents, plus the commission accounting behind it - Someone else owning payment risk: chargebacks, disputes, refund flows, payout timing, PCI scope and multi-currency - 24/7 human support during a season where a broken booking page costs real departures that day - The messy operational features you only miss in August: resource and guide assignment, gear allocation, multi-day and multi-activity itineraries, gift cards, promo codes, waivers, group and private bookings - Mobile check-in that works on a beach with one bar of signal, and the reporting your accountant already knows how to read ## Success criteria - The primary workflow is measurable end to end. - Setup is reproducible in a clean environment. - Failure, recovery, and support paths are documented. - Product claims match what the implementation actually guarantees.
# Architecture ## Starting brief Build a self-hosted booking system for a single tour operator. Stack: Next.js 15 with the App Router, TypeScript, Tailwind, Postgres via Prisma, Stripe Checkout. No auth provider, no analytics, no telemetry. Data model: Product (name, slug, description, duration minutes, base price cents, currency, min and max party size, active flag), Departure (product, start datetime, capacity, status: scheduled | cancelled), Booking (departure, lead name, email, phone, party size, amount cents, stripe payment intent id, status: pending | confirmed | cancelled | refunded, notes, waiver accepted at), Passenger (booking, name, age band). Public side: - /tours lists active products, /tours/[slug] shows the next 60 days of departures with seats remaining computed as capacity minus confirmed and pending party sizes. - Booking flow: pick a departure, enter party size and lead contact, tick a waiver checkbox, then redirect to Stripe Checkout. Create the Booking as pending before redirect. Confirm it only in the Stripe webhook handler, never on the return URL. - Overselling is the thing you must get right: take the seat hold inside a serialisable transaction that re-checks remaining capacity, and expire pending bookings older than 20 minutes with a cron route. Operator side at /admin, protected by a single shared password from .env stored in an httpOnly cookie: - Day view manifest: every departure today with lead names, party sizes, phone numbers, waiver status and a check-in toggle. - Create and bulk-generate departures from a weekday recurrence rule with a date range. - Cancel a departure: refunds all confirmed bookings through the Stripe API and emails everyone. - Manual booking entry for phone and walk-up guests, marked as unpaid or cash. - CSV export of bookings for a date range. Email confirmations and cancellations via Resend, plain text, with an .ics attachment. Money in integer cents, one currency, store all times in UTC and render in a single operator timezone from .env. Explicitly out of scope: OTA or reseller channel sync, promo codes, gift cards, multi-day itineraries, guide and equipment assignment, multi-currency, per-user accounts and roles. Secrets in .env: DATABASE_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, RESEND_API_KEY, ADMIN_PASSWORD, OPERATOR_TIMEZONE. Ship a seed script with two products and 30 days of departures, a README with the Stripe CLI webhook command, and a test that proves a departure cannot be oversold under concurrent requests. ## Boundaries Separate the product into replaceable modules for interface, application logic, persistence, external integrations, and operational concerns. Keep domain logic independent from delivery frameworks and vendors. ## Production baseline - Configuration: validated at startup with safe local defaults where possible. - Security: least privilege, input validation, secret redaction, rate limits on abuse-prone paths, and no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore instructions. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, and timeouts. - Observability: structured logs with request or operation IDs, an error-tracking hook, and health/readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, and one end-to-end critical-path test. ## Decision records For each major dependency, document why it was chosen, its failure mode, and how it can be replaced. Do not introduce infrastructure until a requirement justifies it.
# Agent instructions - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. - Implement milestone by milestone; keep each change reviewable and leave the application runnable. - Treat authentication, payments, encryption, imports, webhooks, and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a test pass. - Use provider interfaces for external services and deterministic fakes in tests. - Add migrations and rollback or recovery notes for persistent data changes. - Log useful operational context without credentials, tokens, passwords, or personal data. - Update documentation and run all checks before completing a milestone.
# Delivery milestones ## M0 — Decisions and scaffold - Confirm the runtime, persistence model, threat boundaries, and deployment target. - Create a reproducible local environment and continuous checks. ## M1 — Core workflow - Implement the smallest end-to-end product path with validation and tests. - Keep integrations behind interfaces. ## M2 — Trust layer - Add secure failure behavior, recovery paths, audit-relevant events, and data safeguards. - Test abuse cases and destructive operations. ## M3 — Operability - Add structured logs, error reporting hooks, health signals, backup/restore documentation, and deployment configuration. ## M4 — Release gate - Run a clean-install test, critical-path end-to-end test, dependency review, and documented rollback exercise. - Compare the shipped behavior with `PRODUCT.md` and publish remaining limitations.
# Operations ## Before release - Validate configuration and secrets at startup. - Define backup, restore, and rollback procedures and test them. - Document logs, error tracking, health signals, and alert ownership. - Set dependency update and vulnerability review expectations. ## Incident checklist 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified source when needed. 5. Document the root cause, remediation, and regression test. ## Launch constraint Do not market omitted FareHarbor capabilities as implemented. The v1 non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
$ choose a build depth, inspect the files, then open the complete pack in your agent · this prompt is generated from the build plan · improve it via PR
Because the fee is usually charged to the traveler, not the operator, so it never shows up as a line item on the operator's P&L the way a subscription would, and because the alternative to a channel manager is manually keeping availability in sync across five OTAs while running trips. Operators also pay for the absence of liability: when a card is disputed or a payout is late, that is not their engineering problem. A DIY build is a real option for a direct-sales operator with a stable product catalogue and someone technical on the team, and it is a bad option for anyone whose seats are filled by resellers.
xOTA and reseller distribution: live availability pushed to Viator, GetYourGuide, Expedia and dozens of local agents, plus the commission accounting behind it
xSomeone else owning payment risk: chargebacks, disputes, refund flows, payout timing, PCI scope and multi-currency
x24/7 human support during a season where a broken booking page costs real departures that day
xThe messy operational features you only miss in August: resource and guide assignment, gear allocation, multi-day and multi-activity itineraries, gift cards, promo codes, waivers, group and private bookings
xMobile check-in that works on a beach with one bar of signal, and the reporting your accountant already knows how to read
Nothing worth pointing at. That's why the prompt exists.
Vibecode FareHarbor
Kinda. The core of FareHarbor is buildable in a weekend with the prompt on this page, but there are real gaps: OTA and reseller distribution: live availability pushed to Viator, GetYourGuide, Expedia and dozens of local agents, plus the commission accounting behind it, Someone else owning payment risk: chargebacks, disputes, refund flows, payout timing, PCI scope and multi-currency. Read the honest list above before committing.
How much does FareHarbor cost?
FareHarbor's pricing is usage-based or varies by plan · No monthly software fee for operators; the fee (commonly cited around 6% in North America, negotiable 5-8%) is added to the traveler's checkout total. OTA-sourced bookings are billed to the operator separately..
What do I lose by replacing FareHarbor?
Honestly: OTA and reseller distribution: live availability pushed to Viator, GetYourGuide, Expedia and dozens of local agents, plus the commission accounting behind it; Someone else owning payment risk: chargebacks, disputes, refund flows, payout timing, PCI scope and multi-currency; 24/7 human support during a season where a broken booking page costs real departures that day; The messy operational features you only miss in August: resource and guide assignment, gear allocation, multi-day and multi-activity itineraries, gift cards, promo codes, waivers, group and private bookings; Mobile check-in that works on a beach with one bar of signal, and the reporting your accountant already knows how to read. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to FareHarbor?
No mature open-source alternative worth pointing at, which is exactly why the one-shot prompt on this page exists.