@open-press/core

useSource

React hook that reads a registered MDX source from the Press tree's resolved source map. Synchronous, safe to call anywhere inside <Press>.

Hook Impl

# useSource(id)

Reads a resolved source by its registered key. The engine populates sources synchronously before rendering, so this hook never returns null — it throws if the id is unknown.

import { useSource } from "@open-press/core";
function useSource<T = ResolvedSource>(id: string): T

Parameters

Name Type Default Description
id required string The source id passed to mdxSource() inside a <Press sources> array. Case-sensitive; must match exactly.

Returns

Name Type Default Description
ResolvedSource object The fully resolved source — its blocks, metadata, anchor map, and per-block source mapping. Type-parameterizable via useSource<CustomShape>(id) when you've extended the registration.

Throws

Name Type Default Description
Outside <Press> Error If called from a component that isn't rendered inside the <Press> subtree. The error message tells you which source you tried to read.
Unknown source id Error If id doesn't match any registered source. The error lists all known source keys to help you spot typos.
Reading a registered source
import { useSource } from "@open-press/core";

function CustomTableOfContents() {
  const story = useSource("story");
  return (
    <ul>
      {story.sections.map((s) => (
        <li key={s.id}>{s.title}</li>
      ))}
    </ul>
  );
}
Type-parameterized read
import { useSource } from "@open-press/core";
import type { ResolvedSource } from "@open-press/core";

interface StorySource extends ResolvedSource {
  sections: Array<{ id: string; title: string; chapterCount: number }>;
}

function ChapterCounts() {
  const story = useSource<StorySource>("story");
  return story.sections.map((s) => (
    <div key={s.id}>{s.title}: {s.chapterCount} chapters</div>
  ));
}

When to use it

  • Custom frame helpers — when you're writing your own <Sections> replacement or a wrapper around the manuscript helpers, this is how you read the source.
  • Custom TOC — when the bundled <Toc> doesn't fit and you need to render section titles / page numbers from scratch.
  • Metadata-driven chrome — page headers, footers, or covers that need to read author / version / section counts from the source registration rather than from config.

When NOT to use it

  • Inside MDX prose — MDX blocks already render in source context; use the block-level props instead of re-reading from the hook.
  • Outside <Press> — the hook throws. If you need source data outside the document tree, read the exported sources from press/index.tsx directly.

Related