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 FileProcesses
index.pre.tsindex.html
about.pre.tsabout.html
blog/post.pre.tsblog/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

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