Astro Crash Course #7 - Reusable Components
Chapters8
Set up a dedicated components directory to hold reusable UI pieces, starting with the new bookcard.astro file.
Extract the book card into a reusable Astro component, pass data via props, and enforce prop shapes with a TypeScript interface for safer, IntelliSense-friendly code.
Summary
Net Ninja lays out a clean path to modularize an Astro app by turning the repeated book card markup into a reusable component. He creates a new components/bookcard.astro file, moves the template and its styles into that component, and then swaps the page markup to render the card via the new component. The lesson emphasizes passing the current book data as a prop to the book card, so each list item can render its own title and author. To handle props safely, he introduces a TypeScript interface in the component front matter, defining a book object with title and author as strings. This interface provides IntelliSense when accessing book.title and book.author and prevents accidental prop leakage. Net Ninja also demonstrates how Astro props are accessed and destructured, showing how to pull the book prop from astro.props. Finally, he highlights the practical benefits: better modularity, leaner page components, and preserved functionality after refactoring. The result is a reusable, type-aware component ready for broader reuse across the app.
Key Takeaways
- Create a reusable component by extracting the book card template into components/bookcard.astro.
- Pass the current book data as a prop to the book card; use curly braces to provide a dynamic value during list rendering.
- Define a TypeScript interface in the component front matter to describe allowed props (e.g., book with title and author strings).
- Access props in Astro using destructuring from astro.props to enable clean template usage.
- Move styles from the page into the component to keep the page lean while preserving visual output.
- Enable IntelliSense and catch prop-mismatch errors by defining a props interface, preventing extra, unused props from slipping through.
- After refactoring, the books page continues to render identically, but with a modular and reusable component structure.
Who Is This For?
Frontend developers who want to learn how to create reusable Astro components, pass data via props, and enforce prop types for safer, more maintainable templates.
Notable Quotes
""we could also extract this book card template and the styles into its own reusable component and then we could just drop that component into this template where we need it.""
—Opening motivation for extracting reusable components to improve modularity.
""we need to pass that book variable as a prop into the book card component when we output it in the template.""
—Introduces the core concept of prop drilling the current book data into the new component.
""prop is just short for property.""
—Defines what a prop is in simple terms for beginners.
""to combat both of these things, we can use a TypeScript interface within the front matter of the component to define how the props should look.""
—Shows how to enforce prop shapes for safety and IntelliSense.
Questions This Video Answers
- how do you create reusable components in Astro
- how to pass props to an Astro component
- how to define prop types in Astro with TypeScript
- how to move styles into a reusable component in Astro
Full Transcript
Okay then. So in the previous lesson we output a list of books each one with their own bit of template for the author and the title and we start those books in a kind of book card right. So this is completely fine but we could also extract this book card template and the styles into its own reusable component and then we could just drop that component into this template where we need it. Now the benefit of that is that we're modularizing the application a little bit more then so that we can reuse components where we need them and we also keep our page components a little leaner.
So then let's do that in this lesson. We'll make a book card component to hold all of this template and the styles for the template as well. And then we'll use that component right here. First then we'll need to make that component somewhere. And we're free to make that wherever we want inside the source directory. But a common convention is to make a components folder and put them all in there. So we'll do that. We'll create a new components folder right here. And then inside that we can create a new file which I'm going to call bookcard.astro.
Now remember we use because this is going to be an Astro component. It's not a page but it's still an Astro component. Okay. Okay, so now inside this component, we're going to first of all add the front matter at the top using two sets of three dashes. And then below that, we want to add the template. So I'm going to head back to the books page now, and I'm going to cut the template that we output for each book. Then I'm going to replace that template with the new book card component we're making. And if we click on this option right here, it should automatically import that component up at the top, which we need to do.
After we've done that, I'm going to come to the book card component and paste in the bookcard template that we want to output for each book. So, all we've done so far is extract the template into its own bookcard component. And then we're outputting the book card component for each list item on the books page. Right now, we are going to get some errors when we do this, and that's because we're trying to access the book title and author in this template, and we don't have those values available to us yet. Now, they're available in the books page because that's where we initialize the book's value, right?
But they're not available in here. There's no book variable, right? So, to solve this, we need to pass that book variable as a prop into the book card component when we output it in the template. And now, prop is just short for property. It's basically a way to pass a value into a nested component like this. And we can have multiple props passed into components. So, we can name props whatever we want in Astro. In this case, I'm going to add a prop to this component called book. And then as a value, we want to pass something dynamic.
So we use curly braces. And then we want to pass the book we're currently iterating that we have access to right here in this function. So then now we're passing the individual book into the bookcard component. And we're doing that for each book in the array, one after the other. Right. Next then let's head back to the bookcard component to access that book prop. Now the way we accept props within a component is by dstructuring them from a special props value given to us by Astro. So we can say const then curly braces to dstructure a prop and we set that equal to astro.props.
So any prop we pass into this component will be stored on this props value given to us by Astro and then we can just dstructure them right here. So we passed in the book prop and that means we can grab that book value like this. And now we can go ahead and use that book value in the template. And you'll see that those errors that we had before have now gone away because we do have the book object available. The next thing I want to do is move all the styles from the books page into this new component.
So let's first of all copy all of those card styles. And once we've done that, in fact, you want to cut them, not copy them. And once you've done that, you can come back and make a style tag down here and then paste them all in. Okay, so this should all work now the same as before. We've not added any new functionality. We've structured the app a little bit better by making this component reusable, but it should do the same thing. And in the browser, we can see that they're all still here. They all look the same.
It's still working identically as it was before. It's just that now we've restructured it. Okay, so currently we're accepting a prop into this bookcard component. But there's two things I want to highlight. First, when we're accessing properties on the prop in the template, we don't get any IntelliSense to tell us which properties are on the book. And I can demo that by deleting the title down here. And then I'm going to put a full stop after the book and we don't see the properties. Second, as it stands, we could pass any prop that we wanted into this component, and there would be no checks or errors when we did so.
So I could come and pass another prop into the bookcard component, I don't know, called name, for example, and Astro would currently let me do that even though we're not using the name in that component. And we don't really want it. So to combat both of these things, we can use a TypeScript interface within the front matter of the component to define how the props should look. And the way we do that is by coming up here and saying interface. And we call this props with a capital P and then curly braces. And within this we can define what props should be allowed into this component and the fields and types of those props as well.
In our case we're allowing a book prop and the type of that is going to be an object where two properties need to exist. So curly braces first, right? Then we can say we want a title property on the object which is going to be a string and we also want an author property on the object which should be a string as well. And now Astro will automatically pick this props interface up and check that the correct props are being passed into the component. And now if we try to pass an additional prop in, which I'm going to go back over here and show you, then we're going to get an error because that prop wasn't defined on the component.
Right? Also because we defined that props interface, we now get IntelliSense when we use it in the template, which I can show you by coming back and deleting the title field again. And then I'm going to put a dot after book. And when we do that, this time we can see the two properties available to use. All right, then. So we've made a reusable component now. And we've seen how to pass a prop into that component.
More from Net Ninja
Get daily recaps from
Net Ninja
AI-powered summaries delivered to your inbox. Save hours every week while staying fully informed.









