Building modern web apps often means choosing between SPAs or traditional MPAs. I wanted a simpler, faster, and more flexible approach that keeps HTML as the source of truth, allows mixing server-rendered and client-only components, and avoids JSX entirely. In this article, I’ll walk you through my HTML-First Multi-Part Application architecture, why I built it, and how it can boost performance and maintainability for your projects.
Motivation
I decided to create my own HTML-First architecture to build something easy, robust, and performance-oriented. By leveraging Sigment’s syntax (e.g., return div("hello")
), components are declared in plain JavaScript without JSX. This produces smaller bundles, faster performance, and a simpler development experience.
Why Not a SPA?
While SPAs are powerful, they aren’t always ideal for larger projects. My Multi-Part Application (MPA) approach allows parts of a page to be server-side rendered (SSR) for SEO, while other parts can remain client-rendered when SEO isn’t critical. This combination provides better SEO, fine-grained performance optimization, and flexibility in choosing which parts of a page require SSR.
Architecture & Concepts
My MPA differs from traditional MPAs because a single page can contain multiple independent parts, each with its own components and lifecycle. Key concepts include:
-
<layout>
: Base template for a page containingdata-part
placeholders. -
data-part
: Marks sections in the layout that can be overridden by page-specific content. -
data-component
: Represents interactive or dynamic components that can be SSR (runAtServer
) or client-only. -
data-paramname
: Allows sending parameters to a component. Example:<div data-component="Product" data-item="laptop"></div>
Inside the component (client-only), you can access it viaprops.item
. ⚠️ Works only for client-only components, not SSR.
This system allows mixing SSR and client-only components seamlessly on the same page.
Layout Example
Here’s an example of a layout file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Site</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link rel="stylesheet" href="/assets/css/index.css">
</head>
<body>
<header>
<div data-component="Header" runAtServer></div>
</header>
<main>
<div data-part="sectionA"></div>
<div data-part="sectionB"></div>
<div data-part="sectionC"></div>
</main>
<footer>
<div data-component="Footer" runAtServer></div>
</footer>
</body>
</html>
Example of Using Layout in a Page
<layout data-layout="/layouts/index.html"></layout>
<description data-description="Hello page description"></description>
<keywords data-keywords="hello,greeting"></keywords>
<script type="module" src="/bundle.js"></script>
<div data-part="sectionA">
<h1>Hello Page</h1>
<p>This page shows the Hello component.</p>
<div data-component="Hello" runAtServer></div>
</div>
Example Components
Hello.js
import 'sigment';
function Hello() {
return div(
div({ class: "mycss" }, "what is your name:"),
input({ type: "text", name: "youname" })
);
}
export default Hello;
Header.js
import 'sigment';
function Header() {
return div({ class: "site-header" },
nav(
a({ href: "/" }, "Home"),
" | ",
a({ href: "/about" }, "About"),
" | ",
a({ href: "/hello" }, "Hello"),
" | ",
a({ href: "/counter" }, "Counter"),
" | ",
a({ href: "/about/1/2" }, "Example with param")
)
);
}
export default Header;
Footer.js
import 'sigment';
function Footer() {
return div("© 2025 Sigment. Built with love for developers");
}
export default Footer;
Components & Features
-
Hello.js: SSR-enabled component. Renders on the server when
runAtServer
is used. - Header.js & Footer.js: Globally loadable SSR components.
Dynamic Props Example: Visiting /about/1/2
automatically injects id=1
and pageid=2
into About.
Multiple Component Instances: Multiple instances (like Hello) can coexist with independent lifecycles and reactive state.
Developer Experience
- Adding a new page/component is simple: create HTML in
src/html
and JS insrc/components
. - Layouts are reusable with
<layout>
anddata-part
. Components can be SSR or client-only. -
Dev mode (
npm run dev
) serves pages as-is without layout transformation for faster iteration. -
Production mode (
npm run build && npm run start
) fully processes layouts and SSR components for clean HTML output.
Benefits
- HTML as source of truth — semantic, clean, and easy to edit.
- Flexible hybrid rendering — SSR where needed, client-only elsewhere.
- Lightweight & modular — small bundle sizes, no JSX.
- SEO & performance friendly — SSR ensures important parts are indexed.
- Fine-grained control — independent lifecycles per component.
Try It Out
Check the project here: HTML-First Architecture Example
git clone https://github.com/sigmentjs/html-first-architecture-example.git
cd html-first-architecture-example
npm install
npm run build
npm run start
Visit /
, /hello
, /about/1/2
, or /counter
to see the architecture in action.
Extending the Architecture
Once you understand the basics, you can extend this architecture for your own projects by:
- Adding new SSR or client-only components.
- Creating custom layouts with multiple
data-part
sections. - Using dynamic props from URLs to customize component rendering.
- Mixing SSR and client-only components to optimize SEO and performance.
Contact Me
You can reach m via email: Yaniv
Top comments (2)
Very interesting idea, I'll have to try it out.
the html first architecture you show ,looking good
I will try this thanks