Colocate modules with pages
🌱 This post is in the growth phase. It may still be useful as it grows up.
Colocate modules in pages directories
Put modules that share getter functions and types inside nested /pages
directories.
/src /pages /my-collection /index.astro /[collection_slug].astro /collection.ts
Astro has a “generation one” /pages
directory.
Every .astro
, .md
, and .mdx
file becomes a page on your site.
Unlike other gen 1 /pages
directories (like those in Next.js, pre App Directory), Astro doesn’t read .js
or .tsx
modules as pages.
This means you can colocate collection-type specific code there.
Here’s what mine look like, at the moment.
import * as ASTRO_CONTENT from 'astro:content'import * as COLLECTION from '#modules/collection'import {z, defineCollection} from 'astro:content'
// Used as both type and valueexport const COLLECTION_NAME = 'decisions'
export type CollectionEntry = ASTRO_CONTENT.CollectionEntry< typeof COLLECTION_NAME>
// Collection-aware getCollection facade.// Proxies `filter` and adds `sort` argument.export async function getCollection( filter = () => true, sort = compareCollectionByDate): Promise<CollectionEntry[]> { const result = await ASTRO_CONTENT.getCollection( COLLECTION_NAME, filter )
return result.toSorted(sort)}
// ContentEntry aware sort facadeexport function compareCollectionByDate( a: CollectionEntry, b: CollectionEntry) { return COLLECTION.compareByDate(a.data.date, b.data.date)}
// Content collection schema// Utilized by config.tsexport const collectionSchema = defineCollection({ schema: z.object({ /* ... */ }),})
You may see immediate value you this. You may not. I’ll do my best to make the benefits clear in other patterns.