Writing and Scheduling Posts
A post is written once and sent to one or more channels.
What a post holds
Section titled “What a post holds”| Field | Notes |
|---|---|
| Text | Required. Up to 63,206 characters stored; each network has its own, lower limit. |
| Link URL | Optional. Must be an absolute https:// URL with a host, up to 2,048 characters (link.https_required). |
| Link title | Optional, up to 200 characters. Required for LinkedIn when there is a link. |
| Link description | Optional, up to 500 characters. |
| Link image | Optional. The card’s image, read from the page (an absolute https:// URL). Sent with the card where the network shows one. |
| Image | Optional. An item from the Umbraco Media library (media.unknown if the key isn’t a media item), with its framing: a focal point and each network’s own crop. Required for Instagram. |
| Image alt text | Optional, up to 1,000 characters. Describes the image for screen readers. |
| Channels | At least one (channel.none). Each can have its own text. |
Text and links are sent exactly as written. Text that looks like an Automate binding (${ … }) is sent as plain text, never evaluated.
Links and link cards
Section titled “Links and link cards”You don’t fill in a link separately: the first link in the text is the post’s link. Change it to a different link and the card starts again, with no title or description.
When a chosen network shows link cards, the composer reads the card from the page the link points to: its title, description and image. Open Graph tags come first (og:title, og:description, og:image), then Twitter’s, then the page’s own <title> and description; an image is kept only as an absolute https URL. It fills only what you haven’t written, and Edit changes the title and description. How each network shows the link is in Network limits:
- LinkedIn and Facebook show the card the post sends.
- Bluesky shows the card the post sends, with the page’s image.
- Mastodon and X read the page themselves and build their own card.
- Instagram doesn’t get the link.
A post shows its image or its link card, not both: choosing an image replaces the card on every network.
To read cards from somewhere else, replace ILinkPreviewService (see Replacing services).
Images
Section titled “Images”Add an image opens the Media library. Once it is chosen:
- Alt text describes it for screen readers. It is sent to every network that takes it (see Network limits).
- Click the image to open Umbraco’s crop editor. Set the focal point, the part of the image that matters, and adjust any network’s crop. There is one crop per chosen network, in the shape that network is sent:
| Network | Sent as |
|---|---|
| X, Bluesky, Mastodon | 1200 × 675 |
| 1200 × 627 | |
| 1200 × 630 | |
| 1080 × 1350, always as a JPEG |
A network with its own crop gets that crop. The others are cut to their shape around the focal point (the centre without one). The previews show each network’s cut, made by the site’s image processor, exactly as it will be sent. Files the image processor can’t handle, such as SVG, are sent as they are.
Per-channel text
Section titled “Per-channel text”Any channel can have its own text instead of the post’s main text, for example a shorter version for X. A channel without its own text uses the main text. Each channel’s text is checked against its own network’s limit.
The link, image and alt text belong to the whole post. How each network uses them is in Network limits.
When it goes out
Section titled “When it goes out”| Choice | What happens | Permission |
|---|---|---|
| Draft | Saved, not scheduled. It doesn’t go out until it is scheduled. | Write |
| Add to queue | Takes the next free slot in the posting schedule. Refused with schedule.no_free_slot if there is none in the next 28 days. |
Write + Schedule |
| Specific time | Goes out at that time (UTC). A time in the past is refused (schedule.past). |
Write + Schedule |
| Publish now | Saved as due now: it goes out at the next check (every 30 seconds by default). | Write + Schedule |
In the composer these are Umbraco workspace actions in the footer bar: Save draft; Add to queue, with Schedule for a time… and Publish now in its menu; or Schedule, keeping the post’s time, when it has one. Someone without Schedule gets Save draft only.
A post only goes out where publishing is switched on. Elsewhere it waits.
Checks before saving
Section titled “Checks before saving”In the composer, a post without text, or a Specific time without a time, is marked on the field the way Umbraco marks any required field, and nothing is sent.
When a post is saved, Social checks it against every channel it goes to and refuses it, with every problem it found, if:
- the text is empty, or a field is too long;
- the link isn’t an absolute https URL;
- a channel’s text is over its network’s limit (
text.too_long:<network>); - a network’s rules aren’t met (
image.required:instagram,link.title_required:linkedin,link.image_conflict:linkedin); - a channel is unknown, removed, or paused by the free edition’s allowance (
channel.unknown,channel.paused).
You can run the same checks without saving to show live counts while writing: IPostService.CheckAsync, or POST …/posts/check in the management API. It returns each channel’s count, its limit and its errors. Every code is listed in Error codes.
Editing a post
Section titled “Editing a post”A post can be edited at any time, with these rules:
- While it is being sent (any channel is Publishing), it can’t be edited or deleted (
post.in_flight). Try again in a moment. - While any channel’s outcome is Unknown, it can’t be edited (
post.outcome_unknown). Resolve that channel first: check the account, then retry it or mark it as published. This stops an edit from sending a post a second time. - Channels where it is already published keep the text they went out with, whatever you change. They aren’t sent again.
- Channels where it failed are sent again at the new time, as a new attempt.
- You can add channels to a post, or remove channels where it hasn’t been published.
- On the free edition, a post sealed by the history window can’t be edited (
post.sealed).
Deleting a post
Section titled “Deleting a post”Delete a saved post from the composer’s footer bar (Delete, then confirm). Deleting a post removes it from Social. It doesn’t remove anything from the networks: delete a live post on the network itself.
A post can’t be deleted while it is being sent (post.in_flight).