Following up on my last post, I thought I’d post some code samples that might help other uses make sense of using Astro and NocoDB.
Firstly get the latest version and enable the experimental Content Layer feature in the astro config file. This won’t be needed when version 5 drops.
Context: I’m building a little tracker site for my art supplies, so the code will reflect that.
// src/content/config.ts
import { defineCollection, reference, z } from 'astro:content';
const supplies = defineCollection({
loader: async () => {
const response = await fetch('NOCODB URL', {
headers: {
Accept: "application/json",
"xc-token": "AUTHENTICATION TOKEN",
},
});
const data = await response.json();
// Must return an array of entries with an id property, or an object with IDs as keys and entries as values
return data.list.map((supply: any) => ({
id: supply.Id.toString(), //id has to be a string not a number
name: supply.Name,
mediumName: supply.Medium.Name,
rangeTitle: supply.Range?.Title,
hue: supply.ColourGrouping,
...supply,
}));
},
// optionally define a schema using Zod
schema: z.object({
id: z.string(),
name: z.string(),
mediumName: z.string(),
hue: z.string(),
rangeTitle: z.string().optional(),
// ...
}),
});
export const collections = {
supplies,
};
Okay now the front matter of an index view:
import { getCollection, getEntry } from 'astro:content';
const allSupplies = await getCollection('supplies');
Ultra dirty nasty unordered list of items in the collection:
<ul>
{allSupplies.map((item: any) => (
<li><a href={item.data.id}>{item.data.Id} {item.data.name} {item.data.mediumName} {item.data.hue}</a></li>
))}
</ul>
Here’s the [id].astro file that generates individual pages out of each record:
---
import type { GetStaticPaths } from "astro";
import { getCollection, type CollectionEntry } from "astro:content";
import Layout from "../../layouts/Layout.astro";
export const getStaticPaths: GetStaticPaths = async () => {
const supplies = await getCollection("supplies");
return supplies.map((supply) => ({
params: {
id: supply.id,
},
props: { supply },
}));
};
type Props = { supply: CollectionEntry<"supplies"> };
const { supply } = Astro.props;
---
<Layout title={supply.data.name}>
<h1>{supply.data.name}</h1>
</Layout>
Pretty bare bones but it works, should be enough to build on? Hope this helps people out anyway. I might stick this post on the astro subreddit too.