.slurp files. There is no config file, no
scaffolding command, and no manifest the compiler reads. slurp build walks the
tree it is given and writes a mirror of it.
This page uses examples/basic-theme from the repository as the worked example.
Building it
The output tree mirrors the input tree
There is no rewriting. A.slurp file keeps its relative path and changes
extension, so pages/index.slurp becomes dist/pages/index.html, and
pages/ stays in the URL unless whatever serves the site strips it.
Special directories
components/ and layouts/ are compiled and checked but never written out. A
component or a layout rendered on its own is a fragment rather than a document,
and a layout in particular comes out carrying literal <slot> elements, so
emitting them would fill the output with files nothing can serve.
They are still compiled. A syntax error, a security violation or an unknown
filter in a component that no page imports yet still fails the build.
pages/ is a convention, not a rule
The compiler does not require it. A lone index.slurp at the root builds to
dist/index.html, which is what the Quickstart does.
slurp-dev and the hosts that embed Slurp route an extensionless request path
into it, resolving / to pages/index.html and /product to
pages/product.html or pages/product/index.html. Anything with a file
extension is served straight from the theme root as an asset.
slurp build also prints a warning when it emits no pages at all, and that
warning names pages/:
Static assets are copied verbatim
Every non-.slurp file in the input tree is copied to the output at the same
relative path. There is no assets directory and no manifest: CSS, images, fonts
and JavaScript go wherever the markup references them, and they land at the same
path.
README.md and .gitignore appear in the listing above. If you do
not want a file published, keep it out of the input tree.
The copy walk skips the same directories the compile walk does:
- any directory whose name begins with
., node_modules,distandtarget, by name, wherever they appear,- the
--outputdirectory itself, so a build cannot copy its own output back into a nested copy of itself, - symlinks, which are never followed.
dist and target are excluded by NAME, not because they happen to be the
defaults. A directory you genuinely want published cannot be called either.The globals file is input, not an asset
--globals seeds the render context with values a template must resolve at
compile time. It is read and not copied to the output, even though it sits
inside the input tree in the obvious layout. An earlier version of the copy walk
shipped it to production at a guessable path.
Commit the globals file. It holds no secrets, and without it a fresh clone builds
with those values empty. A build-time secret belongs in .env, never here.
How imports resolve
An@ path is the file’s path from the input root, without the extension.
@components/ui/Card resolves components/ui/Card.slurp, so nesting works with
no configuration. The local name is the last path segment, or the alias in
using "./Card" as Renamed.
.gitignore
.gitignore suited to a theme into the current directory. It refuses
rather than clobbering an existing one, and prints the three options:
dist/, node_modules/, .env and editor files. The
rest of the file names what must not be ignored.
The globals file and a theme.json manifest, if you have one, are committed for
the same reason: they are inputs, not build artifacts.
Next
Writing pages
File-based routing, page data, and output paths.
Components
Props, slots, and imports.
Middleware
The
--middleware flag, scope rules, and redirects.CLI
Every subcommand and flag.