Astro Components

Purpose and Scope

Astro components are the main authoring unit for Astro projects. A component is written in a .astro file, combines a frontmatter-style component script with an HTML-like template, and renders to HTML instead of shipping a client-side component runtime by default. This page explains the component model from a developer point of view: what you write, how it fits into an Astro project, and how the repository evidence around examples, build configuration, and runtime infrastructure supports the public authoring surface.

The most important mental model is that Astro components are server-rendered templates first. The component script can import data, compute variables, and prepare props, while the template emits markup using HTML plus Astro expressions. If a component needs browser behavior, you add ordinary <script> tags or mount framework islands with client directives. If a component represents a whole route, placing it under src/pages/ turns that component into a page. If it is reusable UI, placing it under src/components/ keeps it importable by pages, layouts, and other components.

Relevant Source Files

  • .devcontainer/basics/devcontainer.json — defines the Basics example development container, opens src/pages/index.astro, forwards the Astro dev server port, installs dependencies, builds the repository, and starts the example site.
  • configs/tsconfig.build.json — provides the shared TypeScript build convention used by packages, compiling each package from src to dist and placing build metadata under dist/._cache.
  • packages/astro-prism/tsconfig.build.json — shows a package extending the shared build configuration while including both src and a virtual type declaration, a pattern used by Astro-adjacent feature packages.
  • packages/astro-rss/tsconfig.build.json — shows another published Astro package using the shared build configuration without extra include overrides.
  • packages/astro/src/assets/fonts/infra/build-font-file-id-generator.ts — demonstrates build-time infrastructure used by rendered pages and components: font file IDs are derived from resolved content and font type.
  • .changeset/sharp-bags-build.md — records a rendering-related fix for Cloudflare builds where prerender failures during page rendering must surface as build failures rather than producing truncated HTML.

Sources: .devcontainer/basics/devcontainer.json, configs/tsconfig.build.json, packages/astro-prism/tsconfig.build.json, packages/astro-rss/tsconfig.build.json, packages/astro/src/assets/fonts/infra/build-font-file-id-generator.ts, .changeset/sharp-bags-build.md

Component Authoring Model

A .astro component has two cooperating parts. The component script is the fenced section at the top of the file, where you define local variables, import other components, fetch data, and prepare values for the template. The component template is the markup below the fence. Astro syntax is intentionally close to HTML, with JSX-like expressions for variables, conditional rendering, lists, dynamic attributes, and component invocation. This gives authors a compact format for static HTML, dynamic server-rendered HTML, and composition without requiring a client-side framework runtime.

A useful way to design components is to decide whether a file is a page, a layout, or a reusable fragment. A page component owns a route and is discovered from src/pages/. A layout wraps page content and usually receives props or slots. A reusable component might be a header, metadata block, card, navigation menu, or any repeated markup. The same component syntax supports all three roles, so the distinction is mostly project organization and routing behavior rather than a separate API surface.

The Basics development container points directly at src/pages/index.astro when a Codespaces workspace opens, which reflects the intended learning path: start by editing a page component, run the dev server on port 4321, and preview the result immediately. Its setup also installs the Astro VS Code extension and Prettier extension, reinforcing that component authoring is meant to be editor-assisted and formatted consistently. For contributors and example users, this environment provides a concrete route from repository checkout to live component editing. Sources: .devcontainer/basics/devcontainer.json

System-to-Code Mapping

Although .astro files are the author-facing format, the repository is organized as buildable packages that publish JavaScript and types. The shared build configuration sets a package-local src directory as rootDir and emits compiled output to dist. That matters for component users because public Astro features are distributed as packages, not as raw repository TypeScript. When a component imports Astro-provided modules, components, or integration helpers, those imports ultimately come from package build outputs governed by this shared convention.

The Prism and RSS package build configs show the same convention applied to Astro ecosystem packages. packages/astro-rss/tsconfig.build.json simply extends the shared build config, while packages/astro-prism/tsconfig.build.json extends it and includes virtual.d.ts in addition to source files. From a component author’s perspective, this explains why feature packages can feel uniform while still exposing feature-specific types or virtual modules. A component can use Markdown highlighting, RSS generation, or other package capabilities while relying on consistent package build and publishing mechanics. Sources: configs/tsconfig.build.json, packages/astro-prism/tsconfig.build.json, packages/astro-rss/tsconfig.build.json

Rendered component output also depends on build-time infrastructure beyond the .astro file itself. The font file ID generator is a small example: it receives an original URL and font type, resolves the file content, hashes that content, and returns a deterministic filename ending in the font type. This kind of infrastructure lets component-authored pages reference optimized assets while Astro handles stable output naming. The author writes page and component markup; the build system turns supporting assets into cacheable, content-derived files. Sources: packages/astro/src/assets/fonts/infra/build-font-file-id-generator.ts

Execution Flow

A typical component workflow starts with local editing, continues through the dev server, and ends in a build or server-rendered deployment. In the Basics container, repository setup runs pnpm install, builds the repository from the workspace root, and then starts the example with pnpm start --host. Port 4321 is forwarded and opened as an application preview. This mirrors the common Astro loop: edit a component, let Vite-powered development reload the preview, then validate the same project through a production build.

During production rendering, Astro must treat component and page failures as build-significant errors. The Cloudflare changeset documents a fix where prerender errors thrown during rendering in workerd could previously be swallowed, allowing astro build to exit successfully while emitting truncated HTML. The fix buffers the response body before returning it to the build process so streaming errors are caught and surfaced. For component authors, the practical lesson is that exceptions during page rendering are not cosmetic: they must fail the build clearly because they can corrupt final HTML. Sources: .changeset/sharp-bags-build.md

Authoring Reference

Use the following component primitives when reading or writing Astro code. The component script is the fenced JavaScript or TypeScript section at the top of a .astro file. The component template is the HTML-like body below it. Expressions use curly braces to interpolate variables, attributes, lists, conditionals, and dynamic tags. Imports let one Astro component compose another, or mount framework components as islands. Standard HTML <script> tags are available when a component needs browser-side behavior, while framework islands add targeted interactivity without changing Astro’s default zero-JavaScript output model.

When deciding where code belongs, prefer the smallest component that keeps intent clear. Put route-specific data loading and page structure in src/pages/ components. Put repeated shells in layouts, and put reusable display units in src/components/. Keep browser-only behavior explicit, because ordinary Astro component logic runs before HTML is sent to the browser. When asset-heavy components use fonts or other generated files, remember that Astro’s build pipeline may rewrite supporting resources into deterministic output files, as shown by the font ID generator infrastructure.

Next Steps

To go deeper, read the routing and layouts pages next if you are organizing components into a site structure. Read the framework components and client-side scripts pages if you need interactivity through islands or browser scripts. Read the images, assets, and fonts pages if your components depend on optimized static resources. Finally, use the Basics example workflow as the shortest practical loop: open the starter page component, run the local server, edit markup and expressions, then run a production build to catch rendering and packaging issues before deployment.