Documentation
Docs
Introduction
Getting Started
Tutorial: build an app
Core Concepts
Routing
Server-Side Rendering
Mimir, state management
Pages & Layouts
API Routes
Styling & Theming
Building & Deploying
API Reference
Guides
Recipes
FAQ (use cases)
SCSS
You style a rune app by importing stylesheets. Write .scss (or .css) files and import them from your
components; the build compiles the SCSS, bundles it, records it in the manifest, and rune injects it into
every page's <head> on the server-rendered first paint. There is no compileSass call to wire up and no
<style> string to assemble by hand.
How it works
Import the stylesheet once, typically from your root layout so it applies everywhere:
That is the whole wiring. A plain import "./x.scss" is a side-effect import: it ships that stylesheet to
every page that includes it. Plain .css files work the same way, the Sass step is simply skipped.
Hot reload under ekko dev
ekko dev watches your stylesheets. Editing a .scss/.css file reconverts and rebundles it and reloads
the page automatically, with no server restart. (A production build, ekko build --client, compiles and
hashes the stylesheets into the client output.) See The dev loop.
Component-scoped styles: CSS Modules
For class names that cannot collide, name the file *.module.scss (or .module.css) and use a default
import. You get back a map of your class names to collision-proof scoped names:
Scoping is automatic and per-file (a .button here never clashes with a .button elsewhere), and the scoped
names are computed identically on the server and in the client bundle, so the SSR markup matches hydration
exactly. composes: joins names within the same file. Reach for modules when you want local styles; reach for
a global sheet for design tokens, resets, and typography.
Why a bundled stylesheet (and SSR-first)
The compiled CSS is delivered as a <link rel="stylesheet"> emitted into the server-rendered HTML, so the
page is styled on first paint with no flash of unstyled content, and the stylesheet is content-hashed and
cacheable. (Theme flashing is a separate concern, handled by the no-FOUC script, see
No-FOUC.)
Structure your stylesheet
A typical global.scss:
Everything reads var(--token), so flipping the .dark class restyles the whole app at once. See
Theming.
SCSS features
You get the SCSS you expect, nesting, variables, @mixin/@include, @use/@import of partials, functions
like color-mix (via CSS), and math.
Static CSS and assets
Fonts, images, and any static CSS you do not import go in static/ and are served at your staticPrefix
(commonly /assets). Reference them in your SCSS or markup by that URL:
Generating CSS dynamically (escape hatch)
When you need CSS that is not known at build time (a theming server, tooling), call the
ekko:ssr/css toolchain directly: compileSass, transform, minify, and
cssModules, the same engine the import pipeline uses. For anything authored as a file, prefer the imports
above, they are simpler and give you SSR-first delivery for free.
Next: the theme system, Theming.