@t8n/ui
v1.8.4
Published
A lightweight HTML templating engine for TitanPL with file caching and variable interpolation.
Downloads
58
Readme
@t8n/ui
A minimal, explicit UI extension for TitanPL that lets you render HTML and inject CSS in a single render call — with no static routes, no magic, and full control.
This extension is designed for action-based routing and runtime-first TitanPL apps.
✨ Features
ui.render()→ render HTML + CSS in one callui.load()→ preload templates for reuseui.css()→ load CSS manually if needed- Simple templating:
tpl{{ var }} - Explicit CSS injection (no hidden parsing)
- Memory + persistent (
ls) caching - Zero static file server
- Zero extra routes
- One extension, one mental model
📦 Installation
npm install @titanpl/uiTitanPL automatically loads the extension at runtime.
📁 Project Structure
app/
├─ actions/
│ └─ hello.js
├─ static/
│ ├─ app.html
│ └─ styles.cssAll paths are relative to app/.
🧠 Core Idea
TitanPL does nothing implicitly.
- HTML is rendered only when you call
ui.render()orui.load() - CSS is injected only if you explicitly request it
- You decide where CSS goes in HTML
🧩 Template Syntax
Variables
tpl{{ name }}CSS injection point
tpl{{ css }}🚀 Usage
1️⃣ HTML Template
app/static/app.html
<!DOCTYPE html>
<html>
<head>
tpl{{ css }}
</head>
<body>
<h1>tpl{{ name }}</h1>
</body>
</html>2️⃣ CSS File
app/static/styles.css
body {
background-color: black;
height: 100vh;
}
h1 {
color: rgb(32, 215, 215);
}3️⃣ One-Shot Render (Recommended)
import { ui } from "@t8n/ui"
export const hello = () => {
return ui.render(
"static/app.html",
{ name: "Titan" },
{ css: "static/styles.css" }
);
};✔ HTML rendered ✔ CSS injected ✔ Single response ✔ No static routes
4️⃣ Multiple CSS Files
return ui.render(
"static/app.html",
{ name: "Titan" },
{ css: ["static/base.css", "static/theme.css"] }
);CSS files are injected in order.
🔁 Preloading Templates with ui.load()
Use this for high-traffic routes.
const page = ui.load("static/app.html");
export const hello = () => {
return page(
{ name: "Titan" },
{ css: "static/styles.css" }
);
};Why use load()?
- Template read once
- Faster per request
- Cleaner route code
🎯 Manual CSS Loading (Optional)
If you want full control:
export const hello = () => {
return ui.render("static/app.html", {
name: "Titan",
css: ui.css("static/styles.css")
});
};🧠 API Reference
ui.render(htmlPath, data?, options?)
Render HTML once with optional CSS.
ui.render(
"static/app.html",
{ name: "Titan" },
{ css: "static/styles.css" }
);ui.load(htmlPath)
Preload template and return a reusable renderer.
const page = ui.load("static/app.html");
page(data, options);ui.css(cssPath)
Load CSS and return a <style> block.
ui.css("static/styles.css");ui.clearCache()
Clear all cached HTML and CSS files.
ui.clearCache();🧠 Mental Model (Important)
ui.render() → returns an HTML response
tpl{{ css }} → where styles are injected
tpl{{ var }} → template variables
YOU → control compositionNo implicit behavior. No auto static serving. No hidden parsing.
❌ What This Extension Does NOT Do
- ❌ No static file server
- ❌ No
<link>interception - ❌ No auto CSS loading
- ❌ No HTML AST parsing
- ❌ No framework magic
This is intentional.
✅ Why This Fits TitanPL
- Runtime-first
- Predictable
- Explicit IO
- Action-based routing friendly
- Production-safe
- Easy to debug
🛣️ Possible Extensions (Future)
ui.js()for inline JS- Layouts / partials
- Scoped CSS
- Dot-path vars (
tpl{{ user.name }}) - HTML escaping / raw blocks
