# Frontend: Route Wiring in App.tsx

> Referenced from `steps/step-05-frontend.md` — Detailed route wiring patterns and verification.

---

## Step 4: Wire Routes to App.tsx (BLOCKING)

**CRITICAL:** This step is MANDATORY. Without it, routes exist as files but are invisible to the React Router. The page will be BLANK.

After `scaffold_routes` generates the route files, you MUST manually insert the routes into `App.tsx`.

---

## Step 4a: Import Page Components

At the top of App.tsx:

```tsx
import { {EntityName}Page } from '@/pages/{Application}/{Module}/{EntityName}Page';
// Or lazy-loaded:
const {EntityName}Page = lazy(() => import('@/pages/{Application}/{Module}/{EntityName}Page'));
```

---

## Step 4a.5: Import Generated Route Extensions (if scaffold_routes was used)

If `scaffold_routes` generated `applicationRoutes.generated.tsx`, import and spread:

```tsx
import { applicationRouteExtensions } from '@/routes/applicationRoutes.generated';

const applicationRoutes: ApplicationRouteExtensions = {
  ...applicationRouteExtensions,
  // additional manual routes if needed...
};
```

If no generated file exists, add routes directly to the existing `applicationRoutes` object.

---

## Step 4b: Detect App.tsx Routing Pattern

Read App.tsx and detect which pattern is used:

### Pattern A: applicationRoutes Object

**If App.tsx contains:** `applicationRoutes: ApplicationRouteExtensions`

→ Add routes to `applicationRoutes.{application}[]` with **RELATIVE** paths (no leading `/`)

```tsx
const applicationRoutes: ApplicationRouteExtensions = {
  'human-resources': [
    // existing routes...
    { path: '{module_kebab}/{section_kebab}', element: <{EntityName}ListPage /> },
    { path: '{module_kebab}/{section_kebab}/create', element: <Create{EntityName}Page /> },
    { path: '{module_kebab}/{section_kebab}/:id', element: <{EntityName}DetailPage /> },
    { path: '{module_kebab}/{section_kebab}/:id/edit', element: <Create{EntityName}Page /> },

    // Parent redirect routes (MANDATORY — prevents /login redirect on parent navigation)
    { path: '{module_kebab}', element: <Navigate to="{module_kebab}/{first_section_kebab}" replace /> },
    { path: '', element: <Navigate to="{first_module_kebab}/{first_section_kebab}" replace /> },
  ],
};
```

Routes are automatically injected into BOTH standard (`/{application}/...`) and tenant-prefixed (`/t/:slug/{application}/...`) route trees by `mergeRoutes()`. No manual duplication needed.

#### RULE — Route Ordering in applicationRoutes

> **CRITICAL:** Routes within each application key MUST follow static-before-dynamic order.
> React Router matches top-to-bottom — a `:id` route placed before a `dashboard` route
> will match `dashboard` as an `id` parameter → 404.

```tsx
const applicationRoutes: ApplicationRouteExtensions = {
  'human-resources': [
    // ✅ CORRECT ORDER — static before dynamic
    { path: 'employees', element: <EmployeesPage /> },
    { path: 'employees/create', element: <CreateEmployeePage /> },
    { path: 'employees/dashboard', element: <EmployeeDashboardPage /> },
    { path: 'employees/:id', element: <EmployeeDetailPage /> },
    { path: 'employees/:id/edit', element: <EditEmployeePage /> },

    // Redirect routes ALWAYS LAST
    { path: '', element: <Navigate to="employees" replace /> },
  ],
};
```

```tsx
// ❌ FORBIDDEN — :id before static routes
'human-resources': [
  { path: 'employees/:id', element: <EmployeeDetailPage /> },      // ← WRONG: catches 'dashboard'
  { path: 'employees/dashboard', element: <DashboardPage /> },      // ← NEVER REACHED
]
```

See `smartstack-layers.md` "RULE — Frontend Route Ordering" for the full ordering specification.
POST-CHECK C49 detects and BLOCKS this anti-pattern.

#### Custom Applications (Pattern A)

Custom application keys (any key **not** in the built-in list: `administration`, `support`, `user`, `api`) are fully supported in `applicationRoutes`. `mergeRoutes()` automatically:

1. Creates a new route entry wrapped in `<AppLayout />`
2. Injects it into **both** standard (`/{app-key}/...`) and tenant-prefixed (`/t/:slug/{app-key}/...`) trees, inside `TenantRouteWrapper > RouteGuard > LicenseGuard`
3. Generates automatic parent redirect routes (e.g., `employees` → `employees/management`)

