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)
Asgard integration
@ekko/asgard is the EkkoJS component suite: buttons, inputs, data tables, dialogs, a docking system, a
Markdown renderer with syntax highlighting, and a docs shell. It pairs naturally with rune, the docs site
you are reading is a rune app rendering Asgard's MarkdownRenderer and TreeView inside a docs shell. This
page shows how to wire it in.
Add it
Declare it in ship in ekko.json:
Then import components and the theme:
Theming Asgard
Asgard components read a theme object (not your CSS variables). Wrap a subtree in ThemeProvider with a
theme:
To match your site's light/dark choice, drive the ThemeProvider from your theme atom:
This works, but on its own it means maintaining a SCSS palette and an Asgard Theme object and keeping
them in sync by hand — the source of the classic "themed buttons, white page" bug. The next section
removes the duplication.
Theme your page from the same theme: <ThemeCssVars />
ThemeProvider themes Asgard components, not your own markup (the Task-299 trap). Instead of a second
SCSS palette, drop <ThemeCssVars /> inside the provider — it mirrors the active Asgard theme onto
:root as --ekko-* CSS custom properties, so your own CSS themes from the same object and re-themes on
every toggle. Render it once in the root layout:
Then style your page from those variables — including the page background, which is exactly what the signoff validator checks (a fully themed page, not a white page with themed widgets on top):
Common tokens: --ekko-background-{primary,secondary,tertiary,elevated}, --ekko-text-{primary,secondary},
--ekko-border-{default,focus,divider}, --ekko-accent-{primary,secondary}. Need the map server-side?
themeToCssVars(theme) returns it; applyThemeToRoot(theme) is the imperative escape hatch.
No-FOUC: apply the dark/light class before first paint with the no-FOUC script from Dark mode, and keep the choice in the
themeAtom(it survives navigation).<ThemeCssVars />re-applies the matching--ekko-*values on the client whenever the atom changes.
See Theming for the atom + toggle, and Dark mode for the full light/dark recipe.
Rendering Markdown (how these docs work)
Asgard's MarkdownRenderer turns a Markdown string into themed elements with syntax-highlighted code:
Note onLinkClick: routing Markdown links through router.navigate keeps doc-to-doc navigation on the
client (no reload), the same rule as everywhere else (see Navigation).
A docs shell
The sidebar nav, breadcrumb, and content layout you see here are built from Asgard's TreeView (the nav),
Breadcrumb, and SDiv (themed scroll regions), wrapped in a ThemeProvider. The pattern: a DocsShell
component takes a nav tree and the current page's content, renders the sidebar + content + table of contents,
and is itself wrapped in the site-aware theme. You feed it the generated docsData (nav + per-page markdown)
from your content pipeline.
SSR considerations
Some Asgard components read the DOM on render (canvas-based ones, drag-and-drop). Render those client-only
(after mount) and show a placeholder during SSR, the same mounted pattern you use for any non-SSR-safe
component:
Prose, buttons, inputs, and the Markdown renderer SSR fine; gate only the genuinely DOM-dependent ones.
When to use Asgard vs plain SCSS
- Plain SCSS , content sites, marketing, simple forms. Lighter, full control, no component theme to sync.
- Asgard , dashboards and docs that want data tables, dialogs, trees, a docking workspace, or a Markdown
renderer out of the box. You trade the two-declarations sync for a lot of finished UI.
Next: eliminating the theme flash, No-FOUC.