Document types
The room writes Posts by default. To write other kinds too, list their document types:
writingRoom({
types: ['post', 'caseStudy'],
})
Fields
The room reads each type’s schema to find what it writes:
| It looks for | If there’s none | |
|---|---|---|
| Title | title, else the field the type’s preview shows as its title, else the first string field |
The type is left out |
| Body | body, else content, else the first portable text field |
The type is left out |
| Slug | slug, else the first slug field |
No slug is settled on publish |
| Published date | publishedAt, else the first date field whose name contains “publish” |
No date is stamped on publish |
| Cover image | coverImage, else mainImage, else the first image field |
No “Add a cover image” nudge after a publish |
If it guesses wrong, name the field: {type: 'article', fields: {body: 'content', title: 'headline'}}. Every other field (excerpt, tags, a client name…) shows up under Details, with nothing to configure.
Details
Details in the room’s controls swaps the body for the document’s other fields, on one page in the order your schema gives them. The title stays where it is, and the arrow or Esc goes back to the writing.
- Simple fields get the room’s own inputs: strings, text, numbers, booleans, dates, slugs and tag lists.
- Everything else is Sanity’s own input, looking as it does in the rest of your Studio: references, images, files, arrays of objects, and lists of choices. With the matching theme they sit closer to the room’s look.
- Your custom inputs are used as they are. A field with its own
components.inputorcomponents.fieldis never replaced. - List the Writing Room last in
pluginsif another plugin wraps every input. For simple fields the room’s inputs take the place of Sanity’s, which ends Sanity’s chain of input components there. A plugin listed before the Writing Room still wraps the room’s inputs in Details; one listed after it, and aform.components.inputin your own Studio config, does not. Everything still appears in the Structure form. - Your schema’s rules apply:
hidden,readOnlyand validation behave as they do in the standard form. Field groups are not shown as tabs; fieldsets are kept. - A type with only a title and a body has no Details button.
Details are saved as you type, like the writing. If a required field blocks a publish, the room opens Details at that field.
If the Details view can’t be shown in your Studio, the room says so and offers Open in Structure instead.
The body
The editor is built from the body field’s own type, so the room only offers what that type can store. A blockContent with headings, quotes, bullets, links and images gets exactly those: no code blocks, embeds or numbered lists in the Insert Menu, selection bubble or markdown shortcuts. Image description and caption inputs appear only when your image type has alt and caption fields.
To offer the room’s own blocks (YouTube/Vimeo/Spotify embeds, code blocks, section breaks), add them to your body type. The plugin registers them for you, under prefixed names that can’t clash with yours:
import {writingRoomBlocks} from 'sanity-plugin-writing-room'
defineType({
name: 'blockContent',
type: 'array',
of: [{type: 'block'}, {type: 'image'}, ...writingRoomBlocks],
})
Your site then renders them as writingRoomEmbed, writingRoomCodeBlock and writingRoomSectionBreak. (The starter writingRoomSchemaTypes uses the original names, embed, codeBlock and sectionBreak; the room handles both.)
Blocks of your own that the room doesn’t know (a callout, a product card…) keep their place in the text as a quiet placeholder: the Writer can move or delete them, and Edit in Structure opens that block in the standard form.
Labels and URLs
The Lobby’s New button starts a document of your type (“New Post”); with several types it asks which. Recent writing lists them together. The room names each type with its schema title (“Case Study”). If a name comes out wrong, set it yourself:
writingRoom({
types: ['post', {type: 'news', title: 'News', pluralTitle: 'News'}],
})
| Option | Default | What it does |
|---|---|---|
types |
['post'] |
The document types the room writes, as names or {type, title?, pluralTitle?, fields?}. |
types[].title |
the schema type’s title |
What one is called: “New Case Study”. |
types[].pluralTitle |
title made plural |
What several are called: “Case Studies”. |
types[].fields |
detected | {title?, body?, slug?, publishedAt?, image?}: field names, when the room guesses wrong. |
The first type is the default: its documents open at /writing-room/<id>, the others at /writing-room/<type>/<id>. A Studio with one type keeps short URLs, and links to it keep working if you add more types later, as long as it stays first.
If a type in types isn’t in your schema, or has no title or body the room can find, the room leaves it out and says why in the browser console. Slugs are unique within a type, so a Post and a Case Study can both be hello-world.