JSDA

JSDA-Kit — Build the Web with Pure JavaScript

A comprehensive toolkit for Static Site Generation, Server-Side Rendering, and dynamic servers — powered by standard ESM modules instead of framework magic.

npm GitHub

The Idea

Most web frameworks demand you learn their way of doing things — proprietary file conventions, custom compilers, opaque build pipelines. JSDA-Kit takes the opposite approach: your JavaScript ESM modules are your web assets. A file named index.html.js exports a string — and that string becomes your HTML page. The same pattern works for CSS, SVG, Markdown, JSON, or anything else text-based.

This is the JSDA (JavaScript Distributed Assets) concept brought to life: PHP-like simplicity with modern JavaScript power. No template engines, no custom syntax, no black-box build steps. Just modules, template literals, and the full Node.js ecosystem at your fingertips.

// src/static/index.html.js → dist/index.html
import { getPageData } from './data.js';

const page = await getPageData();

export default /*html*/ `
<!DOCTYPE html>
<html>
<head><title>${page.title}</title></head>
<body>
  <h1>${page.heading}</h1>
  <app-widget></app-widget>
  <script type="module" src="/app/index.js"></script>
</body>
</html>
`;

No routing config, no manifest, no plugin chain — the folder structure is the routing.

Killer Features

ESM-Native Asset Pipeline

Every .html.js, .css.js, .svg.js file is a standard JavaScript module that exports a string. You get loops, conditionals, async data fetching, and imports — not a limited template engine. Convention-based file mapping (src/static/about/index.html.js → dist/about/index.html) eliminates routing configuration entirely.

Default exports can also be functions for dynamic generation: sitemaps, RSS feeds, config-driven page sets — all from the same pipeline.

Isomorphic Web Components

JSDA-Kit integrates Symbiote.js for a three-layer rendering model:

  • Server-only — rendered once during SSG/SSR, no client JS shipped
  • Client-only — standard browser Web Components
  • Isomorphic — set isoMode = true and the same component auto-detects its environment: SSR on the server, hydration on the client
import Symbiote, { html, css } from '@symbiotejs/symbiote';

class AppGreeting extends Symbiote {
  isoMode = true;
  greeting = 'Hello, World!';
}

AppGreeting.template = html`
<h2 ${{textContent: 'greeting'}}></h2>
`;

AppGreeting.rootStyles = css`
app-greeting {
  display: block;
  padding: 1em;
}
`;

AppGreeting.reg('app-greeting');

One component definition. Server renders it with Declarative Shadow DOM (optional, only if needed). Browser hydrates it seamlessly. No 'use client' / 'use server' annotations, no separate server components API, no hydration mismatches possible.

Three-Tier SSR Imports

SSR component resolution is layered for maximum flexibility:

  1. Global imports in project.cfg.js — components available to every page
  2. Per-endpoint ssrImports exports in individual .html.js files — page-specific components
  3. Programmatic wcSsr() API — full control when you need it

The SSR loader automatically resolves export *, re-exports, and side-effect imports from barrel files — no manual registration boilerplate.

Trusted Types & CSP

Pass a nonce to SSR and all inline <style> tags get the nonce attribute automatically — enabling strict Content Security Policy without template hacks.

Smart Static Site Generation

JAMStack-ready SSG where source folder structure maps directly to output. The watcher mode (npx jsda ssg) rebuilds on file changes during development. Deploy the dist/ folder to any static hosting as-is — GitHub Pages, Cloudflare Pages, S3, or your own Nginx.

esbuild-Powered Build

JS and CSS bundling with tree-shaking, ESM output, and automatic tagged template minification — html and css tagged literals are minified inside bundles while untagged templates stay untouched. HTML, CSS, and SVG assets are also minified by default via @minify-html/node.

Route-Based SSR Server

A built-in dynamic server with a clear pipeline:

Request → Route Lookup → Data Injection → SSR → Minification → Response

Routes are a simple JS object mapping paths to .html.js modules. Custom hooks let you inject data per-route (getDataFn) or resolve routes dynamically (getRouteFn) — enabling i18n, A/B testing, and user-specific content with zero framework overhead.

In-memory response caching is enabled by default with URL-level granularity and per-path excludes.

Automatic Import Maps

JSDA-Kit generates <script type="importmap"> from your package.json dependencies with configurable CDN schemas, adds <link rel="modulepreload"> for critical modules, and supports optional polyfills — all automatically.

Isomorphic Utilities

A set of cross-environment helpers that work in both Node.js and the browser:

  • md2html() — Markdown to HTML with syntax highlighting and automatic heading IDs
  • applyData() — template token replacement with customizable delimiters
  • getHash() — SHA-1 hex via Web Crypto (browser) or Node.js crypto

