Owner: Engineering Team | Last Updated: 2026-01-30 | Status: Current
The web app uses the Next.js App Router with locale-prefixed routes (/[locale]/...), route groups for shared layouts, and middleware for both internationalization (via next-intl) and authentication (via next-auth). Every user-facing route is nested under a dynamic [locale] segment supporting 8 languages. Server-side API routes live under app/api/ without locale prefixing. For the full web app overview, see Web App Overview.
app/
├── layout.tsx # Root layout (html, body, fonts, analytics)
├── error.tsx # Root error boundary
├── global-error.tsx # Global unhandled error boundary
├── not-found.tsx # Root 404 page
├── styles.css # Global styles
│
├── [locale]/ # Dynamic locale segment (en, de, es, fr, it, pt, zh, nl)
│ ├── layout.tsx # Locale layout (wraps all locale pages)
│ ├── providers.tsx # Client providers (theme, auth session, Redux store)
│ ├── page.tsx # Landing page (/)
│ ├── error.tsx # Locale-level error boundary
│ ├── not-found.tsx # Locale-level 404
│ ├── loading.tsx # Locale-level loading state
│ │
│ │── ── PUBLIC PAGES ── ──
│ ├── humanizer/ # /[locale]/humanizer
│ ├── detector/ # /[locale]/detector
│ ├── login/ # /[locale]/login
│ ├── register/ # /[locale]/register
│ ├── forgot-password/ # /[locale]/forgot-password
│ ├── reset-password/ # /[locale]/reset-password
│ ├── register-verification/ # /[locale]/register-verification
│ ├── verify/ # /[locale]/verify
│ ├── account-setup/ # /[locale]/account-setup
│ ├── account-deleted/ # /[locale]/account-deleted
│ ├── checkout/ # /[locale]/checkout
│ ├── pricing/ # /[locale]/pricing
│ ├── trial-started/ # /[locale]/trial-started
│ ├── trial-started-email-signup/ # /[locale]/trial-started-email-signup
│ ├── payment-failed-redirect/[token]/ # /[locale]/payment-failed-redirect/:token (dynamic)
│ ├── wp-plugin-callback/ # /[locale]/wp-plugin-callback
│ ├── sentry-example-page/ # /[locale]/sentry-example-page (error tracking demo)
│ │
│ │── ── EMBED PAGES ── ──
│ ├── embed/ # /[locale]/embed (variant 1)
│ ├── embed-2/ # /[locale]/embed-2
│ ├── embed-3/ # /[locale]/embed-3
│ ├── embed-4/ # /[locale]/embed-4
│ ├── embed-5/ # /[locale]/embed-5
│ ├── embed-6/ # /[locale]/embed-6
│ ├── embed-register/ # /[locale]/embed-register
│ │
│ │── ── PROTECTED: DASHBOARD GROUP ── ──
│ ├── (dashboard)/ # Route group -- shared sidebar layout
│ │ ├── layout.tsx # Dashboard sidebar layout
│ │ ├── dashboard/ # /[locale]/dashboard
│ │ ├── documents/ # /[locale]/documents
│ │ ├── settings/ # /[locale]/settings
│ │ ├── refer-a-friend/ # /[locale]/refer-a-friend
│ │ └── request-a-feature/ # /[locale]/request-a-feature
│ │
│ │── ── THANK-YOU GROUP ── ──
│ ├── (thank-you)/ # Route group -- minimal layout
│ │ ├── thank-you/ # /[locale]/thank-you
│ │ └── thank-you-1/ # /[locale]/thank-you-1
│ │
│ │── ── SEO & SHARED COMPONENTS ── ──
│ ├── seo/sitemap.ts # Dynamic sitemap generation
│ └── components/
│ ├── Footer.tsx # Shared footer component
│ └── UpdateUserSession.tsx # Session refresh component
│
├── api/ # Server-side API routes (no locale prefix)
│ ├── auth/
│ │ ├── [...nextauth]/route.ts # NextAuth.js catch-all handler
│ │ └── register.ts # Server-side registration helpers
│ ├── churnkey-generate/route.ts # Churnkey hash generation
│ ├── ipconfig/route.ts # IP configuration endpoint
│ ├── actions.ts # Shared API call wrapper
│ └── sentry-example-api/route.ts # Sentry demo endpoint
│
└── middleware.ts # Request middleware (locale + auth)
| Code | Language |
|---|---|
en |
English (default) |
de |
German |
es |
Spanish |
fr |
French |
it |
Italian |
pt |
Portuguese |
zh |
Chinese |
nl |
Dutch |
Default locale: en
Every user-facing route is prefixed with a locale segment. For example, the login page resolves to /en/login, /de/login, /es/login, and so on. The next-intl middleware detects the user's preferred locale from browser headers and redirects accordingly.
The middleware pipeline is defined in middleware.ts at the project root. It chains two middleware layers:
next-intl middleware -- Locale detection and redirectnext-auth withAuth middleware -- Authentication enforcementIncoming Request
│
▼
┌─────────────────────────┐
│ next-intl middleware │
│ - Detect locale from │
│ Accept-Language or │
│ URL prefix │
│ - Redirect to locale- │
│ prefixed URL if │
│ missing │
└────────────┬────────────┘
│
▼
┌─────────────────────────┐
│ next-auth withAuth │
│ - Check JWT token │
│ - Set Sentry user │
│ context │
│ - If public page → │
│ allow through │
│ - If protected page │
│ and no token → │
│ redirect to /login │
│ - Preserve extension= │
│ true query param │
└────────────┬────────────┘
│
▼
Route Handler
These routes are accessible without a valid session. The middleware skips auth checks for paths matching these patterns:
| Path Pattern | Description |
|---|---|
/ |
Landing page |
/account-setup |
Onboarding wizard |
/account-deleted |
Account deletion confirmation |
/checkout |
Payment checkout |
/embed |
Embed variant 1 |
/embed-2 through /embed-6 |
Embed variants 2-6 |
/embed-register |
Embed registration |
/forgot-password |
Password reset request |
/login |
Login page |
/pricing |
Pricing page |
/register |
Registration page |
/register-verification |
Registration verification |
/reset-password |
Password reset form |
/trial-started-email-signup |
Trial start (email signup flow) |
/verify |
Email verification |
/sentry-example-page |
Error tracking demo |
/payment-failed-redirect/.+ |
Payment failure redirect (dynamic token) |
/wp-plugin-callback |
WordPress plugin callback |
Every route not in the public list above requires a valid JWT session. If the user is unauthenticated, the middleware redirects to /[locale]/login.
Key protected routes include:
/dashboard -- Main dashboard/documents -- Document history/settings -- User settings/refer-a-friend -- Referral program/request-a-feature -- Feature request page/humanizer -- Humanizer tool (authenticated tier)/detector -- Detector tool (authenticated tier)/thank-you, /thank-you-1 -- Post-purchase confirmation/trial-started -- Trial activation confirmation| Behavior | Detail |
|---|---|
| Extension parameter preservation | When extension=true is present as a query parameter, the middleware preserves it through auth redirects. This supports the browser extension login flow where the user is redirected to /login?extension=true and the parameter must survive the full redirect chain. |
| Sentry user context | On every request, the middleware sets the Sentry user context from the JWT token so that errors are attributed to the correct user in monitoring. |
| JWT validation | The JWT token is checked on every request. Expired or invalid tokens trigger a redirect to the login page. |
Next.js route groups (directories wrapped in parentheses) allow multiple routes to share a layout without the group name appearing in the URL.
(dashboard) -- Dashboard Layout GroupLayout file: app/[locale]/(dashboard)/layout.tsx
This route group wraps all authenticated dashboard pages in a sidebar navigation layout. The sidebar provides links to the dashboard, documents, settings, referrals, and feature requests.
Routes in this group:
| Route | URL Path | Purpose |
|---|---|---|
dashboard/ |
/[locale]/dashboard |
Main dashboard view |
documents/ |
/[locale]/documents |
Document history and management |
settings/ |
/[locale]/settings |
User account settings |
refer-a-friend/ |
/[locale]/refer-a-friend |
Referral program interface |
request-a-feature/ |
/[locale]/request-a-feature |
Feature request submission |
All routes in this group require authentication. The (dashboard) directory name does not appear in the URL -- /[locale]/dashboard resolves to app/[locale]/(dashboard)/dashboard/page.tsx.
(thank-you) -- Thank You Layout GroupLayout file: app/[locale]/(thank-you)/layout.tsx (if present)
This route group wraps post-purchase confirmation pages in a minimal layout without the full dashboard sidebar.
Routes in this group:
| Route | URL Path | Purpose |
|---|---|---|
thank-you/ |
/[locale]/thank-you |
Post-purchase confirmation |
thank-you-1/ |
/[locale]/thank-you-1 |
Alternate thank-you variant |
API routes live under app/api/ and do not use the [locale] prefix. They handle server-side logic and integrations.
| Route | Method | Purpose |
|---|---|---|
/api/auth/[...nextauth] |
GET, POST | NextAuth.js catch-all handler. Manages sign-in, sign-out, session, and callback endpoints. |
/api/auth/register |
-- | Server-side registration helpers (not a standard route handler; used internally). |
/api/churnkey-generate |
POST | Generates HMAC hash for Churnkey cancellation flow integration. |
/api/ipconfig |
GET | Returns IP configuration data for the requesting client. |
/api/actions |
-- | Shared API call wrapper module (not a route handler; utility used by server actions). |
/api/sentry-example-api |
GET | Sentry error tracking demo endpoint for testing error reporting. |
The app provides multiple embeddable widget variants for third-party integration:
| Route | URL Path |
|---|---|
embed/ |
/[locale]/embed |
embed-2/ |
/[locale]/embed-2 |
embed-3/ |
/[locale]/embed-3 |
embed-4/ |
/[locale]/embed-4 |
embed-5/ |
/[locale]/embed-5 |
embed-6/ |
/[locale]/embed-6 |
embed-register/ |
/[locale]/embed-register |
All embed routes are public (no auth required). They are designed to be loaded inside iframes on partner sites. The embed-register route provides a registration form tailored for the embedded context.
| Route | Segment | Purpose |
|---|---|---|
app/[locale]/ |
[locale] |
Language prefix. Matches one of: en, de, es, fr, it, pt, zh, nl. |
app/[locale]/payment-failed-redirect/[token]/ |
[token] |
Unique payment failure token. Used to identify the failed transaction and display recovery options. |
app/api/auth/[...nextauth]/ |
[...nextauth] |
NextAuth.js catch-all. Matches /api/auth/signin, /api/auth/callback/*, /api/auth/signout, etc. |
Site navigation is defined in config/site.ts:
export const siteConfig = {
name: 'Walter AI',
navItems: [
{ label: 'Home', href: '/' },
{ label: 'Docs', href: '/docs' },
{ label: 'Pricing', href: '/pricing' },
{ label: 'About', href: '/about' },
],
navMenuItems: [
{ label: 'Profile', href: '/profile' },
{ label: 'Dashboard', href: '/dashboard' },
{ label: 'Settings', href: '/settings' },
// ... additional items
],
}
| Property | Usage |
|---|---|
navItems |
Top-level navigation bar links visible on public pages (Home, Docs, Pricing, About). |
navMenuItems |
Mobile/hamburger menu items and authenticated user menu (Profile, Dashboard, Settings, etc.). |
Note: Some siteConfig links (e.g., /docs, /about, /profile) may point to routes not yet implemented in the App Router or served by an external system.
| File | Purpose |
|---|---|
app/[locale]/seo/sitemap.ts |
Generates a dynamic sitemap for search engine indexing. Produces locale-aware URLs for all public pages. |
The app uses Next.js error boundaries at multiple levels:
| File | Scope |
|---|---|
app/error.tsx |
Root-level error boundary (catches errors outside locale routes) |
app/global-error.tsx |
Global unhandled error boundary (last resort) |
app/not-found.tsx |
Root-level 404 page |
app/[locale]/error.tsx |
Locale-level error boundary |
app/[locale]/not-found.tsx |
Locale-level 404 page |
app/[locale]/loading.tsx |
Locale-level loading/suspense fallback |
| Date | Author | Change |
|---|---|---|
| 2026-01-30 | Admin | Expanded with complete route tree, middleware details, route groups, embed routes, dynamic routes, navigation config, error boundaries, and SEO section |
| 2026-01-30 | Admin | Initial creation |
Prev: Folder Structure | Next: Web App - State Management (Redux) | Up: WalterWrites