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