Get Started
Tome is a library of Payload + Next.js building blocks — block packs (the things authors drop onto a page) and capability layers (Commerce, CRM, Learning, and the rest) — that you install into your own app from Wabbit's private npm registry. You keep your codebase; Tome is a set of packages you pull in, wire up, and own.
This guide takes a developer who knows Payload and Next but has never seen Tome from a fresh account to a Tome block rendered on a page. Every command here is real and copy-pasteable, and we test this exact path against a brand-new Payload site before every blocks release.
Before you start
You need a Payload 3 + Next.js app to install into — the one you already have, or a fresh one from Payload's own website template (npx create-payload-app -t website). Tome doesn't replace your project; its blocks drop in next to the ones you already use.
You'll want Node 20+ and your app running locally (npm run dev) so you can see blocks render as you go.
Create a free account
Sign up at /signup — no card. Two of the block packs, marketing-starter and content-writer, are free, so you can complete this whole guide before deciding to buy anything. Everything else (the Commerce, Learning, and Org packs, the Signal theme, and the rest) needs an active plan or pack — see the block catalog and plans.
Get an install token
Every install from the registry needs a token — free packs included. Once you're signed in, go to Account → Credentials. On a new account, claim the free license there and generate your key in the same card. Later tokens come from the Blocks · Registry install tokens section; give each a label (one token per client site is the intended pattern).
We show the raw token exactly once, at creation. We store only a hash of it — we can't recover or re-display it. If you lose it, generate a fresh one (that supersedes the old). You can suspend a token (pause it, reversible) or revoke it (kill it for good) from that same page at any time — no call, no waiting on us.
A token is scoped to what your account holds. A free token installs the two free packs and everything they depend on; a plan or a purchased pack widens the same token to cover what you bought.
Configure npm
Point the @wabbit scope at the Wabbit registry in your project's .npmrc:
@wabbit:registry=https://npm.wabbit.com/Then put your token in your user-level ~/.npmrc, not the project one, so it never lands in your repository:
//npm.wabbit.com/:_authToken=YOUR_TOKEN_HEREThe token is a secret. In CI, inject that line from an environment variable at build time rather than committing it.
Install your first pack
We'll use the free marketing-starter pack so this works before you buy anything:
npm install @wabbit/tome-blocks-marketing-starterThat one command is the whole install. Every pack declares @wabbit/tome-blocks-core (the block system itself) and the design-token package @wabbit/tome-ui as required peers, and npm installs required peers automatically. You end up with exactly one copy of each.
Load the design tokens
One line in your site's global CSS:
@import '@wabbit/tome-blocks-core/styles.css';Tome blocks are styled with design tokens. Skip this line and they render as bare, unstyled HTML.
Add the blocks to a field
Every pack exports its blocks as descriptors. .block() returns a real Payload Block config, so add the ones you want to your Pages collection's blocks field, next to whatever it already has:
import { pricingBlock, faqBlock } from '@wabbit/tome-blocks-marketing-starter'
// in your Pages collection:
{
name: 'layout',
type: 'blocks',
blocks: [...existingBlocks, pricingBlock.block(), faqBlock.block()],
}Run payload generate:types afterwards so your generated types know about the new blocks.
Render them on a page
Pack blocks lay themselves out on Tome's page grid, so render them through RenderBlocks with the grid class on its container. Most Payload sites pass block fields as spread props (<Block {...block} />); adaptRenderersForPayload turns a pack's renderers into components that accept that shape:
import { renderers } from '@wabbit/tome-blocks-marketing-starter/render/register'
import { adaptRenderersForPayload, RenderBlocks } from '@wabbit/tome-blocks-core/render'
import gridStyles from '@wabbit/tome-ui/grid'
const blockComponents = {
...yourExistingComponents,
...adaptRenderersForPayload(renderers),
}
<RenderBlocks
blocks={page.layout}
components={blockComponents}
gridClassName={gridStyles.grid}
/>The grid is what gives every block its gutters and its full-width placement. Leave it out and nothing errors, but blocks sit flush against the edge of the screen. Rich text and images render with no extra setup, as long as your page query populates uploads (depth 1 or more, which Payload's templates already do).
Leave defaultColumnSpan unset for pack blocks. They place themselves on the grid's named lines, and narrowing every wrapper to the content columns cuts off the lines their full-width bands reach for. The width & breakout doctrine explains how blocks choose their width.
Create a page in /admin, drop a pack block into its layout, publish, and load the page — the block renders. That's the whole loop: account → token → install → design tokens → field → render. The blocks-core reference has every option, including swapping in your own image or link component.
Coming from Payload's website template
- Block names that collide. The template already registers blocks named
ctaandbanner, and so does marketing-starter (content-writerandextrasadd three more:archive,content,code). Rename just the Tome ones withapplyBlockSlugOverridesandremapRendererSlugsfrom@wabbit/tome-blocks-core/slugOverrides, passing the same map to both. Your existing content is untouched. - The global CSS file is
src/app/(frontend)/globals.css. - Type the template's block map. In
src/blocks/RenderBlocks.tsx, annotateblockComponentsasPartial<Record<string, React.ComponentType<any>>>and delete the@ts-expect-errorcomment above<Block {...block} />, or the build fails once pack renderers are merged in. - Swap its render loop for
RenderBlockswith the grid class, as above. The template's own loop wraps each block in adivthat breaks the grid.
Where to go next
Once the loop works, the capability quickstarts add a business system on top of it:
- Commerce quickstart — a product catalog and checkout, with the Commerce block pack on the front.
- CRM & Marketing quickstart — capture a lead and land it as a CRM contact.
- Learning quickstart — a course shell with the Learning block pack.
- Versioning & updates — what your subscription's update promise actually covers.
Stuck on anything? Support is a real person reading email.