Installation
Install the Scribekit package, wire up its stylesheet, and link the Claude Code skills.

This page gets the package and the Claude Code skills installed in an existing Next.js App Router project. It stops there: to build your first page, follow Quickstart; for what the pieces are, read Getting started.
Install the package
Install Scribekit together with next-mdx-remote, which renders the MDX bodies:
npm install @daanvandenbergh/scribekit next-mdx-remote
Scribekit declares four peer dependencies. Your project supplies them:
| Peer dependency | Range | Notes |
|---|---|---|
next | >=14 | Optional peer. Required in practice: the components target the App Router |
react | >=18 | Required peer |
react-dom | >=18 | Optional peer |
next-mdx-remote | ^5 || ^6 | Optional peer. Required to render any post or docs page body |
The optional markings keep npm quiet for consumers who only import the Blog or Docs class in a script. If you render pages, install next-mdx-remote.
Everything else the package needs at runtime - @daanvandenbergh/i18nkit, fuse.js, gray-matter, remark-gfm, and server-only - is a real dependency and arrives with the install.
Import the stylesheet once
Import the stylesheet in your root layout, not in each page. It is a global sheet, and importing it more than once is wasted work:
// app/layout.tsx
import "@daanvandenbergh/scribekit/styles.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
The package sets sideEffects: ["**/*.css"], so bundlers will not tree-shake the import away.
Set metadataBase
Docs.docMetadata and Blog.postMetadata already emit their own metadataBase from the siteUrl you pass the instance. Set one in the root layout as well, so relative URLs elsewhere in your app resolve against the same origin:
// app/layout.tsx
export const metadata = {
metadataBase: new URL("https://example.com"),
};
Use the same origin you give the instance. A mismatch produces canonical URLs that disagree with your other pages.
Link the Claude Code skills
The skills ship inside the npm tarball. Symlink each one into .claude/skills/ so Claude Code picks it up:
mkdir -p .claude/skills
ln -s ../../node_modules/@daanvandenbergh/scribekit/skills/scribekit-blog .claude/skills/scribekit-blog
ln -s ../../node_modules/@daanvandenbergh/scribekit/skills/scribekit-docs .claude/skills/scribekit-docs
ln -s ../../node_modules/@daanvandenbergh/scribekit/skills/scribekit-hero .claude/skills/scribekit-hero
ln -s ../../node_modules/@daanvandenbergh/scribekit/skills/scribekit-docs-github-pages .claude/skills/scribekit-docs-github-pages
Check the links resolve:
ls -la .claude/skills/
Each entry should point at its target under node_modules/@daanvandenbergh/scribekit/skills/. A broken arrow means the package is not installed, or the relative path does not climb far enough out of .claude/skills/.
Link only what you need. scribekit-hero and scribekit-docs-github-pages each stand alone, so you can skip either. The two content skills are the exception, and the next section says why. See Skills for what each skill does.
Install scribekit-docs and scribekit-blog together
scribekit-docs depends on scribekit-blog. It reads two files from it, house-style.md for voice and MDX rules and research-protocol.md for how it sources facts, and it stops when it cannot resolve them at any of three locations, in order: a sibling scribekit-blog link, .claude/skills/scribekit-blog/ from the project root or $HOME, or node_modules/@daanvandenbergh/scribekit/skills/scribekit-blog/.
That last fallback means the package you installed in step 1 already satisfies the dependency, so linking scribekit-docs alone still runs. Link both anyway - the sibling link is what keeps working if the skills are ever copied out of a project that has no scribekit install. The same three-location fallback applies to scribekit-hero, which scribekit-blog and scribekit-docs hand off to for hero images.
Add the CLAUDE.md rule
The package also ships one CLAUDE.md rule snippet, rules/docs_parity.md: docs and README.md are updated in the same change as the code, never deferred. Claude Code inlines any @path reference in CLAUDE.md at load time, so point it straight at the file in node_modules and the text auto-updates with the package:
@node_modules/@daanvandenbergh/scribekit/rules/docs_parity.md
The path is relative to CLAUDE.md, so keep CLAUDE.md at the project root, next to node_modules. Unlike the skills, a rule needs no symlink.
Create the content directory
Each surface reads one directory, with one subfolder per page:
mkdir -p docs
A missing content directory is not an error: the reader returns no pages until the folder exists. contentDir resolves against process.cwd(), the directory holding the package.json you run Next from, so "./docs" means <project-root>/docs/.