TrademarkTrademark
Ctrl k
Search docs...
Guides
Surfaces

Journal

Long-form reading: books as directories of chapters, with a reading view and optional narration.
The journal surface publishes books. A book is a directory, a chapter is an MDX file inside it, and one books.json holds the order and the jacket copy. It requires no slices and runs on zero environment variables. Its files, listed in composition/surfaces/journal.json, are src/app/(journal), src/lib/journal and src/content/journal. It serves /journal and declares rootRedirect: "/journal" for compositions where nothing else serves /.
  • /journal — the shelf, one cover per book. A cover links to the book's first chapter.
  • /journal/<book> — the book: cover, subtitle, author and chapter list.
  • /journal/<book>/<chapter> — the reading view.
  • /journal/about — the author, read from books.json.
  • Create a directory under books/. Its name is the book's id and its URL segment.
  • Add one .mdx file per chapter, with title, summary, order and publishedAt in the frontmatter. Chapters sort by order, then by title.
  • Add an entry to books in books.json with the same id and a title, subtitle, author, cover and summary.
The directory is what makes a book exist. A book in books.json that has no chapter files is dropped, so deleting a directory never leaves a dead route. A directory missing from books.json still appears, after the listed books, with a title made from its name. A malformed books.json falls back to the directories on disk. A chapter page has the book and chapter title, a heading rail built from the chapter's headings, a reading-progress dial, the book's table of contents, share links, a newsletter form and a previous/next pager. Narration is optional, chapter by chapter. Set audio to a file under /public and, if you want jump points, narrationChapters as a list of { start, title }. The chapter then gets a narrator that docks to the bottom of the viewport, and each paragraph is highlighted while it is being read. The chapter page passes no timing data, so the audio is split evenly across the paragraphs. NarrationProvider accepts a timings prop for per-paragraph timing from a transcription. A chapter with no audio just shows the text. None of the sample chapters ship with audio. The newsletter form in JournalNewsletter.tsx is not connected to anything. Submitting it says that no mailing provider is configured. Connect its submit handler to your provider. The 3D cover (components/Book.tsx) and the narrator (Narrator.tsx, NarrationContext.tsx) are local to this surface. The comments in journal.json and Book.tsx say core is pinned to 1.8 and describe these as waiting for core 2.0. That is out of date: package.json now depends on @once-ui-system/core ^2.1.0-rc.0, which exports Book and MediaAudioPlayer (with an onTimeUpdate callback). Neither is imported yet. Switching to them means changing the import in BookCard.tsx and deleting the local Book.
Last updated October 18, 2026
Edit this page on GitHub