GioJSdocs
On this page

File Conventions

The file and folder names GioJS gives a meaning to: route files in app/, special folders, metadata files, and the files in the project root.

text
my-app/
  app/
    layout.tsx          the document and the layout of every page
    page.tsx            /
    not-found.tsx       404 page (also for unmatched URLs)
    error.tsx           500 page and error boundary
    globals.css         imported by layout.tsx
    sitemap.ts          /sitemap.xml
    (site)/             route group: no URL segment
      layout.tsx
      blog/
        page.tsx        /blog
        loading.tsx     Suspense fallback for /blog/...
        [slug]/page.tsx /blog/:slug
      _components/      private folder: never routed
    api/posts/route.ts  GET/POST /api/posts
  public/               static files at the site root
  middleware.ts         redirects, rewrites, headers, guards
  gio.config.ts         Node plugins
  gio.toml              server settings
  .env.local            environment variables
  .gio/                 generated: builds, caches, route types

Route files

These names have a meaning in app/ and every folder below it, except private folders. Component files may be .tsx, .jsx or .js (in that order of precedence); route may be .ts or .js.

FilePurpose
page.tsxMakes a folder a route: the UI for its URL
layout.tsxWraps the pages in its folder and below; the root one renders the document
route.tsHTTP handlers (GET, POST, PUT, PATCH, DELETE), Server-Sent Events and a WebSocket handler
loading.tsxSuspense fallback for its folder and below, streamed first while the content suspends
error.tsxThe 500 page when a render fails on the server, and a client error boundary once hydrated
not-found.tsxThe 404 page for notFound() at or below its folder; the one in app/ also answers unmatched URLs and is exported to 404.html

Pages and layouts may also export metadata or generateMetadata for their <head> tags, and pages a few more values: see Page Exports.

error.tsx, not-found.tsx and loading.tsx may sit in any folder, including route groups and dynamic folders, and the nearest one at or above a page wins. Inside a folder they nest like this:

text
<Layout>                 layout.tsx
  <ErrorBoundary>        error.tsx   - catches everything below, not the layout above it
    <Suspense>           loading.tsx - fallback while anything below suspends
      ...the next folder's layout, or the page

So an error.tsx never handles errors from the layout in its own folder - the error.tsx of a parent folder does. See Error Handling and Layouts & Pages.

Folder conventions

FolderEffect
[id]Dynamic segment - matches exactly one URL segment (/posts/:id)
[...slug]Catch-all - one or more segments; params.slug is 'a/b'
[[...slug]]Optional catch-all - zero or more segments, so it also matches the parent URL (params.slug is '')
(group)Route group - organizes files and scopes a layout without adding a URL segment
_folderPrivate - never routable; for colocated components and helpers

Layouts apply by folder ancestry: a page gets the layout.tsx of every folder from app/ down to its own, groups and dynamic folders included. When several routes match a URL the most specific wins (see matching order), and two files that answer the same URLs stop startup with an error naming both.

Param names may not start with . or contain ?, : or *; a folder like [...slug?] or [id?] fails startup instead of quietly changing what the route matches.

Metadata files

Only at the root of app/, as .ts or .js. The default export is the data, or a function returning it; export const revalidate sets how long the output is cached (default 3600 seconds).

FileServes
sitemap.ts/sitemap.xml from [{ url, lastModified, changeFrequency, priority, alternates }]
robots.ts/robots.txt from { rules, sitemap, host }
manifest.ts/manifest.webmanifest from a Web App Manifest object

A public/ file with the same name wins (the server warns at startup); a page or route.ts at the same URL fails startup.

Styles

FilePurpose
Imported .cssBundled per route, content-hashed, linked in <head>
*.module.cssLocal class names, imported as a map
app/**/*.cssAlso served at their path inside app/ (legacy)

Project root files

File or folderPurpose
public/Static files, served at the site root and under /public/
middleware.tsRedirects, rewrites, headers and guards, enforced by the Rust server
gio.config.tsNode plugins
gio.tomlEvery server setting
.env, .env.local, ...Environment variables loaded at startup
.gio/Generated: client bundles, stylesheets, caches, route types

Not supported

GioJS follows the App Router's names where it has the feature. These Next.js conventions have no GioJS equivalent; a file or folder with one of these names is an ordinary module or an ordinary URL segment:

Next.jsIn GioJS
global-error.tsxNot supported. app/error.tsx covers every page; an error in the root layout itself gets the built-in error page.
template.tsxNot supported. Layouts keep their state across navigations; key a subtree yourself to reset it.
default.tsxNot supported (it belongs to parallel routes).
Parallel routes (@slot folders)Not supported. @slot is a literal URL segment.
Intercepting routes ((.)photo, (..)photo, (...)photo folders)Not supported. Such a folder is a literal URL segment. A folder named only (.) or (..) is a route group.
forbidden.tsx, unauthorized.tsxNot supported. Answer 401/403 with a Response from a route.ts or a page action, or redirect with a guard.
opengraph-image.tsx, icon.png, apple-icon.pngNot supported. Use the openGraph and icons metadata fields with files from public/.
instrumentation.tsNot supported. Use a plugin's onStartup in gio.config.ts.
A src/ folderNot supported. app/ sits in the project root. GIO_APP_DIR can point at another folder, but public/, gio.toml and the other root files then belong next to that folder.
Route segment config (dynamic, runtime, ...)Different: see Page Exports.