---
description: Creating new Pages in the app
globs: apps/**
alwaysApply: false
---
# Creating Pages

# Makerkit Page & Layout Guidelines

## Page Structure Overview

Makerkit uses Next.js App Router architecture with a clear separation of concerns for layouts and pages. The application's structure reflects the multi-tenant approach with specific routing patterns:

```
- app
  - home        # protected routes
    - (user)    # user workspace (personal account context)
    - [account] # team workspace (team account context)
  - (marketing) # marketing pages
  - auth        # auth pages
```

## Key Components

### Layouts

Layouts in Makerkit provide the structure for various parts of the application:

1. **Root Layout**: The base structure for the entire application
2. **Workspace Layouts**:
   - User Workspace Layout (`app/home/(user)/layout.tsx`): For personal account context
   - Team Workspace Layout (`app/home/[account]/layout.tsx`): For team account context

Layouts handle:
- Workspace context providers
- Navigation components
- Authentication requirements
- UI structure (sidebar vs header style)

### Pages

Pages represent the actual content for each route and follow a consistent pattern:

1. **Metadata Generation**: Using `generateMetadata()` for SEO and page titles
2. **Content Structure**:
   - Page headers with titles and descriptions
   - Page body containing the main content
3. **i18n Implementation**: Wrapped with `withI18n` HOC

## Creating a New Page

### 1. Define the Page Structure

Create a new file within the appropriate route folder:

```tsx
// app/home/(user)/my-feature/page.tsx
import { PageBody } from '@kit/ui/page';
import { Trans } from '@kit/ui/trans';

import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
import { withI18n } from '~/lib/i18n/with-i18n';

// Import components from the _components folder if needed
import { MyFeatureHeader } from './_components/my-feature-header';

export const generateMetadata = async () => {
  const i18n = await createI18nServerInstance();
  const title = i18n.t('account:myFeaturePage');

  return {
    title,
  };
};

function MyFeaturePage() {
  return (
    <>
      <MyFeatureHeader
        title={<Trans i18nKey={'common:routes.myFeature'} />}
        description={<Trans i18nKey={'common:myFeatureDescription'} />}
      />

      <PageBody>
        {/* Main page content */}
      </PageBody>
    </>
  );
}

export default withI18n(MyFeaturePage);
```

- Authentication is enforced already in the middleware
- Authorization is normally enforced by RLS at the database level
- In the rare case you use the Supabase Admin client, you must enforce both authentication and authorization manually

### 2. Create a Loading State

```tsx
// app/home/(user)/my-feature/loading.tsx
import { GlobalLoader } from '@kit/ui/global-loader';

export default GlobalLoader;
```

### 3. Create a Layout (if needed)

If the feature requires a specific layout, create a layout file:

```tsx
// app/home/(user)/my-feature/layout.tsx
import { use } from 'react';

import { UserWorkspaceContextProvider } from '@kit/accounts/components';
import { Page, PageNavigation } from '@kit/ui/page';

import { withI18n } from '~/lib/i18n/with-i18n';
import { loadUserWorkspace } from '../_lib/server/load-user-workspace';

// Import components from the _components folder
import { MyFeatureNavigation } from './_components/my-feature-navigation';

function MyFeatureLayout({ children }: React.PropsWithChildren) {
  const workspace = use(loadUserWorkspace());

  return (
    <UserWorkspaceContextProvider value={workspace}>
      <Page>
        <PageNavigation>
          <MyFeatureNavigation workspace={workspace} />
        </PageNavigation>

        {children}
      </Page>
    </UserWorkspaceContextProvider>
  );
}

export default withI18n(MyFeatureLayout);
```

## Layout Patterns

### 1. User Workspace Layout

For pages in the personal account context, use the user workspace layout pattern:

```tsx
import { use } from 'react';

import { UserWorkspaceContextProvider } from '@kit/accounts/components';
import { Page } from '@kit/ui/page';
import { withI18n } from '~/lib/i18n/with-i18n';
import { loadUserWorkspace } from './_lib/server/load-user-workspace';

