Skip to content
Moku LabsDocs
@moku-labs/web pages

collection

Optional provider. (collection, shard) → JSON file: written at build, fetched on demand in the browser.

collection.mdllms.txt

What it does

Optional provider. collection owns one contract: a (collection, shard) key maps to one JSON file. On Node, write(entries) persists the shards your build script authored. In the browser, at(collection, shard) fetches and caches one of them.

It knows nothing about what the data is. A search index, a question bank, a dictionary: you pick the shape. It is the collection-keyed sibling of the page-keyed data plugin.

How it works

urlFor and fileFor both come from one function, so the file write creates is exactly the URL at fetches. The shard key may contain /, which becomes nested folders. Outer slashes are trimmed.

(collection, shard)fileForurlFor with baseUrl: "/"
("bank", "ru")bank/ru.json/bank/ru.json
("bank", "en/animals")bank/en/animals.json/bank/en/animals.json
("/bank/", "/en/")bank/en.json/bank/en.json

write serializes each shard's data with JSON.stringify, at most 8 files at a time. Its node:fs writer is loaded lazily, so composing the plugin in a browser bundle pulls no node:* module. at returns null when the fetch or the parse fails, so the caller can fall back.

Config

pluginConfigs.collection.

OptionTypeDefaultDescription
baseUrlstring"/"The URL prefix the browser fetches shards from. Must end with /.

API

Mounted at app.collection, reachable with ctx.require(collectionPlugin).

MethodSignatureDescription
write(entries: readonly CollectionShard[], options?: { outDir?: string }) => Promise<CollectionWriteSummary>Node. One file per entry. outDir defaults to ./dist. Resolves to { fileCount, bytes, files }.
at(collection: string, shard: string) => Promise<unknown | null>Browser. Fetches and caches one shard. null on failure.
urlFor(collection: string, shard: string) => stringThe fetch URL.
fileFor(collection: string, shard: string) => stringThe outDir-relative file path.

CollectionShard is { collection: string; shard: string; data: unknown }.

Events

Emits

None.

Listens to

None.

Depends on

Nothing. The relationship to the build is a call you make: write the shards after app.build.run(), which deletes outDir first.

Example

scripts/build.ts
import { buildPlugin, collectionPlugin, createApp, defineRoutes, route } from "@moku-labs/web";
import { h } from "preact";

const words = { en: ["cat", "dog"], uk: ["кіт", "пес"] };

const routes = defineRoutes({ home: route("/").render(() => h("h1", null, "Words")) });

const app = createApp({
  plugins: [collectionPlugin, buildPlugin],
  pluginConfigs: {
    site: { name: "Words", url: "https://words.dev", author: "Ada", description: "A word game." },
    router: { routes },
    build: { outDir: "dist", feeds: false }
  }
});

await app.build.run();
const summary = await app.collection.write(
  Object.entries(words).map(([locale, list]) => ({ collection: "bank", shard: `${locale}/animals`, data: list })),
  { outDir: "dist" }
);
console.log(summary.files); // ["bank/en/animals.json", "bank/uk/animals.json"]
  1. After the build: build.run() empties outDir first.
src/words.ts
import { collectionUrl, loadCollectionShard } from "@moku-labs/web/browser";

export async function loadWords(locale: string): Promise<string[]> {
  return loadCollectionShard<string[]>("/", "bank", `${locale}/animals`);
}

export const englishUrl = collectionUrl("/", "bank", "en/animals"); // "/bank/en/animals.json"
  1. Throws on a non-OK response. Wrap it when a miss is expected.
  • collectionPlugin is not exported from @moku-labs/web/browser in 2.4.11. In the client bundle use loadCollectionShard and collectionUrl, which are.
  • at returns unknown. There is no validation step. Check the shape before you trust it.
  • loadCollectionShard throws; at returns null. Pick the one whose failure mode fits the caller.
  • baseUrl must end with /. Otherwise createApp throws [web] collection.baseUrl: must be a URL prefix ending with "/" (e.g. "/" or "/cdn/").