No need to use Pattern B for custom applications — Pattern A handles everything automatically.

### Pattern B: JSX Routes

**If App.tsx contains:** `<Route path="/{application}" element={<{Layout} />}>`

→ Insert `<Route>` children inside the Layout wrapper:

```tsx
<Route path="/human-resources" element={<AppLayout />}>
  {/* ... existing routes ... */}
  <Route path="{module_kebab}" element={<{EntityName}Page />} />
</Route>
```

**ALSO add the same routes inside the tenant-prefixed block:**

Find `<Route path="/t/:slug">` and add the **same route entries** there.

---

## Step 4b.5: Verify mergeRoutes() Call (BLOCKING)

**BEFORE modifying routes, READ App.tsx and verify the `mergeRoutes()` call has 2 parameters.**

✅ Correct:
```tsx
const routes = mergeRoutes(clientRoutes, applicationRoutes);
```

❌ If you see only 1 parameter:
```tsx
const routes = mergeRoutes(clientRoutes);
```

→ Add the `applicationRoutes` object and pass it as 2nd parameter.
Without it, ALL application routes are silently ignored → blank page or /login redirect.

**NEVER remove the `applicationRoutes` parameter or the `ApplicationRouteExtensions` import.**

---

## Step 4c: Application-to-Layout Mapping

| Application prefix | Layout Component | Route path |
|---------|------------------|------------|
| `administration.*` | `AppLayout` | `/administration` |
| `*` (business apps) | `AppLayout` | `/{application}` |
| `myspace.*` | `AppLayout` | `/myspace` |

---

## Step 4d: Verify Wiring

```
Tool: mcp__smartstack__validate_frontend_routes
Args:
  scope: "routes"
```

If `appWiring.issues` is not empty, fix the wiring before proceeding.

---

## Step 4e: Parent Redirect Routes (MANDATORY)

**CRITICAL:** Without parent redirects, navigating to an application or module URL (e.g., `/human-resources` or `/human-resources/employees`) will cause a redirect to `/login` because no route matches.

For each application, you MUST add:

1. **Application root redirect** — redirects `/{application}` to the first module/section:
   ```tsx
   { path: '', element: <Navigate to="{first_module}/{first_section}" replace /> }
   ```

2. **Module redirect** (if modules have sections) — redirects `/{application}/{module}` to first section:
   ```tsx
   { path: '{module}', element: <Navigate to="{module}/{first_section}" replace /> }
   ```

**Example:** For NavRoutes `human-resources.employees.management` and `human-resources.employees.departments`:
```tsx
{ path: 'employees', element: <Navigate to="employees/management" replace /> },
{ path: '', element: <Navigate to="employees/management" replace /> },
```

The `to` prop is resolved relative to the **parent route** (`/{application}`), so always use the full path from the application root.

> Note: `scaffold_routes` with `outputFormat: "applicationRoutes"` generates these redirects automatically.

---

## Forbidden Patterns (BOTH patterns)

- Adding application routes to `clientRoutes[]` with absolute paths — `clientRoutes` is ONLY for routes outside SmartStack applications (e.g., `/about`, `/pricing`)
- Adding routes OUTSIDE the Layout wrapper (shell will not render)
- Using `createBrowserRouter` (SmartStack uses `useRoutes()` + `mergeRoutes()`)
- Adding custom application routes to `clientRoutes[]` with absolute paths:
  ```tsx
  // ❌ WRONG — bypasses RouteGuard + TenantLayout + AppLayout → /login redirect
  const clientRoutes: RouteConfig[] = [
    { path: '/human-resources/employees/management', element: <EmployeePage /> },
  ];
  ```
  Custom application routes MUST go in `applicationRoutes` with RELATIVE paths:
  ```tsx
  // ✅ CORRECT
  const applicationRoutes: ApplicationRouteExtensions = {
    'human-resources': [
      { path: 'employees/management', element: <EmployeePage /> },
    ],
  };
  ```
- Removing the `applicationRoutes` 2nd parameter from `mergeRoutes()` — this silently breaks ALL custom routes

---

## Verification Checklist

- [ ] Routes are inside the AppLayout wrapper
- [ ] Routes use NESTED structure (not flat)
- [ ] Application kebab-case matches navigation seed data
- [ ] Both standard and tenant-prefixed blocks have routes (if using Pattern B)
- [ ] Page components are imported at top of App.tsx
- [ ] `mcp__smartstack__validate_frontend_routes` returns no issues
