How to build an Astro collection loader
A few days ago Astro released version 1.14 which introduced a new feature called the “Content Layer API”. This feature builds on the existing content collections feature and instead expands it so you can use data from sources other than local files within the Astro project repository.
Now, to get started the Astro team has already published a number of loaders to deal with the most common possible cases you may need. Including “feeds” like RSS feeds, CSV files, etc. But what if you wanted to build your own? Well it’s actually quite simple.
Setting up Astro
First things first, you need to set up a new Astro project. You can do this by running the following command:
This will walk you through a very fancy CLI guide to set up your project.
Once you have done that, you can run the following command to start your project:
With this up and running you can visit http://localhost:4321
to see your new Astro project.
Enable the experiment
Next, you will need to make one slight tweak to the Astro configuration file to enable the Content Layer API as it’s currently still experimental.
To do this, open the astro.config.mjs
file and add a experimental
object with a contentLayer
key set to true
like so:
The basic structure
With the experimental API enabled we can now actually start to build out the basic structure for a collection loader.
Now, for the sake of example I’ll be using TypeScript but it’s not strictly required.
First up, create a new file in your project. I’ll call mine src/loaders/jokes.ts
. This file will be responsible for loading in a collection of posts.
At its most basic premise a loader is an object with a 2 required properties & one optional property:
name
(Required): This will be the name of the loader and how it will show up in logs and such.load
(Required): Here is the actual “loader logic” function where you actually fetch the data from whatever source you need. This function exposes a loader context parameter which can be used to access things like thestore
where the data will actually get stored,logger
for logging, etc.schema
(Optional): If you want to provide a Zod schema to validate the data after it’s been fetched you can do so here.
Fetch some data
Now we need some data, let’s use this dad joke API to get a bunch of random dad jokes.
To do this in the load
function all we need to do is make a fetch
request. For this API we just need to make sure we set the Accept
header to application/json
to get the data in JSON format.
I’ve added a console.log
statement for now just so we can check it works. But how do we do that?
Using the loader
With some actual logic in the loader we can hook it up to a collection to see what data we get back from the API.
To do this create the following file src/content/config.ts
:
With this we should now have a new collection called jokes
that we can access in our Astro project.
If we run a build of the project with npm run build
we should see the loader being run and the data being logged to the console.
Perfect, we can see our loader ran by the [jokes]
log message and the data being returned from the API. Additionally it confirms the data structure we get back.
Store the data
Now we have some data we need to actually store it so we can access it in our Astro project.
To do this we can use the store
scoped data store that is available on the context
parameter. This ScopedDataStore
appears to be some form of a superset of a regular Map
object.
When actually setting the data you need to provide a unique id
for the data, along with the data itself. This works quite well for us here as the API gives us an id
field for each joke.
Accessing the data
Since we removed the logging builds will still succeed if you run npm run build
but we won’t see the data being logged anymore.
To actually access the data, you can access it like you would any other collection in Astro.
For example, in an Astro file you can use the getCollection
function to get the data.
Running npm run build
with the above added you should see something along the lines of:
And just like that it works! Now every time you build your Astro project it will fetch a new dad joke from the API and store it in the collection.
Conclusion
And that’s it! You’ve now built your own collection loader for Astro. This is a very basic example but it should give you a good starting point to build more complex loaders.
Later down the line this can be easily adapted into a function to return a loader so you could say take in some user options and publish it as a package for others to use.
I’m excited to see what other loaders people come up with now and in the future.