CONTENTS

    How a Travel Site Turns Every Quote Form Into a Scored Lead and a Sent Quote

    avatar
    Cici Yu
    ·September 19, 2026
    ·9 min read

    Pro AI Income, who documents end-to-end app builds with AI tooling, shipped GoTrip: a premium travel site where visitors browse destination packages and request a personalized quote. The split is clean — Claude Code built the React and Vite frontend, and Momen is the entire backend: the database, the AI agent, the email integration, the logins, and the server-side flow that ties them together.

    None of that backend was configured by hand. Momen's no-code plugin connects Claude Code to a Momen project, so one master prompt carrying the project URL and a set of Mailgun credentials was enough: Claude Code created the table, the API integration, the AI agent, and the Actionflow while they appeared live in the Momen editor.

    What the app does

    • Browse packages — four destination cards (Maldives, Bali, Dubai, Switzerland) render straight from the React bundle; they're static marketing content, not rows anyone queries

    • Request a quote — a modal collects name, email, destination, number of travelers, travel date, budget, trip type, booking timeline, and special requirements

    • Get scored on submit — the form starts a server-side flow that runs an AI agent over the inquiry and returns its verdict to the modal

    • Receive a quote by email — the customer gets a personalized quote with a recommended package, a suggested itinerary, and an estimated total, without anyone on the team touching it

    • Work the leads in a private CRM — an admin route shows total, hot, warm, and cold counts, a search box across name, email, destination and recommended package, and ALL / HOT / WARM / COLD filter tabs

    • See the hottest first — the dashboard sorts by status rank, then by lead_score descending, so the inquiries worth calling sit at the top

    The data model: one table carrying both halves of the job

    The interesting choice here is how little there is. With the package catalog living in the frontend, the only thing worth persisting is the lead itself — so beyond Momen's built-in account table there is exactly one business table. travel_lead holds what the visitor typed and what the AI produced in the same row:

    • What the customer submitted — name, email, destination, travel_date, budget, trip_type, booking_timeline, special_requirements as TEXT, plus num_travelers as BIGINT

    • What the AI wrote back — lead_score (BIGINT), status (TEXT, carrying the HOT / WARM / COLD classification the dashboard filters on), ai_summary, recommended_package, recommended_next_action, follow_up_message

    • Pipeline state — processed and email_sent, two booleans recording how far a lead got through the flow, plus the created_at the CRM query sorts on

    travel_date is deliberately free text, not a date column — the form asks for "e.g. October 2026", because someone planning a honeymoon has a month in mind, not a calendar day. The AI reads it as a phrase rather than a timestamp.

    Keeping the AI's output in the lead row rather than in a separate log is what makes the CRM cheap to build: one query returns the inquiry, the score, the recommendation, and the delivery status together. Small calls like that are why it pays to settle the data model before anything binds to it.

    Logins and permissions: the public can trigger, only staff can read

    The project keeps Momen's two default roles and gives them opposite rights on the one table that matters.

    Anonymous User has no permission entry on travel_lead at all — no select, no insert, no update. A visitor can still submit an inquiry, because the form never touches the table: it calls the Actionflow, and the flow writes the row. Asking the project's GraphQL API for a lead's fields without a token comes back refused, which keeps customer email addresses and budgets off the open internet even though the endpoint itself is reachable.

    Logged-in User can read and write every column on travel_lead. That role is the CRM. Sign-in runs through Momen's built-in authentication — authenticateWithUsername returns the account with its permissionRoles plus a JSON Web Token (JWT), which the frontend keeps in local storage and sends as a bearer token on the leads query. That token is the only reason the dashboard returns anything. Momen's permissions documentation covers how the role, table, and column layers combine to produce exactly this asymmetry.

    The login screen says it plainly: "Authenticated with Momen. Access is restricted to authorized staff."

    One Actionflow, six nodes, everything after submit

    The quote form calls fz_create_action_flow_task with the flow's ID and the nine form fields, gets a task ID back, then polls fz_action_flow_result until the task reports COMPLETED or FAILED — up to 14 attempts, 2.5 seconds apart. The flow is configured async with a 120-second timeout, which is why the frontend polls rather than waiting on a response.

    Process Travel Inquiry runs in order:

    • Save Lead — inserts those nine fields and seeds the rest: lead_score 0, status NEW, processed and email_sent both false. Every lead therefore exists in the database before the AI has said anything about it

    • Run AI Qualification — hands the inquiry to the Travel Lead Qualification agent

    • Update Lead with AI results — matches the row by the ID the insert returned, then writes lead_score, status, ai_summary, recommended_package, recommended_next_action, follow_up_message, and flips processed to true

    • Send Travel Email — posts to Mailgun with the subject line "Your GoTrip {destination} journey — a personal recommendation from GoTrip" and the agent's follow_up_message as the body, wrapped in inline-styled HTML with the recommended package repeated in the footer

    • Mark Email Sent — flips email_sent on the same row

    • Output — returns lead_id, lead_score, status, and recommended_package to the browser, which is what the confirmation screen shows

    Seeding status as NEW before the AI runs is the detail worth copying. The row is committed first and enriched second, so a lead is never lost to a slow model or a failed email — it just sits as NEW, outside the HOT, WARM and COLD counts.

    The Mailgun credential is stored as a Momen secret named "Mailgun Basic Auth" and bound to the request's Authorization header, so the key never reaches the frontend bundle. That is the reason to put an API integration behind a backend at all — a key shipped to the browser is a key anyone can read. Momen's Actionflow guide covers how the node chain is assembled.

    No scheduled jobs, no database triggers, and no payment provider in this project. Money changes hands later, offline, once a lead turns into a booking.

    The agent: a scoring rubric, not a chat window

    The Travel Lead Qualification agent runs on Gemini 2.5 Flash at temperature 0.4, with no tools, no database queries, and no API access of its own — it reads one inquiry and returns one verdict. Momen's AI integration covers how a model gets attached to an agent, and choosing between Gemini's tiers is its own decision — Gemini Pro vs Flash vs Nano walks through it.

    Its output is a structured type with six required fields, each carrying its own instruction to the model:

    • lead_score — an integer 0–100, "higher = more likely to book soon and higher value"

    • status — "exactly one of HOT, WARM, or COLD"

    • ai_summary — a 2–3 sentence read on intent, value, urgency, and fit

    • recommended_package — the specific GoTrip package matching destination and budget

    • recommended_next_action — a concrete step for the sales team, e.g. "Call within 2 hours to lock ocean villa"

    • follow_up_message — the customer-facing email body

    Structured output is what lets the next node bind straight to lead_score and status without parsing prose. The rubric is what makes those values mean the same thing twice — and it's where the real work went.

    The system prompt carries its own catalog — eight packages, two per destination, each with a per-person starting price, twice what the marketing page shows. It then ranks the scoring inputs: booking timeline first, then specificity of requirements, then trip type and value, then budget last.

    Above all of that sits a HARD RULE that forces HOT with a score of at least 80 whenever a near-term timeline meets a committed trip type or specific requirements, spelled out in capitals: "a mid-range but workable budget NEVER lowers such a lead below HOT." A rule written that emphatically is a rule that had to be enforced — budget is the input that most easily outvotes readiness, and here it is explicitly demoted.

    The follow_up_message section is prescriptive to the point of being a template — a numbered list of six sections the email must contain in order, down to computing per-person price times number of travelers for the estimated total, noting that flights are extra, and signing off exactly "Warm regards, The GoTrip Team," in 160–220 words. That specificity is what makes a generated email look like a quote instead of a chatbot reply.

    The frontend, and how it got deployed

    Claude Code generated a two-route React app: / for the marketing site — hero, destination packages, an experiences gallery, reviews, and the quote modal — and /admin for the lead CRM. Both talk to the GraphQL API Momen generates from the data model, so there is no server code in the frontend repository at all.

    Deployment went through the plugin rather than a separate host. "Deploy to beta" put the app on a free preview URL for a once-over; "deploy to production" gave it a permanent villa.momenapp.com address, where it is live now. Momen's app deployment docs cover the publishing path.

    One detail the video flags itself: the Admin link sits in the public navigation bar while testing, and should come out before the site goes to real customers. The permission rules already stop a visitor from reading leads — hiding the link is tidiness, not the security boundary.

    What running this actually costs

    Priced against a projected 200 users accumulating over a 225-day operating period — a small staff roster plus the stored quote-request contacts a public lead-capture site builds up in its first year — this project comes to $41.92/month on the Basic plan.

    • Basic plan — $39 — the minimum viable tier here, required for ongoing public publishing, professional branding, SEO, and multiple automated integrations

    • Outbound data transfer add-on — $2.92 — the project needs about 5.71 GB/month against the plan's 2 GB, so a 500 GB annual add-on amortizes to cover the 3.71 GB gap

    • Everything else — $0 — AI points (68K projected against the plan's 1M), database storage (26 MB against 200 MB), object storage (3.67 MB against 2 GB), and peak request rate all fit inside the plan

    The only thing pushing this past the flat plan fee is bandwidth, not AI. A quote page carrying destination photography ships far more bytes than a Gemini call costs in points — the AI work that makes this app interesting is the cheapest thing in it. You can estimate the cost of your own project using Momen's pricing calculator.

    The whole build — the master prompt, the live submission, the email landing in Gmail, and the CRM — is walked through end to end in the video.

    To build on this pattern: install the Momen plugin in Claude Code, describe the record you want stored and the work that should happen after it's stored, and let it build the table, the agent, and the flow before it writes a single component. Then expect to spend your real effort where this build did — on the rubric inside the agent, not on the plumbing around it.

    Vibe No-Coding with Momen Today. Describe Your App, Own Every Piece AI Builds.