Directives and Astro Syntax
Purpose and Scope
Astro component syntax is the authoring language used in .astro files. It starts from familiar HTML, adds a frontmatter component script between --- fences, and allows JavaScript expressions inside the template. Template directives are the special HTML-attribute-like controls that tell Astro’s compiler or runtime to treat an element, component, or value differently. The official docs describe directives as attributes with a colon in their name, such as client:load, class:list, and set:html, and emphasize that directives must be visible to the compiler rather than hidden inside a spread object.
This page is a reference-oriented map for readers who already know how to create a page or component and now need to understand which syntax belongs to Astro, which behavior is compile-time, and which behavior reaches package or build infrastructure. The supplied source evidence for this page does not enumerate every directive implementation, so the practical reference uses the official docs terminology while grounding repository-level behavior in the build and asset modules that participate after authoring. Sources: configs/tsconfig.build.json, packages/astro-prism/tsconfig.build.json, packages/astro/src/assets/fonts/infra/build-url-resolver.ts
Core Syntax Model
An Astro component has two related regions: frontmatter and template. The frontmatter is server-side JavaScript or TypeScript that can define local variables, import components, fetch data, or prepare values. The template is HTML-like markup that can include those values with curly-brace expressions. This model makes basic dynamic output readable: a variable defined in frontmatter can become text content, an attribute value, a conditional branch, or a mapped list of elements without requiring a client-side framework by default.
Template directives fit into that model as named signals to Astro. A directive name has the form X:Y, and Astro treats it as an instruction rather than a normal HTML attribute. Some directives take no value, such as a hydration directive on a component, while others take structured values, such as class:list receiving strings, arrays, objects, and falsy values that are skipped. Because directives are compiler-visible syntax, authors should write them directly on the element or component instead of constructing them indirectly through a spread object.
---
const name = 'Astro';
const classes = ['hero', { visible: true }];
---
<h1 class:list={classes}>Hello {name}</h1>
<Counter client:load />
<article set:html={trustedHtml} />Directive Families
Common template directives help authors express behavior that would otherwise require awkward string building or imperative DOM code. class:list composes a final class string from mixed inputs. set:html injects an HTML string into an element and should only be used with trusted or already-sanitized content because the value is not automatically escaped. set:text is the safer counterpart for plain text. These are template-level conveniences: they affect rendered output, but they are written in the same place as ordinary HTML attributes.
Client directives are the syntax readers most often associate with Astro’s islands architecture. They tell Astro when an imported framework component should hydrate in the browser. Examples include eager hydration, idle hydration, viewport-based hydration, and media-query-based hydration. The important distinction is that the page remains server-rendered HTML first; the directive marks a specific interactive island. That is different from a local script tag, which runs browser JavaScript, and different again from a server-only frontmatter expression, which is evaluated before the page is sent.
Syntax-highlighting components are a useful adjacent authoring surface because Astro supports Markdown code fences, the built-in Shiki-powered Code component, and the Prism-powered Prism component in .astro files. The astro-prism package has its own TypeScript build configuration that extends the shared build config and includes both ./src and ./virtual.d.ts, indicating that its public component surface is built with package-local source plus virtual type declarations. Sources: configs/tsconfig.build.json, packages/astro-prism/tsconfig.build.json
System-to-Code Mapping
The shared build configuration explains how repository packages turn TypeScript authoring surfaces into distributable JavaScript. configs/tsconfig.build.json extends the base config, sets the package source root to ${configDir}/src, emits to ${configDir}/dist, and stores TypeScript build metadata under dist/._cache/ts_build/build.tsbuildinfo. That pattern matters for directive and syntax-facing packages because public authoring helpers must be compiled consistently before they can be consumed by projects. Package configs such as astro-prism and astro-rss inherit that shared behavior rather than redefining it from scratch. Sources: configs/tsconfig.build.json, packages/astro-prism/tsconfig.build.json, packages/astro-rss/tsconfig.build.json
The font asset infrastructure shows how values authored in components can become stable build outputs. BuildFontFileIdGenerator receives a hasher and a font-file content resolver, resolves the original URL to content, hashes that content, and appends the font type as the extension. BuildUrlResolver then produces URLs from emitted IDs, base paths, asset prefixes, and adapter-level search parameters. This is not itself template directive syntax, but it is the kind of build pipeline that component authors rely on when syntax references assets and expects deterministic output. Sources: packages/astro/src/assets/fonts/infra/build-font-file-id-generator.ts, packages/astro/src/assets/fonts/infra/build-url-resolver.ts
The changeset for Cloudflare prerendering is a reminder that syntax-level choices eventually pass through rendering and adapter execution. It describes a fix where prerender errors thrown during workerd rendering are buffered and surfaced as build failures instead of being silently swallowed while emitting truncated HTML. For directive users, the practical lesson is that compiler-visible attributes and server-rendered expressions are part of the build contract: when rendering fails, a correct build should fail clearly rather than hiding broken output. Sources: .changeset/sharp-bags-build.md
Compact Reference
| Area | Author-facing form | Behavior | Notes |
|---|---|---|---|
| Frontmatter | --- const value = 1; --- | Defines server-side values for the template | Runs before HTML output is produced |
| Expressions | {value} | Inserts JavaScript expression results into markup | Used for text, attributes, lists, and conditionals |
| Dynamic attributes | class={name} | Computes an attribute value | Works on HTML elements and components |
| Common directive | class:list={...} | Builds a class string from strings, arrays, objects, and falsy values | Compiler-visible directive, not emitted as-is |
| HTML injection | set:html={html} | Injects trusted HTML into an element | Escape or sanitize untrusted input first |
| Island hydration | <Component client:load /> | Hydrates a framework component in the browser | Applies to component islands, not ordinary HTML attributes |
| Syntax highlighting | <Prism />, <Code />, Markdown fences | Renders highlighted code through Prism or Shiki surfaces | astro-prism is built as a package with virtual declarations |
Relevant Source Files
.changeset/sharp-bags-build.md— records a Cloudflare prerendering fix where rendering errors in workerd are surfaced as build failures, which is relevant to understanding how authored syntax participates in build-time rendering guarantees.configs/tsconfig.build.json— defines the shared TypeScript package build shape, including source root, output directory, and build-info cache location used by package authoring surfaces.packages/astro-prism/tsconfig.build.json— extends the shared build config and includes./srcplus./virtual.d.ts, grounding the Prism component/type surface referenced by syntax-highlighting docs.packages/astro-rss/tsconfig.build.json— extends the shared build config for another published package, showing the common package-build pattern used across Astro surfaces.packages/astro/src/assets/fonts/infra/build-font-file-id-generator.ts— implements build-time font file ID generation from resolved content hashes and font types, showing deterministic asset naming behind authored component output.packages/astro/src/assets/fonts/infra/build-url-resolver.ts— implements build-time URL resolution for emitted assets, including base paths, asset prefixes, search parameters, CSP resource tracking, and collected output URLs.
Practical Guidance
When writing .astro files, prefer the syntax form that states your intent directly. Use expressions for values, dynamic attributes for computed attributes, directives for compiler-recognized behavior, and component props for data passed to components. Do not hide directives inside object spreads, because the directive must be visible to the compiler. Treat set:html as an escape hatch, not a default rendering strategy, and use component islands only where browser interactivity is required.
For repository contributors, check both the author-facing syntax and the package or build surface affected by a change. A syntax feature that introduces a public component, virtual module, asset URL, or generated file should have build configuration aligned with the shared package conventions. If the feature participates in prerendering, make sure failures are surfaced during astro build rather than deferred or hidden. Next, read the API reference for exported modules, the image and asset references for URL behavior, and the framework component docs for hydration directives in real island examples.