CHART/DOCS/PROJECT STRUCTURE

Project structure

Pages map to routes. Everything else is a convention.

Server pages live under pages/. Client components can live anywhere else - components/ and islands/ are conventions, not rules.

Routes from files

The directory tree maps directly to URL routes:

File Route
src/pages/Index.tsx /
src/pages/About.tsx /about
src/pages/blog/Post.tsx /blog/post
src/pages/docs/Install.tsx /docs/install

Nesting is unlimited and compiled to depth-correct relative paths, so a page at /blog/post loads its runtime, islands, and stylesheets from ../-levels - never from the root, and never with an assumption about where the site is mounted.

Rule: every component file must begin with a // @runsOn server, // @runsOn client, or // @runsOn api directive. This is the framework's only mechanism for the server/client/api boundary - there is no inference from filenames or import sites.

A server page declares page-level metadata by assigning a raw HTML string to a const head at the top of the component body. It is injected verbatim into the built page's - no parsing, no escaping, no transformation. Use it for </code>, <code><meta></code>, Open Graph tags, or structured data: </p> <pre class="code"><code>const head = '<title>My Page';

The name is fixed: head. A page that declares no head gets only the import map and its CSS links.

Conventions, not rules

  • pages/ - the only directory with routing meaning for pages.
  • api/ - top-level directory mapped to /api/* HTTP routes.
  • components/ - server-rendered building blocks imported by pages.
  • islands/ - client components hydrated at client:hydrate call sites.
  • middleware.ts - optional; one request gate for the whole site (project root).
  • src/site.css - a shared stylesheet imported by a component every page renders.

The compiler walks each page's component tree to find its islands and stylesheets, so files outside pages/ are only included when a page actually uses them.