Pre-rendering
Pre-rendering (.pre.ts files) allows you to transform HTML documents at build time. Unlike components that target specific elements, pre-rendering gives you full access to the entire document.
Quick Start
Create a .pre.ts file with the same base name as your .html file:
// index.pre.ts
const title = document.querySelector("title");
if (title) {
title.textContent = "My Awesome Site";
}
The corresponding index.html is automatically loaded and modified.
How It Works
File Pairing
Pre-rendering files are paired with HTML files by name:
| Pre-render File | Processes |
|---|---|
index.pre.ts | index.html |
about.pre.ts | about.html |
blog/post.pre.ts | blog/post.html |
The document Variable
Every .pre.ts file has access to a document variable — the parsed DOM of the corresponding HTML:
document.querySelector("h1");
document.getElementById("content");
document.querySelectorAll(".items");
document.body;
Build Process Order
1. Run .pre.ts files → Modify HTML documents
2. Iterative component processing (up to 10 iterations):
a. Process .com.ts → Replace TypeScript components
b. Process .com.html → Replace HTML components
c. Process .com.md → Replace Markdown components
d. Repeat until no changes detected
3. Compile .ts to .js → TypeScript compilation
4. Copy to output → Final build
Pre-rendering happens first, so you can inject components dynamically.
Auto-Create HTML
If the .html file doesn't exist, Tkeron creates a default template. Then your .pre.ts runs on it.
Examples
Inject Meta Tags
// index.pre.ts
const head = document.querySelector("head");
if (head) {
const meta = document.createElement("meta");
meta.setAttribute("name", "description");
meta.setAttribute("content", "A description of my site");
head.appendChild(meta);
}
Inject Build Time
// index.pre.ts
const buildTimeElement = document.getElementById("build-time");
if (buildTimeElement) {
buildTimeElement.textContent = `Built: ${new Date().toLocaleString()}`;
}
Fetch External Data
// products.pre.ts
const response = await fetch("https://api.example.com/products");
const products = await response.json();
const container = document.getElementById("products");
if (container) {
products.forEach((product: any) => {
const card = document.createElement("div");
card.className = "product-card";
card.innerHTML = `
<h3>${product.name}</h3>
<p>$${product.price}</p>
`;
container.appendChild(card);
});
}
Note: Data is fetched once at build time. Output is static HTML.
Import Modules
// index.pre.ts
import { getBuildMetadata } from "./build-utils";
const metadata = await getBuildMetadata();
const footer = document.querySelector("footer");
if (footer) {
footer.innerHTML = `<p>Version: ${metadata.version}</p>`;
}
Environment Variables
// index.pre.ts
const isProd = process.env.NODE_ENV === "production";
if (isProd) {
const script = document.createElement("script");
script.src = "https://analytics.example.com/script.js";
document.body?.appendChild(script);
}
Dynamic Component Injection
// dashboard.pre.ts
const isDev = process.env.NODE_ENV === "development";
if (isDev) {
const debugPanel = document.createElement("debug-panel");
document.body?.appendChild(debugPanel);
}
The <debug-panel> component will be processed in the next build step.
DOM Manipulation
// Creating elements
const div = document.createElement("div");
div.className = "container";
div.innerHTML = "<p>Content</p>";
// Modifying attributes
const img = document.querySelector("img");
img?.setAttribute("loading", "lazy");
// Inserting content
parent?.appendChild(child);
parent?.insertBefore(child, parent.firstChild);
// Removing elements
element?.remove();
Limitations
- No browser APIs —
window,localStorage,navigatordon't exist - No user input — Can't access runtime form data
- No event listeners — Won't persist to browser output
Use regular .ts files for browser interactivity.
Best Practices
✅ Use for build-time data: API fetching, SEO meta tags, build metadata ✅ Handle errors gracefully: Always catch fetch failures ✅ Use timeouts: Prevent builds from hanging on slow APIs ✅ Keep logic separate: Import from utility modules
❌ Don't overuse: For element-level changes, use TypeScript Components
Next Steps
- TypeScript Components — Element-level logic
- HTML Components — Simple reusable markup
- Best Practices — Patterns and tips
- CLI Reference — Build options