Documentation menu

Compiler and Vite APIs

Goldar compiles Handlebars with a long-lived Go process. A conventional application default-exports an Application from src/index.ts and uses the integrated goldar dev and goldar build commands. Files beneath project-root public/ are served unchanged at root-relative URLs, while application tests live in tests/ and run through the project’s test script. goldar/vite supports custom Vite pipelines; goldar/compiler is the lower-level Node client and artifact model.

The template-language reference defines the exact implemented syntax, rendering semantics, unsupported forms, and diagnostic catalog.

For entryless build and dev, an explicit --config or conventional goldar.config.* takes precedence over src/index.* discovery. Pass an entry, such as goldar dev ./src/alternate.ts, to bypass both conventions. An explicit entry cannot be combined with --config.

Vite plugin

For a custom Vite pipeline, install the assembled Goldar package and Vite, then call the named or default goldar() export:

import { defineConfig } from "vite";
import { goldar } from "goldar/vite";

export default defineConfig({
	plugins: [goldar()],
});

GoldarPluginOptions extends CompilerProcessOptions with an optional components override. compilerExecutable selects the Go executable and cwd selects its working directory. Without an explicit executable, Goldar checks GOLDAR_COMPILER, the compiler bundled with goldar, workspace build locations, then goldar-compiler on PATH.

By default, compiler-emitted custom-element capabilities map each tag to the unique local module with the same basename. The module default-exports its HTMLElement constructor. Missing and ambiguous modules are reported at the originating template tag. The optional components record overrides discovery for a tag and maps it to GoldarComponentRegistration:

  • module: absolute path, project-root-relative ./ path, or package specifier;
  • exportName: named HTMLElement constructor exported by that module.

The plugin compiles .hbs modules for SSR and validates compiler diagnostics, artifact versions, and discovered custom-element modules. It owns one compiler process and disposes it at the end of a build or watcher. It also refreshes exact template declarations and component discovery automatically at build start and during watch changes.

A template may default-import another relative .hbs module in frontmatter and declare a local tag with ImportedView.as("imported-view"). The directive is erased from generated declarations and runtime output. Vite retains the imported template as an ordinary ESM dependency, so its program, styles, watch invalidation, and diagnostics participate in the normal module graph. Aliased tags are template calls rather than Custom Element capabilities.

GOLDAR_CLIENT_MODULE_ID is the preferred virtual:goldar/client browser entry for a custom Vite pipeline. Import it to register discovered components in lexical tag order and include compiled template styles through Vite’s CSS graph. Integrated goldar build and goldar dev applications receive a generated browser entry and do not import this module themselves. GOLDAR_COMPONENTS_MODULE_ID remains the compatible virtual:goldar/components identifier with the same eager browser behavior. Server template modules never import component implementations. A tag already registered with a different constructor throws at runtime.

The plugin is exported from the single goldar package so custom Vite integrations do not require a second Goldar package.

TypeScript client types

Add goldar/compiler/client to the consuming tsconfig’s compilerOptions.types. It supplies:

  • a *.hbs declaration whose default export is CompiledTemplate from goldar/view;
  • a declaration for virtual:goldar/client;
  • a declaration for virtual:goldar/components.

Set allowArbitraryExtensions: true and add .goldar/types to rootDirs. The Vite plugin keeps exact CompiledTemplate<Props> declarations synchronized from .hbs frontmatter; run goldar sync before a standalone tsc invocation. The generated files live beneath .goldar/types; the client entry provides the ambient fallback declarations.

Template type synchronization

syncTemplateTypes(options) scans every .hbs file beneath options.projectRoot, compiles its frontmatter, writes exact declarations beneath .goldar/types, and removes stale Goldar-owned declarations. SyncTemplateTypesOptions extends CompilerProcessOptions; callers may select a custom compiler executable and working directory.

The returned SyncTemplateTypesResult reports scanned, generated, and removed counts. A blocking compiler error diagnostic throws TemplateTypeSyncError without changing declarations. Its failures array contains TemplateTypeSyncFailure records with the diagnostic, source, source name, and template path. Goldar refuses to overwrite declarations without its generated-file banner.

Compiler process

Import CompilerProcess from goldar/compiler for direct compilation:

import { CompilerProcess } from "goldar/compiler";

const compiler = await CompilerProcess.create();

try {
	const result = await compiler.compile("<h1>{{title}}</h1>", {
		sourceName: "src/title.hbs",
	});
	console.log(result.diagnostics, result.artifacts.view);
} finally {
	await compiler.dispose();
}

CompilerProcess.create(options?) starts the child, negotiates protocol and artifact versions, and rejects when the executable cannot start or versions differ. compilerVersion is available after creation. compile(source, options) requires a diagnostic sourceName and accepts optional CompileOptions registry and context type references. dispose() requests an orderly shutdown and must be called by the owner. compilerExecutable and GOLDAR_COMPILER override the bundled compiler when testing a custom build.

