Components and layouts
Import and compose components
Build pages from small components without turning every HTML element into an abstraction.
Components exist to be reused. You write a card once, then use it on the home page, the blog index, and the tag pages. Let’s see how to do that in Astro.
Import the component in the component script, then use its name as a tag in the template:
---
import Card from '../components/Card.astro'
---
<section class="cards">
<Card title="HTML first" />
<Card title="JavaScript when needed" />
</section>
The import works like any ES module import. The path is relative to the current file. The name must start with a capital letter, because that’s how Astro tells a component from a plain HTML tag like <card>.
What the browser receives
Astro resolves the import while rendering. Each <Card> is replaced with the HTML the card produces. Two cards, two blocks of markup.
The browser never downloads Card.astro. It doesn’t download a component runtime either. There is nothing left of the component boundary in the output, just HTML.
When something deserves a component
Not every piece of markup should become a component. My rule of thumb: a component earns its place when the UI repeats, when it has a distinct responsibility, or when it carries its own styles and data.
A Header, a ProductCard, a NewsletterForm. All good candidates. A paragraph that appears once on one page is not. Wrapping it in <Intro /> just adds a file to open.
Composition makes data flow visible
With the code above, the page decides which cards exist and what they say. The card decides how one item looks. Neither one needs to know the other’s internals.
That’s the payoff. When a card looks wrong, you open Card.astro. When a card is missing, you open the page. You always know where to look.
Check the cost
After you extract a component, look at the generated HTML. Astro makes components free at runtime, but they still cost something for the humans reading the code.
Two signs the abstraction went too far. The output has extra wrapper divs that exist only because of the component boundary. Or you have to jump between three files to understand a simple block of markup.
Try this on the astro-notes project: create src/components/Card.astro with an <article> and a heading, use it twice on the home page, and view the page source. Then ask yourself whether a <Section> wrapper component would help or just add a file.
Lesson completed