Skip to content

← Back to the blog

Getting started: your first route and island in JSkelet

· 2 min read

Abstract terminal and route folders for getting started with JSkelet

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 GET that 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 (.jsk pages/partials + views/components helpers).
  • 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

  1. Add data-island="counter" (or similar) in the template.
  2. Export mount(element, props) from client/islands/….
  3. Register a dynamic import in client/entries/main.js via registerAll.
  4. 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 @source paths aligned with directories that contain class names.
  • Use private: true the 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.

Leave a comment

Comments are held for moderation before they appear.