# Working with Content

> Create, edit, publish, schedule, and safely delete content in the EmDash admin.

Source: https://emdashcmseverything.com/official-docs/guides/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

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

1. Select **Add New** on the collection page.

2. 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.

3. Add the body and any supporting fields, such as an excerpt, featured image, byline, categories,
   or tags.

4. Select **Save**. The first save creates the entry as a draft and opens its permanent editor URL.

5. Review the draft. If the collection supports previews, select **Preview** to see the rendered
   page before publishing.

6. 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](https://emdashcmseverything.com/official-docs/guides/querying-content/#entry-identifiers)
explains both values.

## Write rich text

Portable Text fields provide a block editor for headings, paragraphs, quotations, lists, links,
images, videos, 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 and video files into the editor or paste a copied image or screenshot. Each
file uploads to the Media Library and appears between the surrounding blocks when the upload
finishes. If an upload fails, the reason appears where the file 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 a caption, 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. To caption the image, select **Add caption** and type
in the field that opens under the image, then press Enter to keep writing below it. The caption field
stays hidden while an image has no caption. 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](https://emdashcmseverything.com/official-docs/guides/media-library/#edit-an-image-used-in-content) for that distinction.

### Add a video

Type `/video`, then choose a video from the Media Library or upload one in the picker that opens.
The video block is added once you choose a video. You can also drop a video file anywhere in the
text.

The video plays in the editor as it will on your site, at the width of the text.

Hover over a video, or select it, to show **Replace video**, **Add caption**, and **Delete video** in
its corner. **Add caption** opens a caption field under the video; press Enter there to keep writing
below it. From a selected video, Tab moves to the player, where Space plays it, then to the caption
and the three buttons. Escape returns to the block.

Uploads follow the Media Library's size limit,
[`maxUploadSize`](https://emdashcmseverything.com/official-docs/reference/configuration/#maxuploadsize), which is 50 MiB unless you raise it.

### 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, `style` attributes, 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.

> **Note**
>
> In a deployed admin, previews follow the admin's security policy, which blocks scripts, styles,
> fonts and other resources from other sites, but not images or https frames. A note below the
> preview says when this happens. Your site can still load them.

### 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](#add-html-css-and-javascript).

## 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

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](https://emdashcmseverything.com/official-docs/reference/rest-api/#entry-edit-lock)
for the complete API behavior and
[Content lifecycle and bylines](https://emdashcmseverything.com/official-docs/reference/mcp-server/#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

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](https://emdashcmseverything.com/official-docs/deployment/cloudflare/#scheduled-publishing) to verify the trigger.

## 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](#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.

## Review and restore revisions

Collections with revision support show **Revisions** in the settings panel. Expand it to see the
entry's saved versions, grouped by day, with the time and the person who saved each one.
**Current version** marks the version in the editor, and **Published** marks the version visitors
see. The list shows the 20 newest versions; select **Show older versions** to see the rest.

Select a version to show it in the editor, read-only:

- Added text is highlighted and removed text is struck through, in the color of the person who
  saved the version. The dot next to their name in the list shows that color.
- The version's entry in the list describes each change, such as "Changed the title" or
  "Edited “Most teams plan posts in…”". Select a change to scroll to it.
- Turn off **Show changes** to read the version without highlights.

**Save** and **Publish** pause while a version is open, and your unsaved edits stay in the editor.
Select the **×** in the bar (**Back to editing**) or press Esc to return to them. On a
phone, choose a version in the settings panel, then use the arrows in the bar at the bottom of the
editor to step between versions.

To use a version again, select **Restore** in that bar. Restoring copies the version into a new
draft at the top of the list. Your previous draft stays in the list, and visitors keep seeing the
published version until you publish. If the entry is scheduled, the restored version goes live at the
scheduled time.

A version whose content matches an earlier one is marked "Restored from" with that version's date. A
version that matches the current one shows **Same as current version** in place of **Restore**.

## Translate an entry

When [internationalization is enabled](https://emdashcmseverything.com/official-docs/guides/internationalization/), the **Translations** panel
shows the configured locales for the current entry.

1. Open the source entry and find **Translations** in the settings panel.

2. Select **Translate** for a locale that does not yet have an entry.

3. Edit the copied title, slug, body, and other translatable fields.

4. 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

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.

> **Caution**
>
> An administrator can select **Delete Permanently** in Trash. Permanent deletion removes the entry
> and its revisions and cannot be undone. Check that the entry is no longer needed before confirming.

## 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](https://emdashcmseverything.com/official-docs/reference/content-lifecycle/) for state transitions,
permissions, conflicts, and hooks. The [REST API reference](https://emdashcmseverything.com/official-docs/reference/rest-api/) defines request and
response bodies, and the [CLI reference](https://emdashcmseverything.com/official-docs/reference/cli/#emdash-content) covers equivalent terminal
commands.

Continue with [Querying Content](https://emdashcmseverything.com/official-docs/guides/querying-content/) to render published entries in an Astro
site, or [Media Library](https://emdashcmseverything.com/official-docs/guides/media-library/) to add and manage reusable files.
