Directory structure
Silgi reads these folders and files by name; everything else is yours. silgi init writes the ones it needs and you add the rest.
| Path | What it holds |
|---|---|
app/pages/ | Pages. A file is a route: about.ts is /about, blog/[slug].ts is /blog/:slug, [[...path]].ts matches every path. |
app/layouts/ | Layouts. default.ts wraps every page. |
app/middleware/ | Route middleware that runs before a page renders. |
app/plugins/ | App plugins, run in file name order. A .client.ts or .server.ts suffix limits a plugin to one side. |
app/app.ts | The root component. It wraps every layout and page. The extension follows the library: app.tsx, app.vue, app.svelte. See Routing. |
app/error.ts | The error page. Without it the library's default error page is used. |
app/app.config.ts | The app config, merged over appConfig in the config. It is public. |
app/env.ts | defineEnv({ … }): the environment variables the app reads, validated and typed. See Environment. |
app/components/ | Components used without an import, with components: true. See Modules. |
app/composables/, app/utils/ | Their exports are auto-imported in app files with imports.autoImport. See Modules. |
app/graphql/ | The app's own GraphQL operations, *.graphql. See GraphQL. |
server/index.ts | The door of the server. Its named exports are the handlers pages can call, and its default export, defineServer({ plugins, middleware, handlerMiddleware }), is the rest. See Server. |
server/** | Any other file under server/ is yours: handler definitions, helpers, anything. Folders mean nothing, and a file is reachable only through server/index.ts. |
server/utils/ | Their exports are auto-imported in server files with imports.autoImport. See Modules. |
server/graphql/ | The GraphQL schema (*.graphql), resolvers (*.resolver.ts) and context.ts, with server.graphql. See GraphQL. |
shared/ | Code for both sides, imported through the #shared alias. Nothing in it is auto-imported. |
public/ | Static files, copied into the build as they are, except dotfiles and dot-directories (.env, .git/), which are skipped with a warning; only public/.well-known/ is published. See Assets. |
silgi.config.ts | The config. |
.silgi/ holds build files and .output/ holds the build. Both are generated and belong in .gitignore.
Pages and layouts
A page and a layout with the html library:
import { Link } from "@silgi/html";
import type { HtmlProps } from "@silgi/html";
export default function DefaultLayout({ children }: HtmlProps): string {
return `<div>
<header>${Link({ to: "/", children: "Home" })} ${Link({ to: "/about", children: "About" })}</header>
${children}
</div>`;
}
A page that needs a value before it renders has a load file next to it, with the same name and a .load.ts ending. blog/[slug].load.ts loads the data for blog/[slug].ts. It runs on the server for the first render and in the browser for every navigation, and it calls handlers for anything that lives on the server. See Data.
import type { Load } from "silgi/app";
export const load = (({ params }) => ({ title: `Post ${params.slug}` })) satisfies Load;
Server
A handler is defineHandler({ … }) in any file under server/. What a page calls, and what a URL answers, is what server/index.ts exports. A handler with a route answers that URL; this one answers GET /api/hello:
import { defineHandler } from "silgi/server";
export const hello = defineHandler({
route: "/api/hello",
method: "GET",
handler() {
return { message: "Hello" };
},
});
server/index.ts exports it with export { hello } from "./hello.ts";. A file name carries no path and no method; the definition says both. Server files are TypeScript: server/index.ts is .ts, and so are the files that define handlers.
Styles
Importing a .scss, .sass, .less or .styl file fails the build with app/main.scss: Sass needs a CSS preprocessor plugin; install @silgi/css and sass (06 §2) (Less and Stylus name their own tools), unless a module plugin compiles the file. Compile the file to CSS before the build and import the .css file, or add a module whose plugin compiles the extension.
bunx sass app/main.scss app/main.css
Assets
An image, font, audio, video or PDF file that app code imports becomes a hashed asset URL. import logo from "./logo.png" gives a string such as /_silgi/logo-49779094.png, the same in the server HTML and in the browser, under app.buildAssetsDir and app.baseURL. The build copies the file into .output/public/. Files in public/ are not imported: they are served as they are, at the path they have in the folder.