Reading
Get collections, documents and slugs.
Everything is built ahead of time, so reading is synchronous. Import collections from server code only: in the browser bundle, their documents would ship to the client.
Collections
Each collection is exported under its name in your config:
import { posts } from "tomekit/content";
posts.documents(); // every postA module bundles only the collections it imports, so a page that reads posts doesn't load your other collections.
Names known at runtime
When the collection's name is a string, eg a route param, read it from collections. It returns the same collection objects. has narrows a string to a collection name, and a plain string returns the collection or undefined:
import { collections } from "tomekit/content";
collections.names(); // ["docs", "posts"], in config order
collections.get(params.collection); // a collection, or undefined
if (collections.has(params.collection)) {
collections.get(params.collection).documents();
}Reading through collections bundles every collection, since the name could be any of them. So for a name you know in code, import the collection: collections.get("posts") works, but ships your other collections too.
Documents
posts.documents(); // every document, in the loader's order
posts.slugs(); // every slug, in the same order
posts.get("hello-world"); // the document
posts.get(params.slug); // the document, or undefined
posts.get("helo-world"); // doesn't compileget follows the same rule as for collections: a slug that exists returns the document, a misspelled slug doesn't compile, and a plain string might return undefined. has narrows a string to a slug:
if (posts.has(params.slug)) {
posts.get(params.slug).metadata.title;
}Every document has four fields:
slug: its key in the collectionmetadata: the schema's output, or whattransformreturnedbody: the text after the frontmatter, or whattransformreturned, eg a module's path for MDXfile:{ path }, relative to the project root, orundefinedwhen its loader gave no file
documents() returns a plain array, so sort and filter it like any other:
const latest = posts
.documents()
.toSorted((a, b) => b.metadata.date.getTime() - a.metadata.date.getTime());To list every document, combine names() and get():
collections.names().flatMap((name) => collections.get(name).documents());Types
The plugin writes the types to .tomekit and rewrites them when content changes.
import type { CollectionName, DocumentOf, SlugOf } from "tomekit/content";
const name: CollectionName = "posts";
const slug: SlugOf<"posts"> = "hello-world";
function title(post: DocumentOf<"posts">) {
return post.metadata.title;
}- Leave the name out to mean any collection, eg
DocumentOffor a document from any collection. - Read a part of a document from
DocumentOf, egDocumentOf<"posts">["metadata"].
For a helper that works with any collection whose documents fit, type it as Collection from tomekit:
import type { Collection } from "tomekit";
function titles<TDocument extends { metadata: { title: string } }>(
collection: Collection<TDocument>
) {
return collection.documents().map((document) => document.metadata.title);
}
titles(posts);