Getting started: your first route and island in JSkelet
· 2 min read
JSkelet is a Node framework for content sites: Express routes, .jsk templates compiled at build time, Tailwind CSS, vanilla islands, and an HTML cache. This guide walks the smallest loop that proves the architecture — without requiring React, without a client router, and without freezing your content in a static export.
What you should have after an hour
- A public
GETthat returns complete HTML - A layout with metadata hooks
- One presentational component as an HTML-string helper
- One island that mounts on visibility
- A sense of where CSS, client entries, and routes live
If those pieces click, the rest of the docs (cache, migrate, deploy) build on the same mental model.
Scaffold and mental map
npx jskelet init (or your preferred create flow) lays down routes/, views/, client/, styles/, and jskelet.config.mjs. The important split:
- Routes decide HTTP, cache policy, and page data.
- Views decide markup (
.jskpages/partials +views/componentshelpers). - Client decides behaviour (
entries+islands). - Styles decide global and page sheets (Tailwind v4 with explicit
@source).
There is no app/ directory inventing nested layouts for you. Clarity beats magic when you are teaching a team.
Your first cached page
Register a handler with route(). Return a view, metadata, and data. For public brochure pages, pass a revalidate window so the HTML cache can keep warm copies.
The controller should prepare everything the template needs. The .jsk expression language is intentionally small — formatting and object construction belong in the controller or in a component module, not inline in the template.
Your first island
- Add
data-island="counter"(or similar) in the template. - Export
mount(element, props)fromclient/islands/…. - Register a dynamic import in
client/entries/main.jsviaregisterAll. - Call
start().
The island should enhance something that already makes sense in HTML. A counter that starts from a server-rendered value is a teaching toy; a theme toggle that respects a <html class> set before paint is a real product pattern.
Prefer default (visible) hydration unless the control is global chrome.
Components without JSX
Named exports under views/components/** become PascalCase tags in .jsk. They return HTML strings using jskelet/html helpers (esc, attrs, cn). That is how you share buttons, cards, and docs chrome without a React tree.
Config habits that save pain later
- Put public browser values in
clientEnv— never secrets. - Keep
@sourcepaths aligned with directories that contain class names. - Use
private: truethe moment a route needs a session. - Read framework docs for middleware order before inventing a parallel stack.
What “done” looks like for a first vertical
One locale, one layout, one public page, one island, one stylesheet path, and a deploy that runs jskelet build. From there you add docs, blog, and admin surfaces with the same contracts — not a second framework beside JSkelet.
Comments
No comments yet.