# Templates Where template files live, how a template is declared, and how a parent passes content into a child with slots. ## Files A page is a folder: ```text app/pages/home/ index.ts # route handler template.ehtml # templates, handlers, rpc, interfaces, LiveTables style.css # page styles test.ts ``` Everything the page needs starts in `template.ehtml`: its templates, event handlers, helpers, interfaces, `@rpc` functions, LiveTables, and Channels. Both siblings import from it by name. ```ts // index.ts import home, { posts, Post } from "./template"; // test.ts import { normalize, Post } from "./template"; ``` An `.ehtml` file is a module like any other. The `` template is its default export, other templates are named exports, and so is any TypeScript declaration you mark `export`. Add a sibling `services.ts` when the markup gets hard to find in `template.ehtml`, and move the `@rpc` functions and interfaces there first. That is a readability call on one file, not a size threshold, and most pages never reach it. Move to `app/shared/services/.ts` when a second consumer appears: a second page, a job, an email, a route in `app/routes/`. One page plus one job counts; one page on its own does not. Shared templates go in `app/shared/templates/`. ## Reusing a template Two pages that render the same UI with different values want one template, not two copies. Sign in and sign up are the usual pair: the same field stack, the same error line, different labels and a different call on submit. ```bash elements create template auth-form -attrs='title: string, action: string' ``` That writes `app/shared/templates/auth-form/{index.ehtml, style.css}`, and both pages import it. Extract when the shared part is most of the markup and the differences fit in attributes. Do not extract two elements that happen to look alike today, and do not add a `variant` attribute that switches between two layouts with nothing in common. A template whose body is one big `e:switch` on its own attribute is two templates. The same call makes page-local templates. `elements create template ui/button` nests under `app/shared/templates/ui/`, and a template used by one page can just be a second top-level tag in that page's `template.ehtml`. ## Templates **A template name must start with a capital letter.** ``, ``, ``. This is enforced, not a style preference: a call site reads a capitalized tag as a template and a lowercase one as a native HTML element, so a template declared `` could never be called. Declaring one is an error, "The template name `` must start with an uppercase letter." `` is the one exception, and a special reserved name. Marking a template as `` makes it the default export of the file and turns it into an HTML page. Other named templates are named exports. A page's CSS is every stylesheet reachable by import from its `` template: the template's own imports, then each child template's imports, depth first. The imports live in the CSS files, so a page's `style.css` is where the shared baseline gets `@import`ed. A rule written in another page's `style.css` is not in that set, which means markup copied from one page does not bring that page's styles with it. Scripts bundle by the same walk. ```ts import html from "./template"; import html, { Footer } from "./template"; // page + named template ``` Import a template extensionless: `./template` resolves to `template.ehtml`. Templates compose like function or class declarations: define them in one file or split across multiple files. A template name is a type as well as a value, so it cannot be shared with a type declared beside it. An `interface Item` and an `` template in the same file are two declarations of `Item`, and the compiler reports a duplicate identifier on both. Give the data a different name from the template that renders it (`Message` and ``, or `ItemData` and ``). ## Slots Slots are how a parent passes content into a child template. The child declares `` placeholders; the parent fills them. The syntax is standard html. ```ehtml default content
footer content
default footer ```