function MyLayout({ children }: React.PropsWithChildren) {
  const workspace = use(loadUserWorkspace());

  return (
    <UserWorkspaceContextProvider value={workspace}>
      <Page>
        {/* Navigation components */}
        {children}
      </Page>
    </UserWorkspaceContextProvider>
  );
}

export default withI18n(MyLayout);
```

### 2. Team Workspace Layout

For pages in the team account context, use the team workspace layout pattern:

```tsx
import { use } from 'react';

import { TeamAccountWorkspaceContextProvider } from '@kit/team-accounts/components';
import { Page } from '@kit/ui/page';
import { withI18n } from '~/lib/i18n/with-i18n';
import { loadTeamWorkspace } from './_lib/server/load-team-workspace';

function TeamLayout({ children, params }: LayoutParams) {
  const workspace = use(loadTeamWorkspace(params.account));

  return (
    <TeamAccountWorkspaceContextProvider value={workspace}>
      <Page>
        {/* Navigation components */}
        {children}
      </Page>
    </TeamAccountWorkspaceContextProvider>
  );
}

export default withI18n(TeamLayout);
```

## UI Components Structure

### Page Components

Break down pages into reusable components:

1. **Page Headers**: Create header components for consistent titling:
   ```tsx
   // _components/my-feature-header.tsx
   import { PageHeader } from '@kit/ui/page-header';

   export function MyFeatureHeader({
     title,
     description
   }: {
     title: React.ReactNode,
     description: React.ReactNode
   }) {
     return (
       <PageHeader
         title={title}
         description={description}
       />
     );
   }
   ```

2. **Feature Components**: Create components for feature-specific functionality:
   ```tsx
   // _components/my-feature-component.tsx
   'use client';

   import { useUserWorkspace } from '@kit/accounts/hooks/use-user-workspace';

   export function MyFeatureComponent() {
     const { user } = useUserWorkspace();

     return (
       <div>
         {/* Component content */}
       </div>
     );
   }
   ```

### Navigation Components

Create navigation components to handle sidebar or header navigation:

```tsx
// _components/my-feature-navigation.tsx
'use client';

import { NavigationMenu } from '@kit/ui/navigation-menu';

export function MyFeatureNavigation({
  workspace
}: {
  workspace: UserWorkspace
}) {
  return (
    <NavigationMenu>
      {/* Navigation items */}
    </NavigationMenu>
  );
}
```

## Layout Styles

Makerkit supports different layout styles that can be toggled by the user:

1. **Sidebar Layout**: A vertical sidebar navigation
2. **Header Layout**: A horizontal header navigation

The layout style is stored in cookies and can be accessed server-side:

```tsx
async function getLayoutState() {
  const cookieStore = await cookies();
  const layoutStyleCookie = cookieStore.get('layout-style');

  return {
    style: layoutStyleCookie?.value ?? defaultStyle,
    // Other layout state properties
  };
}
```

## Best Practices

1. **Server vs. Client Components**:
   - Use Server Components for data fetching and initial rendering
   - Use Client Components ('use client') for interactive elements

2. **Data Loading**:
   - Load workspace data in layouts using server functions
   - Pass data down to components that need it
   - Use React Query for client-side data fetching

3. **Component Organization**:
   - Place feature-specific components in a `_components` folder
   - Place feature-specific server utilities in a `_lib/server` folder
   - Place feature-specific client utilities in a `_lib/client` folder

4. **i18n Support**:
   - Always use `withI18n` HOC for pages and layouts
   - Use `<Trans>` component for translated text
   - Define translation keys in the appropriate namespace in `apps/web/public/locales/<locale>/<namespace>.json`

5. **Metadata**:
   - Always include `generateMetadata` for SEO and UX
   - Use translations for page titles and descriptions

6. **Loading States**:
   - Always provide a loading state for each route
   - Use the `GlobalLoader` or custom loading components

7. **Error Handling**:
   - Implement error.tsx files for route error boundaries
   - Handle data fetching errors gracefully