What It Does
apps/web-interim is a standalone Next.js 14 app that supports the mobile app with auth callbacks, deep link verification, content redirects, and a landing page with waitlist signup.
This is a SEPARATE app from the full web client (apps/web). They have separate package.json, node_modules, and codebases. The web interim does NOT have API routes for content CRUD — those live in apps/web.
Architecture
| Layer | Technology |
|---|
| Framework | Next.js 14 (App Router) |
| Styling | Tailwind CSS (no CSS Modules) |
| Auth | Supabase browser client (@supabase/ssr) |
| Deployment | Vercel |
| Fonts | Cormorant Garamond / Fraunces (serif) |
Pages
| Route | Component | Purpose |
|---|
/ | page.tsx | Landing page with waitlist signup |
/auth/confirm | Route handler | Server-side OTP verification — handles email confirmation, password recovery, and email change tokens |
/confirmation-success | ConfirmationSuccess | Email verified success |
/reset-password | ResetPassword | Password reset form |
/email-change-pending | EmailChangePending | Waiting for new email confirmation |
/change-email | ChangeEmail | Email change success |
/auth/auth-error | AuthError | Auth link invalid/expired |
/recipes/[id] | AppOnlyContent | Recipe deep link redirect |
/posts/[id] | AppOnlyContent | Post deep link redirect |
/collections/[id] | AppOnlyContent | Collection deep link redirect |
/.well-known/apple-app-site-association | Route handler | AASA for iOS universal links |
/.well-known/assetlinks.json | Route handler | Android Asset Links |
/api/waitlist | Route handler | Waitlist signup via marketing-events Supabase edge function |
The app also includes error.tsx (global error boundary) and not-found.tsx (404 page) at the root layout level.
Auth Callback Flow
The /auth/confirm route handler is the central entry point for all Supabase email link callbacks. When a user clicks a link in a confirmation, recovery, or email change email, the link points to this route with a token_hash and type parameter.
The route calls supabase.auth.verifyOtp() server-side, then redirects based on the OTP type:
| OTP Type | Redirect To | Purpose |
|---|
signup or email | /confirmation-success | Email address confirmed after registration |
recovery | /reset-password | Password reset — user enters new password |
email_change | /change-email | Email change confirmed |
| (any error) | /auth/auth-error | Token invalid, expired, or missing |
The AuthCallbackHandler component (used on pages like /confirmation-success) handles a secondary path: PKCE code exchange via URL query params and hash fragment token parsing for cases where the redirect includes tokens in the URL fragment rather than as query parameters.
Components
| Component | Purpose |
|---|
AuthCallbackHandler | Processes auth tokens from email links (PKCE code exchange + hash fragment handling) |
RecoveryHandler | Backup handler for recovery hash fragments (possibly redundant with /auth/confirm) |
AppOnlyContent | Content redirect page — deep link attempt + “app only” fallback with waitlist |
Design Language
- Monochrome palette (#111111 primary, #fafafa backgrounds, #777777 secondary text)
- Cormorant Garamond / Fraunces serif fonts for headings
- Film-strip sprocket edge decorations on desktop
- Grain overlay texture
- Staggered entrance animations (cubic-bezier easing)
- Consistent accent lines (gradient top/bottom borders)
Key Differences from apps/web
| Aspect | Web Interim | Full Web Client |
|---|
| API routes | No content CRUD | All API routes |
| Middleware | None | Auth-based route protection |
| Supabase client | Browser-only | Server + browser |
| Shared package | No dependency | Uses @recipe-room/shared |
| node_modules | Standalone | Hoisted from monorepo root |
| Scope | Auth callbacks, redirects, landing | Full web application |
Landing Page & Waitlist
The home page is a branded landing page with:
- Hero section with app description and waitlist form
- Feature highlights
- Film-strip visual motif
- Waitlist form →
POST /api/waitlist → marketing-events edge function → Loops.so API
- Responsive design (mobile + desktop)
The /api/waitlist route now uses the marketing-events Supabase edge function, which reads the Loops API key from edge function secrets. No API keys are stored in the web-interim codebase.
Web Client Middleware (apps/web only)
apps/web/src/middleware.ts implements Next.js middleware for auth-based route protection. This exists in the full web client, NOT in the web interim.
| Route Type | Examples | Behavior |
|---|
| Protected | /settings, /saved, /create/*, /me | Redirect to /login if unauthenticated |
| Public | /, /login, /register, /recipes/*, /posts/* | Accessible to all |
Uses @supabase/ssr createServerClient with cookie handling. Phase 2 consideration when the full web client is refactored.