# Frontend: Route Wiring in App.tsx

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

---

## Step 4: Wire Routes to App.tsx

**Important:** This step is required. 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 (Lazy Loading ONLY)

At the top of App.tsx, ALL page imports MUST use `React.lazy()`:

```tsx
// CORRECT — Lazy loading (MANDATORY per POST-CHECK S6)
const {EntityName}Page = lazy(() =>
  import('@/pages/{Application}/{Module}/{EntityName}Page')
    .then(m => ({ default: m.{EntityName}Page }))
);

// WRONG — Static import is BLOCKING per POST-CHECK S6
// import { {EntityName}Page } from '@/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.

#### 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

**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.

**Do not 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

**Important:** 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, 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.

---

## Patterns to Avoid (BOTH patterns)

- Do not add application routes to `clientRoutes[]` with absolute paths — `clientRoutes` is only for routes outside SmartStack applications (e.g., `/about`, `/pricing`)
- Do not add routes outside the Layout wrapper (shell will not render)
- Do not use `createBrowserRouter` (SmartStack uses `useRoutes()` + `mergeRoutes()`)
- Do not add 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 go in `applicationRoutes` with RELATIVE paths:
  ```tsx
  // ✅ CORRECT
  const applicationRoutes: ApplicationRouteExtensions = {
    'human-resources': [
      { path: 'employees/management', element: <EmployeePage /> },
    ],
  };
  ```
- Do not remove 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
