> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bunship.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Adding New Pages

> How to create new pages, add them to the sidebar, and protect them with RBAC.

# Adding New Pages

BunShip Pro uses [TanStack Router](https://tanstack.com/router) with file-based routing. Create a file and you have a route.

## How Routing Works

Routes live in `apps/web/src/routes/`. The file name becomes the URL path:

| File                                            | URL                             |
| ----------------------------------------------- | ------------------------------- |
| `routes/index.tsx`                              | `/`                             |
| `routes/_app/dashboard.tsx`                     | `/dashboard`                    |
| `routes/_app/organizations_.$orgId/members.tsx` | `/organizations/:orgId/members` |
| `routes/_marketing/pricing.tsx`                 | `/pricing`                      |

### Layout Groups

Files are organized into layout groups using the underscore prefix:

| Prefix        | Layout                            | Purpose                         |
| ------------- | --------------------------------- | ------------------------------- |
| `_app/`       | Authenticated layout with sidebar | Dashboard, settings, org pages  |
| `_auth/`      | Minimal centered layout           | Login, register, password reset |
| `_marketing/` | Marketing header/footer           | Pricing, blog, contact, legal   |

The layout file (e.g., `_app.tsx`) wraps all pages in that group with shared UI — sidebar, header, auth protection.

## Adding a Dashboard Page

1. Create a file in `routes/_app/`:

```tsx theme={null}
// apps/web/src/routes/_app/analytics.tsx
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/_app/analytics")({
  component: AnalyticsPage,
});

function AnalyticsPage() {
  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-semibold tracking-tight">Analytics</h1>
        <p className="text-sm text-muted-foreground">View your usage analytics.</p>
      </div>

      {/* Your page content */}
    </div>
  );
}
```

2. The page is now accessible at `/analytics` (authentication required automatically via the `_app` layout).

## Adding an Organization Page

Organization pages are scoped to a specific org and have access to the org ID from the URL:

```tsx theme={null}
// apps/web/src/routes/_app/organizations_.$orgId/reports.tsx
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/_app/organizations_/$orgId/reports")({
  component: ReportsPage,
});

function ReportsPage() {
  const { orgId } = Route.useParams();

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-semibold tracking-tight">Reports</h1>
        <p className="text-sm text-muted-foreground">Generate and view reports.</p>
      </div>

      {/* Use orgId to fetch org-specific data */}
    </div>
  );
}
```

This page is available at `/organizations/:orgId/reports`.

## Adding to the Sidebar

The sidebar navigation is defined in `apps/web/src/components/sidebar.tsx`. There are two navigation arrays:

### Main Navigation

Add items to the `DEFAULT_SECTIONS` array:

```tsx theme={null}
const DEFAULT_SECTIONS: NavSection[] = [
  {
    label: "Workspace",
    items: [
      { label: "Dashboard", href: "/dashboard", icon: LayoutDashboard },
      { label: "Organizations", href: "/organizations", icon: Building2 },
      { label: "Analytics", href: "/analytics", icon: BarChart3 }, // new
    ],
  },
  // ...
];
```

### Organization Navigation

Add items to the `ALL_ORG_ITEMS` array. Each item belongs to either the `org` section (user-facing) or `dev` section (developer tools):

```tsx theme={null}
const ALL_ORG_ITEMS: Array<NavItem & { section: "org" | "dev" }> = [
  // existing items...
  { section: "dev", label: "Reports", href: "/reports", icon: FileText }, // new
];
```

Import icons from `lucide-react`.

## Protecting Pages by Role

The organization layout provides role context. Use the `useOrgContext()` hook to check the current user's role:

```tsx theme={null}
import { useOrgContext } from '../organizations_.$orgId'

function ReportsPage() {
  const { role } = useOrgContext()

  // Hide admin-only sections
  if (role === 'viewer') {
    return <p className="text-sm text-muted-foreground">You don't have access to reports.</p>
  }

  return (
    // Full page content
  )
}
```

### Role Hierarchy

Roles are hierarchical: `owner > admin > member > viewer`. Permissions are defined in `packages/config/src/features.ts`:

```tsx theme={null}
permissions: {
  owner: ["*"],
  admin: ["org:read", "org:update", "members:*", "billing:read", ...],
  member: ["org:read", "members:read", "projects:*", "files:read", "files:upload"],
  viewer: ["org:read", "members:read", "projects:read", "files:read"],
}
```

## Adding a Marketing Page

Marketing pages use the `_marketing` layout with the public header and footer:

```tsx theme={null}
// apps/web/src/routes/_marketing/about.tsx
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/_marketing/about")({
  component: AboutPage,
});

function AboutPage() {
  return (
    <div className="mx-auto max-w-4xl px-6 py-24">
      <h1 className="text-4xl font-bold tracking-tight">About Us</h1>
      <p className="mt-4 text-lg text-muted-foreground">Our story...</p>
    </div>
  );
}
```

To add it to the marketing header navigation, edit `apps/web/src/components/marketing-header.tsx`.

## Next Steps

* [UI Components](/pro/components) — Available components for building page content
* [Configuration](/pro/configuration) — Feature flags and RBAC settings