The client rejects pending calls if the compiler exits, emits invalid JSON, returns a protocol error, or is disposed. It does not restart failed processes.

Compile artifacts

All source and generated ranges use zero-based UTF-16 offsets. SourceRange.end is the exclusive end of a non-empty syntax range; editor mappings may also use zero-length cursor anchors.

CompileTemplateResult contains:

  • source: tolerant TemplateDocument data, including TemplateFrontmatter, TemplateTag, TemplateAttribute, and TemplateAttributeValue records;
  • diagnostics: CompilerDiagnostic values with stable code, message, severity, and source range;
  • artifacts.typecheck: a TypecheckArtifact containing generated TypeScript text and capability-scoped SourceMapping records;
  • artifacts.templateDependencies: ordered, source-located metadata for lexically imported templates;
  • artifacts.view: an executable ViewProgram when no blocking compiler error prevents emission;
  • artifacts.styles: a StylesheetArtifact containing top-level CSS blocks, source ranges, global flags, and the compiler-owned scope attribute.

Template styles

Top-level <style> elements are compile directives rather than runtime markup:

<style>
	.notice {
		color: rebeccapurple;
	}
</style>

<p class="notice">{{message}}</p>

The compiler extracts the CSS and stamps every element authored by that template. Vite parses the CSS and rewrites the selector as .notice:where([data-goldar-s-*]), preserving the selector’s original specificity. Multiple blocks retain source order. <style is:global> disables scoping for a whole block, while :global(...) escapes part of a scoped selector.

Style directives must be top-level and static. Other attributes, Handlebars interpolation, nested or self-closing blocks, unterminated blocks, and authored data-goldar-s-* attributes are compiler errors. Scoped @keyframes are not implemented yet; put them in <style is:global>.

CompileOptions identifies optional registry and context TypeScript types with TypeReference records. Attribute values are categorized by AttributeValueKind; mappings by MappingKind, with independent completion, diagnostic, hover, and navigation flags in MappingCapabilities.

The exported version constants are COMPILER_PROTOCOL_VERSION, TYPECHECK_PROBE_VERSION, STYLESHEET_ARTIFACT_VERSION, and VIEW_PROGRAM_VERSION. InitializeResult, CompilerArtifactVersions, CompileTemplateParams, CompileTemplateOptions, and the artifact interfaces describe the versioned process contract.

Compiler runtime

goldar/compiler-runtime is a low-level target for generated .hbs modules, not a normal application authoring API. It exports createCompiledTemplate() plus the versioned View program model used by goldar/view.

A ViewProgram has a schemaVersion, sourceName, capabilities, dependencyCount, and ordered instructions. ViewInstruction is the union of:

InstructionMeaning
DoctypeInstructionWrites a doctype.
CommentInstructionWrites an HTML comment.
OpenElementInstructionOpens a normal or void element.
StaticAttributeInstructionWrites a literal or boolean attribute.
BoundAttributeInstructionResolves and escapes a prop path into an attribute.
TextInstructionWrites compiler-owned literal text.
EscapedExpressionInstructionResolves and text-escapes a prop path.
TrustedExpressionInstructionRequires and writes a branded TrustedHtml value.
OutletInstructionRenders child views supplied to the callable template.
IfInstructionSelects a recursive instruction body using JavaScript truthiness.
EachInstructionIterates an array in a lexical binding scope, or renders its empty branch.
RenderTemplateInstructionCalls an authenticated imported-template dependency with typed props and optional outlet children.
CloseElementInstructionCloses an element.

Dynamic instructions carry stable binding and region IDs; every instruction carries its original sourceRange. Value references identify either the root props object or a lexical binding. CustomElementCapability records each custom-element tag discovered by the compiler, excluding locally aliased imported templates. Consumers must reject incompatible VIEW_PROGRAM_VERSION values instead of guessing at semantics.

Wire protocol

The executable reads and writes one JSON-RPC 2.0 object per line. Standard output is reserved for protocol responses; diagnostics intended for humans go to standard error. Requests must be initialized before compilation:

  1. initialize accepts protocolVersion and optional artifactVersions, then returns InitializeResult.
  2. goldar/compileTemplate accepts CompileTemplateParams and returns CompileTemplateResult.
  3. shutdown returns an empty result and terminates the process loop.

The executable uses JSON-RPC error codes -32700 for invalid JSON, -32600 for an invalid request, -32601 for an unknown method, -32602 for invalid parameters or incompatible versions, and -32002 when a request arrives before initialization. The goldar package includes the compiler executables selected by the Node client at runtime.

Request IDs are integers. Each input line is limited to 16 MiB. goldar/compileTemplate requires a non-empty sourceName. JSON collection fields, including templateDependencies, are arrays even when empty. See the compiler pipeline for the full cross-language invariants and version-change checklist.