@stnd/loader
Overview
Content ingestion loaders for the Standard Ecosystem, built as custom Astro Content Collection Loaders.
ELI5
This is how an Astro site’s content collections point at something that isn’t a local src/content/ folder — an Obsidian vault (with wikilinks and frontmatter) or a Notion database. Define the collection once with the right loader, then use getCollection() like any normal Astro content collection.
Usage
Use it (vault):
import { defineCollection } from "astro:content";
import { vaultLoader } from "@stnd/loader-vault";
export const collections = {
vault: defineCollection({ loader: vaultLoader({ path: "../../vault/Atelier" }) }),
};
Loaders
1. Vault Loader (@stnd/loader-vault)
Loads content from a local directory containing Markdown files with Obsidian-style frontmatter, wikilinks ([[link]]), and media files.
Configuration (src/content.config.ts)
import { defineCollection } from "astro:content";
import { vaultLoader } from "@stnd/loader-vault";
const vault = defineCollection({
loader: vaultLoader({
path: "../../vault/Atelier", // path to the local Obsidian vault
flattenDirectories: false, // preserve directory structure in IDs
ignore: [".obsidian", ".trash", ".agent"], // directories to ignore
}),
});
export const collections = { vault };
Astro Dev Mode Workaround (Important)
In Astro 6.x/7.x development mode (astro dev), calling getCollection("vault") inside routes injected via injectRoute() (used by plugins/integrations) returns []. This is due to virtual module hydration issues inside Vite SSR context.
To work around this, the vault loader populates a global singleton that survives HMR and SSR code-splitting. Instead of using getCollection, import the vault singleton directly:
import { vault } from "@stnd/loader-vault";
// Wait for the vault to initialize (optional, useful in edge cases)
await vault.ensureLoaded();
// Access entries and metadata
const entries = vault.entries; // Array of VaultEntry
const size = vault.size; // Number of entries
const meta = vault.meta; // { validLinks, imageIndex, vaultPath }
// Find individual entries
const note = vault.getEntry("my-permalink");
2. Notion Loader (@stnd/loader-notion)
Synchronizes content from Notion databases into the Standard Ecosystem.
Configuration (src/content.config.ts)
import { defineCollection } from "astro:content";
import { notionLoader } from "@stnd/loader-notion";
const notion = defineCollection({
loader: notionLoader({
auth: import.meta.env.NOTION_API_KEY,
databaseId: import.meta.env.NOTION_DATABASE_ID,
}),
});
export const collections = { notion };
Notes / Observations
(jot down anything noticed here — quirks, gotchas, ideas)
Todo
- [ ] Evaluate
experimental.collectionStorage: 'chunked'for the vault collection — Astro 7.1.6 added a chunk-size option, and@astrojs/cloudflare14.1.7 fixed chunked-collection loading on the adapter. Only worth it if the vault store is actually large enough to justify it; measure the serialized store first rather than adopting on principle. Note this is unrelated to the dev-modegetCollectionworkaround (root README #1), which chunking does not address. [priority:: 2] [token_scale:: 3] [created:: 2026-08-07] [area:: framework]