Skip to main content
A page is a full screen that belongs to your app. It has its own URL, shows up in the Apps section of the sidebar, and gets the whole content area to itself. Use pages for dashboards, overviews, and anything that isn’t about one record. For UI tied to a single record, use a record tab instead. Pages are defined with Extensions.definePage and laid out with Grid, Card and Stack. For a worked example, see Building app pages.

File convention

Pages live under src/app/pages/. Each page is a folder holding a page.tsx that default-exports a definePage call:
The folder name is the page’s slug, and the slug is the last segment of its URL:
So src/app/pages/dashboard/page.tsx is served at /{workspaceSlug}/apps/{appSlug}/dashboard.

Discovery rules

  • Page folders sit directly inside src/app/pages/. Pages do not nest: src/app/pages/reports/weekly/page.tsx is a build error.
  • Folder names follow the same format as extension ids: lowercase kebab-case, starting with a letter, containing only lowercase letters, digits and single hyphens, at most 64 characters.
  • Each folder contains exactly one definition file, page.tsx or page.ts. Other files in the folder are ignored by discovery; import them from page.tsx like any other module.
  • The definePage(...) call must be the file’s default export directly.
Pages are the one entry point not discovered through extension.tsx. Everything else about app structure still applies.

Example

src/app/pages/dashboard/page.tsx
Once a workspace installs an app with at least one page, the app appears in the Apps section of the sidebar. Clicking the app row opens its first page, where pages are ordered alphabetically by slug. Apps with more than one page expand to list them. Apps without pages get no sidebar entry.

Loading

Page can suspend. While it does, Attio shows the page skeleton with the real header already in place: the name comes from your page definition, so it renders before your code has booted. Add your own React.Suspense boundaries inside the page when one slow section shouldn’t hold up the rest.

Errors

If Page throws, Attio renders an error state in place of that page. Nothing else about your app is affected: record actions, widgets, other pages and tabs keep working.

Build errors

The CLI checks pages on every attio dev and attio build. The build fails when:
  • A folder contains both page.ts and page.tsx. Keep exactly one.
  • A page.tsx sits directly in src/app/pages/ rather than in a subfolder.
  • A folder name is not a valid slug (see the format above).
  • A page.tsx is nested more than one folder deep.
  • The file doesn’t default-export an Extensions.definePage() call.