I know Claude Code deeply. I have built an agent org chart around it, a lesson book with it, and an entire toolkit on top of it. What I did not know deeply was OpenAI Codex. Reading docs was not going to fix that. Shipping something would.
So I built Daytripper, a small travel planner, in one overnight-plus-morning session, entirely with Codex. It is the first of a planned three small apps: brief, plan, build, review, test, launch, each time going deeper into the Codex workflow. Source at github.com/motozero/daytripper.dev.
#What it does
The fastest way to drain the joy out of a free day in a new city is to spend it researching what to do. Daytripper compresses that into one screen: pick Lisbon, Tokyo, or Mexico City, set a $50 / $100 / $200+ budget, choose morning, evening, or full day, a vibe, a pace, and up to three interests. It returns one thoughtful day plan with an honest cost estimate, a “why this fits” explanation in plain language, and a city-specific local note - like a warning that Lisbon’s calçada pavement is beautiful and famously slick. You can swap stops, add extras until the budget is full, save to localStorage, and copy a shareable text version.
The part people find surprising: the app I built to learn an AI coding agent contains no AI at runtime. No external APIs, no accounts, no backend, no LLM calls. A curated pool of 36 activities and a deterministic, fully typed scoring engine in lib/planner.ts. That was deliberate. Deterministic and explainable means every combination is testable - and the test suite runs all 1,296 of them (3 cities x 3 budgets x 3 time windows x 4 vibes x 3 paces x 4 interest sets), asserting chronology, city grounding, budget safety, and distinct extras on each one. When the product later needs fresh data, that limitation will justify a place API or grounded generation. Not before.
#The first prompt failed, and the evidence is in git
My first prompt was underspecified, and Codex built a polished but thin itinerary editor - a day-by-day trip organizer, competent and completely missing the point. The first commit’s README describes that wrong app in detail. Twenty-one minutes later, commit two replaces it with the real thing: the city-selection generator loop I actually wanted.
I am leaving that in the history on purpose, because it was the most instructive moment of the build. Codex moves fast and produces convincing output either way. The product definition and the quality bar stay my job. The workflow that worked was: brief, build, inspect, critique, test, refine, publish. Later I kicked the tires again and found two demo-breakers Codex had shipped without complaint - a profile button that did nothing and a save button with no useful return path. The QA report in the repo documents one High and six Medium bugs, each with a root cause, all fixed before launch.
#What the build revealed about Codex itself
The most interesting things I learned were in the scaffolding, not the app code:
- A project is a directory. Codex works inside the folder you open: reads it, makes scoped changes, runs commands, tests the result. Git records how the directory changes. Same mental model as Claude Code, which made the transfer fast.
- The sandbox is real and observable. The template’s
vite.config.tschecksCODEX_SANDBOX === "seatbelt"and switches Vite to polling file-watchers, because macOS Seatbelt blocks FSEvents inside Codex’s sandbox. You can see exactly how the agent is contained. - Codex ships a hosting control plane.
.openai/hosting.jsondeclares D1 and R2 bindings for Codex-hosted apps, and the build step packages it intodist/.openai/. There is also a complete “Sign in with ChatGPT” helper that works by reading proxy-injected headers likeoai-authenticated-user-id. I used none of it, but it is a clear picture of where OpenAI is pointing this: brief to deployed, batteries included. - Test that you shipped the app, not the loading screen. The template includes a smoke test asserting the built Worker’s HTML does not contain
codex-previewor “Building your site”. That regression guard exists because someone needed it.
#The stack
Next.js 16 with App Router, React 19, TypeScript, and vinext - a Vite-based runtime that compiles a Next app into a Cloudflare Worker. Drizzle is configured for D1 but the schema file is intentionally empty, with a comment telling future-me to add tables only when the site actually needs a database. Tests run on Node’s built-in test runner with --experimental-strip-types, zero test-framework dependencies. Deployed as a Worker on my Cloudflare account at daytripper.dev.
Ten commits, one author, one night and one morning. The lesson was not how to ask an agent for more code. It was how to make the product loop precise, give useful constraints, inspect the result, and close the loop with tests and a real artifact.
The next build goes deeper into the parts this one only touched: AGENTS.md, Codex skills, and the OpenAI API at runtime. That one is called RepoFinder, and it gets its own post.
Let’s go!