Working with Content
Use the EmDash admin to take an entry from its first draft to a published page. The editor keeps draft changes separate from the version visitors can see, so saving and publishing are two distinct actions.
Open a collection
Section titled “Open a collection”Open /_emdash/admin on your site and sign in. Select a collection, such as Posts or Pages,
in the sidebar.
The collection page lists its entries. From here you can:
- select Add New to create an entry;
- search by the entry title, slug, and fields marked as searchable;
- filter by publishing state, author, byline, date, and locale;
- move between pages of entries and choose whether a page shows 20, 50, or 100;
- select entries for bulk publishing, returning to draft, or moving to Trash; and
- open Trash to restore or permanently delete an entry.
The fields and publishing features available in the editor depend on the collection’s content model. For example, a collection may support revisions, previews, taxonomies, or search.
Create and publish an entry
Section titled “Create and publish an entry”-
Select Add New on the collection page.
-
Complete the required fields. If the collection has a title field, EmDash uses it to suggest a slug. You can edit the slug before publishing.
-
Add the body and any supporting fields, such as an excerpt, featured image, byline, categories, or tags.
-
Select Save. The first save creates the entry as a draft and opens its permanent editor URL.
-
Review the draft. If the collection supports previews, select Preview to see the rendered page before publishing.
-
Select Publish now, then confirm. The saved draft becomes the live version that public content queries return.
The entry has a stable content ID and a separate slug. The ID continues to identify the same entry
if its slug changes. Templates normally use the URL-facing identifier returned by
getEmDashCollection(); the querying content guide
explains both values.
Write rich text
Section titled “Write rich text”Portable Text fields provide a block editor for headings, paragraphs, quotations, lists, links, images, galleries, code blocks, tables, HTML blocks, and reusable sections. Installed plugins may add more blocks.
Use the toolbar to format the selected text. To insert a block, select the add-block control beside
a paragraph or type / and search for a block by name. Image and gallery blocks open the same media
picker used by image fields.
You can also drag image files into the editor or paste a copied image or screenshot. Each image uploads to the Media Library and appears between the surrounding blocks when the upload finishes. If an upload fails, the reason appears where the image would have gone.
When you select an image block, a toolbar appears above it. Use it to replace the image, edit its alt text, align it, add a link, or delete the block. The Alt text button is highlighted once the image has a description, and hovering it shows the description. Alt text that is only a Media Library image’s file name doesn’t count. Type a caption in the field under the image, and press Enter to keep writing below it. From a selected image, Tab moves to the caption and then the toolbar.
Image settings in the toolbar opens every setting for that use of the image, including its display size and optional tooltip. Edit asset there opens the underlying Media Library item, where changing or replacing the asset can affect other entries that use it. See Media Library for that distinction.
Add HTML, CSS and JavaScript
Section titled “Add HTML, CSS and JavaScript”An HTML block holds code the other blocks can’t express, such as an embed, a signup form or a small
widget. Its tabs are HTML, CSS, JS and Preview. Each code tab is a code editor where
Tab indents; press Escape to return to the surrounding text. The CSS and JS tabs are
optional: you can also paste a whole snippet, with its <style> and <script> elements, into the
HTML tab.
Preview shows the block as your site renders it. When you open an entry, a block that runs JavaScript waits until you select Run preview, so a broken script can’t freeze the editor.
The block’s menu sets how your site renders it:
- Isolated frame runs the block’s HTML, CSS and JavaScript in a sandboxed frame that grows with
its content. The frame can’t read your site’s cookies, storage or pages, and your site’s styles
don’t reach it. Relative links resolve from your site’s root. After a visitor clicks inside the
frame, it can open other pages in the visitor’s tab or a new one. New HTML blocks use this mode,
but blocks pasted from another website or browser tab don’t. Don’t size content to the frame’s
viewport, as with
height: 100vh: the frame grows to fit it, which makes the content taller again, until the frame reaches 20,000 pixels. - Inline puts the HTML into the page, where it uses your site’s styles. Your site keeps text
formatting, links, lists, tables, images and iframes, and removes other markup, such as scripts,
<style>elements,styleattributes, media and form controls. Iframes from sites other than YouTube and Vimeo are emptied. An inline block has no CSS or JS tab.
Search engines may not treat text inside an isolated frame as part of the page. Put text that matters for search in paragraphs or an inline block.
Embed a page from another site
Section titled “Embed a page from another site”An iframe block shows a page from another site, such as a video, a map or a form. Type /iframe,
then paste the site’s embed code or a link into the Code tab. YouTube and Vimeo links become
their players, and any other https link is embedded as it is. Preview shows the embedded page.
When you open an entry, a saved block waits until you select Load preview, so the admin doesn’t
load other sites’ pages until you ask. Iframe blocks pasted from another website or browser tab
arrive empty.
Only https pages can be embedded, and the block keeps only the parts of an embed code it needs: the address, the title, the size, full-screen support and the permissions players use. Some sites refuse to appear inside another site’s page; their preview stays blank or shows an error from that site.
An embed code that runs a script instead of an iframe, such as some social media posts, belongs in an HTML block.
Save draft changes
Section titled “Save draft changes”After the first save, the editor autosaves changes two seconds after you stop typing. The Save button changes through Saving… to Saved so you can confirm that the server accepted the draft. Autosave replaces the current autosave revision instead of filling revision history with a checkpoint for every pause.
Select Save when you want a point in the editing sequence to remain in revision history. If a save fails, the editor keeps the unsaved fields in place and shows the error. Do not leave the page until the button returns to Saved or you have copied the unsaved work elsewhere.
For a published entry, saving changes updates its draft only. Visitors continue to receive the previous live revision. Use Preview draft to check the pending version, Live View to check the public version, and Publish changes when the draft is ready to replace it.
Changing the slug of a published entry follows the same draft flow. The public URL changes when you publish the draft, not when autosave runs.
Work with another editor
Section titled “Work with another editor”Opening an entry takes an edit lock for that entry and locale. If another person already has it open, EmDash identifies the lock holder and offers two choices:
- Open read-only shows the entry without accepting edits, so you cannot type work that will be discarded.
- Take over gives you the lock. The other person keeps what they typed, but within two minutes their editor reports that you hold the entry. Their next save is refused.
The lock is renewed while the entry is open and released when you leave the editor or close the tab. If the browser or computer closes without releasing it, the lock expires seven minutes after its last renewal.
Locks are independent for each locale, so two people can edit different translations of the same entry. A script, API client, or MCP client is also refused while another editor holds the lock unless it uses the documented override. See Entry edit lock for the complete API behavior and Content lifecycle and bylines for the MCP tools.
An administrator can turn locking off for a collection under Content Types, then the collection, then Edit locking.
Publish or schedule changes
Section titled “Publish or schedule changes”Publishing and scheduling use separate controls:
- Publish now makes a new draft live after confirmation.
- Publish changes makes pending changes to a published entry live after confirmation.
- Schedule sets when a new entry or pending changes become live.
- Change schedule updates an existing schedule.
- Remove schedule cancels an existing schedule.
- Unpublish removes the live revision from public queries, cancels any schedule, and keeps an editable draft.
To schedule an entry, save it first, select Schedule below the publishing summary, and choose a future date and time. The editor displays the time zone used for the schedule. Until that time, the current live revision stays public; for a new entry, nothing is public yet.
Node.js deployments run the scheduled-publishing sweep automatically. Cloudflare Workers require a Cron Trigger. The Cloudflare starter templates include it; existing deployments can follow Scheduled publishing to verify the trigger.
Review the publishing calendar
Section titled “Review the publishing calendar”The calendar shows what was published and what is scheduled across your collections. Contributors and higher roles can open Calendar from the sidebar or the command palette. When something is scheduled, the dashboard’s Scheduled count also links to it.
The calendar has two views:
- Month shows a grid of days. Published entries appear as plain lines and scheduled entries as cards. Hover over or focus an entry to see its full title, state, time, and collection. When a day has more entries than fit, select +N more to list them all.
- Agenda lists the month by day, with each entry’s time. In the current month, days before today start collapsed unless one of them has an overdue entry, and a red line marks the present.
On a phone or another narrow screen, the calendar opens in Agenda, and Month shows a date picker with dots on the days that have entries. Select a day to list its entries.
Select an entry to open its details in a side panel, or Ctrl-click (Cmd-click on macOS) to open it in the editor in a new tab. The panel shows the entry’s state, time, collection, locale and translations, bylines, and when it was last edited. From the panel you can open the entry in the editor, preview scheduled changes, or view a published entry on the site. If you can publish the entry (Authors for their own entries, and Editors and higher roles for any entry), you can also reschedule it, remove its schedule, or publish an overdue entry now. On a phone, the panel opens as a sheet at the bottom of the screen.
Use Filter to narrow both views by collection and state, and by locale on multilingual sites. The filters, the view, the month, and the open entry are kept in the page URL, so you can bookmark or share it.
Entries are placed on days in the site’s time zone, which the calendar names beside the month. If your browser uses a different time zone, the calendar says so, and entry times also appear in your own time zone.
The calendar shows:
- published entries on the date they were published;
- scheduled entries on their scheduled date; and
- scheduled changes to a published entry on their scheduled date, marked Update. Once the changes go live, the entry appears only on its original publication date.
A schedule that is more than two minutes past its time is marked Overdue. This usually means the scheduled-publishing sweep is not running; see Publish or schedule changes.
The calendar leaves out drafts without a schedule, entries in Trash, and collections hidden from the sidebar. The dashboard’s Scheduled count covers every month and includes hidden collections, so it can be higher than what the calendar shows for one month.
The calendar loads at most 1,000 entries for a month, including the days from neighboring months that the grid shows. When there are more, it says on which day the loaded entries end and marks the later days as not loaded.
Restore a revision
Section titled “Restore a revision”Collections with revision support show Revisions in the settings panel. Expand it to see saved versions and the fields that changed between them. Select a revision to inspect its content, then select Restore if you want to use that version again.
Restoring creates a new revision containing the selected content. It does not erase the revisions that came before it, so you can still inspect the complete sequence afterward.
Translate an entry
Section titled “Translate an entry”When internationalization is enabled, the Translations panel shows the configured locales for the current entry.
-
Open the source entry and find Translations in the settings panel.
-
Select Translate for a locale that does not yet have an entry.
-
Edit the copied title, slug, body, and other translatable fields.
-
Select Save, then publish or schedule the translation when it is ready.
Each translation has its own slug, publishing state, schedule, and revision history. Use the locale selector on the collection page to view one language at a time.
Move content to Trash
Section titled “Move content to Trash”Open an entry’s actions or select one or more rows on the collection page, then choose Move to Trash. Trashed entries stop appearing in ordinary content queries but remain available on the collection’s Trash tab.
From Trash, select Restore to return an entry to the collection. A restored entry comes back as a draft with no schedule. Publish it to make it public.
Automate content work
Section titled “Automate content work”The REST API and EmDash CLI support the same draft and publishing workflow. Collection fields belong
inside the request’s data object. An update saves a draft revision; publishing is a separate action.
Pass the latest _rev value when updating or publishing so the server rejects a stale write instead
of replacing newer work.
Use the content lifecycle reference for state transitions, permissions, conflicts, and hooks. The REST API reference defines request and response bodies, and the CLI reference covers equivalent terminal commands.
Continue with Querying Content to render published entries in an Astro site, or Media Library to add and manage reusable files.