ChadScript.embed
Compile-time file embedding. Reads files from disk during compilation and bakes their contents directly into the native binary as string constants. At runtime, accessing embedded files is instant — no file I/O, no filesystem dependency.
This is useful for bundling HTML, CSS, templates, config files, or any static assets into a single self-contained binary.
ChadScript.embedFile(path)
Embed a single file at compile time. Returns the file contents as a string.
const html = ChadScript.embedFile("./index.html");
console.log(html); // contents of index.html, baked into the binaryThe path must be a string literal (not a variable). It is resolved relative to the entry file being compiled.
ChadScript.embedDir(path)
Recursively embed all files in a directory at compile time. Each file is stored as a string constant keyed by its relative path within the directory.
ChadScript.embedDir("./public");This walks the directory tree and embeds every file it finds. Use getEmbeddedFile() to retrieve them at runtime.
ChadScript.getEmbeddedFile(key)
Retrieve a previously embedded file by its key. For embedFile(), the key is the filename. For embedDir(), the key is the relative path within the embedded directory.
ChadScript.embedDir("./public");
const html = ChadScript.getEmbeddedFile("index.html");
const css = ChadScript.getEmbeddedFile("style.css");
const nested = ChadScript.getEmbeddedFile("images/logo.txt");Returns an empty string if the key is not found.
ChadScript.getEmbeddedFileAsUint8Array(key)
Retrieve a previously embedded file as a Uint8Array. Useful for working with binary data programmatically (e.g., hashing, transforming, or writing to disk).
ChadScript.embedDir("./assets");
const imageData: Uint8Array = ChadScript.getEmbeddedFileAsUint8Array("logo.png");
console.log(imageData.length); // exact byte count
fs.writeFileSync("/tmp/logo.png", imageData); // binary-safe writeReturns a zero-length Uint8Array if the key is not found.
ChadScript.serveEmbedded(path)
Return an HttpResponse for an embedded file. Strips the leading / from the path, looks up the file in the embedded table, and returns { status: 200, body: content, headers: "" } if found or { status: 404, body: "Not Found", headers: "" } if not.
The HTTP server automatically sets Content-Type based on the file extension, so .css, .js, .png, .wasm, etc. all get the correct header with no extra work.
This eliminates per-file route boilerplate for serving static assets:
ChadScript.embedDir("./public");
function handleRequest(req: HttpRequest): HttpResponse {
if (req.path.startsWith("/api/")) return handleApi(req);
return ChadScript.serveEmbedded(req.path);
}
httpServe(3000, handleRequest);Example: HTTP Server with Embedded Files
A common pattern is embedding HTML/CSS for a web server so the entire app is a single binary with no external file dependencies:
my-server/
app.ts
public/
index.html
style.css// Compile time: walks ./public/ and bakes every file into the binary as a string constant.
// The directory itself is not needed at runtime — files live in memory.
ChadScript.embedDir("./public");
function handleRequest(req: HttpRequest): HttpResponse {
// serveEmbedded strips the leading '/', looks up the file in the embedded
// table, and returns 200 + body if found, or 404 if not.
// Content-Type is inferred from the file extension (.css, .png, .js, etc.)
return ChadScript.serveEmbedded(req.path);
}
// Starts listening on port 3000; blocks forever
httpServe(3000, handleRequest);Or with manual routing for more control:
ChadScript.embedDir("./public");
function handleRequest(req: HttpRequest): HttpResponse {
if (req.path == "/") {
return { status: 200, body: ChadScript.getEmbeddedFile("index.html"), headers: "" };
}
if (req.path == "/style.css") {
return { status: 200, body: ChadScript.getEmbeddedFile("style.css"), headers: "Content-Type: text/css" };
}
return { status: 404, body: "Not Found", headers: "" };
}
httpServe(3000, handleRequest);$ chad build my-server/app.ts -o server
$ ./server
# HTML and CSS are served from memory — no files needed at runtimeSee examples/hackernews/ for a full working example with embedDir().
How It Works
At compile time, the compiler reads the file(s) from disk and emits them as LLVM IR global string constants. At runtime, getEmbeddedFile() does a simple string comparison lookup across all embedded keys — no file system access occurs.
| API | When | What |
|---|---|---|
embedFile(path) | Compile time | Reads file, returns contents as string |
embedDir(path) | Compile time | Recursively reads all files in directory |
getEmbeddedFile(key) | Runtime | Looks up embedded content by filename/path |
getEmbeddedFileAsUint8Array(key) | Runtime | Same as above, returns Uint8Array (binary-safe) |
serveEmbedded(path) | Runtime | Returns HttpResponse for embedded file (200 or 404, binary-safe via bodyLen) |
Notes
- All paths are resolved relative to the entry file (the
.tsfile passed tochad build) embedFile()andembedDir()arguments must be string literals — they are evaluated at compile timeembedDir()embeds all files recursively; keys are relative paths from the embedded directory (e.g.subdir/page.html), so files with the same name in different subdirectories won't collideembedFile()keys by filename only (basename), so avoid embedding two files with the same name via separateembedFile()calls — useembedDir()instead when you have nested structures- Binary files (images, fonts, wasm, etc.) are fully supported — they are embedded using Latin-1 encoding which preserves all byte values 0x00–0xFF