Date Night
Quenga Designs · 2026
A date-night experience with curated activities, scheduling, and a confirmation flow — small app, disproportionate returns.
- Problem
- Planning a date night usually dies in the group chat — picking activities, checking the calendar, and confirming a time takes more coordination than it should.
- Solution
- I built a seven-screen guided flow — ask, activities, kids, calendar, time, summary, sent — in vanilla TypeScript with no framework, ending in a pre-filled SMS that confirms the plan.
- Result
- Live in production as an installable, offline-capable PWA.
The brief
Turn "we should do something Friday" into a confirmed plan in one sitting. Date Night is deliberately small: one sequence of screens, one output — a text message with the finished plan. The engineering brief was equally opinionated: no framework, no router, no server-side storage, and nothing sends without an explicit user tap.
What was built
A seven-screen guided flow: the ask, activity selection, a kids step for family logistics, a calendar, a time picker, a summary, and a sent confirmation. The finished plan ships as an iOS-safe SMS deep link — synchronous sms: navigation, not a backend send — with phone input passing through a dedicated validator and sanitizer.
The experience layer earns its keep: a FlowerField visual layer with bee and pollen interactions, a keyboard focus-visible ring, and an aria-live region on the itinerary area. It installs as a PWA with a manifest, touch icons, and a service worker that caches the app shell for offline use, with versioned cache invalidation on deploy. Plans persist in localStorage so a refresh resumes where you left off — the phone number deliberately excluded from the persisted blob — and a URL-prefill mechanism can reconstruct a full plan from query params.
Under the hood
Vanilla TypeScript and the DOM — no React, no Vue, no router. Screens are named sections toggled by a ScreenManager; each feature is a controller factory wired by a thin composition root, and all state flows through an immutable PlanState whose transitions return new objects rather than mutating. Rendering uses createElement and textContent exclusively — a deliberate XSS-prevention stance over template-string HTML.
The one server-side piece is api/itinerary.ts, a Vercel function holding the Anthropic API key server-side after I refactored away an early pattern that would have shipped the key to every visitor. The service is wired and hardened but currently dormant — nothing in the UI calls it yet. The build runs tsc -b before Vite, so type errors fail the build.
Where it stands
Live in production. The roadmap's first three phases — ship, durability, PWA and offline — are done; the reach phase is partial, with URL prefill and the SMS template built, and a copy-link button, iCal export, and itinerary wiring still open. Small app, disproportionate returns.