{{article.title}}
{{#each article.sections}}{{heading}}
{{#each paragraphs}}{{this}}
{{/each}}# User Interface — Server-Rendered HTMLX No Angular. No React. No frontend framework. The UI is a set of `.htmlx` template files that the server parses, populates with content from the embedded database, and serves as plain HTML. Real-time updates arrive via SSE and are applied with minimal client-side scripting. ## Why Not Angular The current `writeonce-app` is an Angular 18 SPA with Tailwind, PrismJS, ngx-markdown, and FontAwesome. It works, but it's a heavy delivery mechanism for what is fundamentally a read-heavy content site: - **~200MB of `node_modules`** for a site that renders markdown articles - **Client-side routing** for content that doesn't need it — every article is a distinct URL, not an interactive application - **JavaScript-dependent rendering** — content doesn't exist until Angular boots, hydrates, and fetches from the API - **Separate build pipeline** — `npm run build` produces static assets that must be deployed to nginx independently of the API The content is static between updates. The interactivity is limited to navigation and code highlighting. A server-rendered approach matches the actual requirements. ## HTMLX Templates The author defines the site layout using `.htmlx` files — HTML with embedded data bindings that the server resolves at render time. ### Template Structure ``` templates/ layout.htmlx # outer shell: ,
, header.htmlx # site header, navigation footer.htmlx # site footer home.htmlx # homepage: article list article.htmlx # single article view about.htmlx # static page contact.htmlx # static page components/ article-card.htmlx # summary card for article listings code-snippet.htmlx # code block with language + title img-caption.htmlx # image with caption section.htmlx # article section (heading + paragraphs) ``` ### Template Syntax Templates use a binding syntax that references content from the database. The server parses these bindings, resolves them against the current content, and outputs plain HTML. ```html{{this}}
{{/each}}First paragraph...
``` When a diff arrives for `article.title`, the script finds the element with `data-bind="article.title"` and replaces its text content. This is the minimal client-side code the architecture requires. ## Code Highlighting The current frontend uses PrismJS for syntax highlighting. In the server-rendered model, highlighting can happen at either layer: **Server-side (preferred):** The server parses code blocks during template rendering and emits pre-highlighted HTML with CSS classes. The browser only needs the PrismJS CSS theme, not the JavaScript library. This eliminates client-side parsing entirely. **Client-side (fallback):** Include PrismJS as a small script that runs on page load and on SSE update. Simpler to implement initially but adds a JavaScript dependency. ## Markdown Rendering The current frontend uses `ngx-markdown` and `marked` to parse markdown in the browser. In the target architecture, markdown is rendered to HTML on the server during template composition. The browser never sees raw markdown. This aligns with the content model: the JSON metadata already defines the article structure (sections, paragraphs, code snippets, images). The markdown file provides prose content. The server combines both into final HTML — the template just places the pre-rendered blocks. ## What Gets Removed | Current (Angular) | Target (HTMLX) | |---|---| | `writeonce-app/` (full Angular project) | `templates/` (handful of .htmlx files) | | `node_modules/` (~200MB) | None | | `angular.json`, `tsconfig.json`, `karma.conf.js` | None | | npm build pipeline | Template parsed at request time | | Nginx static file serving | Binary serves its own HTML | | Client-side routing | Server-side route matching | | Client-side markdown parsing | Server-side rendering | | Client-side code highlighting | Server-side or minimal JS | ## Styling Templates use plain CSS. Tailwind can optionally be used as a build-time utility (generating a static CSS file), but there is no runtime CSS framework. The author writes styles in a `styles.css` file that the server serves as a static asset. ``` templates/ styles/ main.css # site-wide styles article.css # article-specific styles code-theme.css # syntax highlighting theme (PrismJS compatible) ``` ## Template Authoring Experience The `.htmlx` files are editable by the same author who writes articles. The template syntax is intentionally close to HTML — there's no JSX, no TypeScript, no build step. An author who knows HTML can modify the site layout. This closes the loop on the writeonce philosophy: the author writes content (markdown + JSON) and layout (`.htmlx` + CSS) as files, and the binary turns them into a live site.