Why Not Something Like Next.js?

If you've grown tired of fighting opaque framework complexity, JSDA-Kit offers a radically different path:

JSDA-KitNext.js
PhilosophyYou control everything — ESM modules are your assetsThe framework controls everything
Component modelW3C Custom Elements — zero runtime lock-inReact-only — components don't work outside React
SSR granularityPer-component isoMode — mix rendering strategies on the same pagePer-page 'use client' / 'use server' boundaries
Dependencies7 production deps, ~50 MB node_modules700+ transitive deps, 300+ MB node_modules
Runtime weight0 KB static; ~7 KB gzipped for interactive~44 KB gzipped React + framework chunks
Build speedesbuild — fast, no config, no plugins to debugTurbopack/webpack — complex when it goes wrong
Codebase~2,500 LOC — readable, no black boxes~300,000+ LOC — good luck tracing a build issue
Vendor lock-inNone — plain files, deploy anywhereVercel-optimized — self-hosting has rough edges
ConfigurationSingle project.cfg.js, deep-mergeablenext.config.js + App Router + caching rules + middleware
CI speedSeconds to install, seconds to buildMinutes for npm install alone

JSDA-Kit handles projects of any complexity — from a single landing page to a full-scale web application. The difference is: you stay in control.

Quick Start

npm install jsda-kit

# Scaffold a new project
npx jsda scaffold

# Start dev server
npx jsda serve

# Start SSG watcher (dev mode)
npx jsda ssg

# Build for production
npx jsda build

The scaffold command generates a complete runnable project: folder structure, config, sample components (server-only, client-only, isomorphic), routes, a static SSG page, CSS design tokens, and dev tooling configuration.

Zero-config start — works out of the box. All settings have sensible defaults. A single project.cfg.js is deep-merged with defaults; override only what you need.

Architecture Highlights

JSDA-Kit stands on a few surprisingly powerful architectural decisions:

Convention over configuration, literally. The file name is the asset type. The folder path is the route. The module export is the output. There is no separate routing layer, no manifest, no plugin registry. This makes the entire system predictable and debuggable — in ~2,500 lines of code.

The ESM module as the universal unit. Every asset — HTML page, CSS stylesheet, SVG icon, Markdown article — is a JavaScript module. This means you can import one asset into another, compose pages from distributed parts, fetch data asynchronously, and publish reusable assets as npm packages with semantic versioning. Web assets become first-class citizens of the JavaScript ecosystem.

Distributed composition. Since every asset is an ESM module, you can import components from CDN endpoints, compose applications from independently deployed micro-products, and cache results at middleware boundaries. This is the natural evolution of micro-frontends — without the framework overhead.

Platform-native everything. Custom Elements for components, importmap for dependency resolution, Declarative Shadow DOM for SSR with native isolation layers, template literals for templating, JSDoc for types. Every choice leans on what the platform already provides rather than duplicating it.

Ecosystem

JSDA-Kit is part of a broader JSDA ecosystem — lightweight, interoperable tools that follow the same philosophy:

JSDA Manifest npm GitHub Symbiote.js Cloud Images Toolkit Immersive Media Spots

Open Source

JSDA-Kit is released under the MIT license. Contributions, feedback, and stars on GitHub are always welcome.

Free hosting friendly — the light CI pipeline fits comfortably within the free tiers of GitHub Pages or Cloudflare Pages. No paid plan required for most projects.

11.12.2025
JSDA is very simple
Why JSDA is the best way to build web apps
30.07.2025
AGI: Three Parts
Let's talk about it before singularity
14.12.2024
Web Images: The Ultimate Solution
How to manage and publish your web media like a pro?
14.10.2024
AUTOBOX v1
History of equipment creation
14.10.2024
ComplexScan
Hardware development is always interesting
7.10.2024
PhotoPizza
From the idea to the Open Source DIY Project
28.09.2024
It was really possible?
Symbiote.js as an answer to many questions
17.09.2024
Smart HTML-tags
Simple recipe with the Artificial Intelligence
26.08.2024
AI as a Platform
New risk for our jobs or new opportunities?
10.05.2024
The path of Full Stack
How to be efficient in multiple development areas?
25.01.2024
Symbiote VS Lit
David and Goliath: differences, pros and cons...
18.01.2024
Symbiote.js 2.x
The new major version is released. Let's see what's new...
01.01.2024
Japanese Netsuke in 3D
History + Art + Technology: What's the result?
RND-PRO.com © 2026