Stream post types¶
Loveshack registers three custom post types alongside the standard WordPress
post. Together they make up the activity stream on the homepage.
| Post type | Name constant | Default archive slug | Admin label |
|---|---|---|---|
| Status update | LOVESHACK_CPT_STATUS (cp_status) |
/status/ |
Status Updates |
| Image post | LOVESHACK_CPT_IMAGE (cp_image) |
/image/ |
Image Posts |
| Video post | LOVESHACK_CPT_VIDEO (cp_video) |
/video/ |
Video Posts |
Each is public, queryable, block-editor enabled (show_in_rest), has its own
archive, and shares the category and post_tag taxonomies with regular posts —
so a tag archive lists every kind of stream item together.
All three support the same feature set:
title, editor, author, thumbnail, excerpt, comments, trackbacks,
custom-fields, sticky, page-attributes
Sticky support means any stream item can be pinned to the top of the stream, not just classic posts.
Writing in Markdown¶
The Text field on the stream editor is Markdown. The source is stored as you wrote it, so reopening a post shows your Markdown rather than generated HTML, and it is converted to HTML when the post is rendered.
| Syntax | Result |
|---|---|
**bold**, __bold__ |
bold |
*italic*, _italic_ |
italic |
~~struck~~ |
struck through |
`code` |
inline code |
```php … ``` |
fenced code block, optionally language-tagged |
# Heading … ###### Heading |
headings, one to six levels; the space after the # is required |
> quoted |
blockquote |
- item, * item, + item |
bulleted list, indent to nest |
1. item |
numbered list, indent to nest |
[label](https://example.com) |
link |
 |
image |
---, ***, ___ |
horizontal rule |
Underscores only mark emphasis at word boundaries, so snake_case_names and
2*3*4 are left alone. Bare URLs are linked automatically.
A # glued to the word after it is a hashtag, not a heading: #release tags the
post, # Release starts a section.
Markdown applies to the three stream post types, in both the Text and the Teaser Text field. Regular blog posts use the block editor and are unaffected.
What is deliberately not supported¶
This is a focused subset rather than full CommonMark. Reference-style links
([label][ref]), tables, footnotes, definition lists, and setext headings
(underlining a line with ===) are not parsed and will show as literal text.
Existing posts and raw HTML¶
HTML already in a post is passed through untouched, so posts written before Markdown was enabled render exactly as they did. You can also mix HTML into Markdown where the syntax does not reach far enough.
Rendered output always passes through wp_kses_post(), so a post can never emit
markup WordPress would not otherwise allow.
Angle brackets and user capability
Markdown source is stored verbatim for users with the unfiltered_html
capability — administrators and editors on a single site — which is the same
rule WordPress applies to post content everywhere else. For users without it,
WordPress entity-encodes stray angle brackets, so > blockquote markers and
< inside fenced code will not survive. In practice everyone who can reach
the stream editor has the capability.
Previewing¶
The editor has a Preview button below the Text field. It renders through the same code the frontend uses, so what you see is what the post will look like, and it updates as you type while it is open.
Teasers and summaries¶
Stream cards and subscriber-only teasers render the same HTML as the single post,
cut to the configured teaser length with the markup kept intact — a heading or
list looks the same in the stream as on the detail page. Only the visible text
counts towards the length, and the cut never splits a word or an element. Leave a
Teaser text length setting empty for no maximum — the full text is rendered
in the stream — or set it to 0 to hide the text on cards altogether. When a
post has a Teaser Text, that Markdown is rendered in place of the Text.
Headings inside a card are capped at the card's body text size so a # line
reads as a bold lead rather than a page title.
Anywhere a post is reduced to plain text — digest emails, generated excerpts, the
ActivityPub summary — the Markdown markers are stripped so readers never see raw
**bold**. A link reads as its label, an image as its alt text.
Enabling and disabling types¶
Each post type is registered only when its setting is enabled, so a site that never posts video can switch that type off entirely and keep the admin clean.
| Setting | Default |
|---|---|
enabled_status |
Enabled |
enabled_image |
Enabled |
enabled_video |
Enabled |
Disabling a type unregisters it. Existing content is not deleted — it becomes inaccessible on the frontend until the type is re-enabled.
Changing archive slugs¶
The archive slug for each type is configurable:
| Setting | Default slug |
|---|---|
status_slug |
status |
image_slug |
image |
video_slug |
video |
Slugs are sanitized with sanitize_title(), and an empty value falls back to the
default. Loveshack flushes the rewrite rules automatically when these settings
change, so a manual permalinks save is not needed after editing them.
Archives use with_front => false
Stream archives sit at the site root — /status/, not
/blog/status/ — regardless of the permalink structure's front base.
Permalinks and threads¶
Stream items always use a flat permalink — /image/my-post/ — regardless of
whether the item is part of a thread.
Threaded items, such as those the Twitter importer creates from a reply chain, are linked by their parent relationship but do not nest in the URL. Thread children are also excluded from the stream itself, which queries only top-level items.
Nested URLs from before 1.1.11
Until 1.1.11 these post types were hierarchical, so a threaded item's
permalink contained the slug of every ancestor:
/image/first-tweet/second-tweet/third-tweet/. Because a thread can mix post
types, most of those URLs did not resolve at all and returned a 404.
Loveshack now redirects any such URL to the flat permalink of the deepest item it can still find, so old links in feeds, sitemaps, and inbound traffic keep working.
The stream query¶
The homepage stream queries post plus every enabled custom type. In code, the
set is returned by:
lscpt_get_stream_post_types(); // array( 'post', 'cp_status', 'cp_image', 'cp_video' )
lscpt_get_enabled_post_types(); // just the enabled Loveshack types
Use these rather than hardcoding the type names — they respect the site's enabled settings.
Video posts¶
Video posts have one type-specific setting:
| Setting | Default | Effect |
|---|---|---|
video_hide_text_default |
Disabled | New video posts hide their body text in the stream by default, showing the video alone |
This is a default for new posts, not a global lock — it can be overridden per post.
Link previews¶
Loveshack renders link previews for URLs in stream items. The preview fetcher is selectable:
| Setting | Default |
|---|---|
link_preview_proxy |
jina |
Related¶
Update releases¶
When the Update API plugin is active on the same site, its published releases
appear in the stream as Release items. Each card shows the product name and
version, the Markdown teaser entered on the release in Update API, and a
download button with the package file name and size. The card links to a release
page at /release/<name-version>/ that shows the full Markdown text. When no
teaser is set, the card shows the start of the text instead. Visitors whose
subscription tier is allowed for the product, and administrators, get a direct
download; everyone else is sent to the subscription page.
When at least one live release is downloadable by the current visitor, a sticky Latest Releases item at the top of the home stream lists the newest release per product as download links with file size and release date, dated with the most recent release. Visitors without access to any product do not see it.
Release dates there are relative while they are recent — Just now, then minutes,
hours, and days for the first week — and fall back to the site's date format from
one week on.
The stream keeps earlier releases as history: publishing a new release marks the previous one as archived rather than hiding it. Turn the items off with Update releases in the stream under Loveshack → Custom Post Types.
Release items are full stream items. They show the author who published the release, next to the Release and Latest labels, and follow the All Posts header and timestamp settings in the Customizer. The release page accepts comments whenever the site's default comment status under Settings → Discussion is open, and releases take reactions according to the All Posts reactions setting.
The Update API plugin adds releases through the theme's stream post type API, which is how any plugin or child theme can add a post type to the stream, feeds, and digest emails. Since Loveshack 1.2.25 the release templates and styles ship with the plugin, and the stream checkbox for releases sits with the other plugin-added types under Loveshack → Custom Post Types.
Blog posts in the stream¶
Regular blog posts are part of the stream, feeds, and digest emails by default. The Blog Posts (post) checkbox under Loveshack → Custom Post Types takes them out of the stream without touching the posts themselves; they stay reachable at their own URLs and in the blog archives. When every checkbox is off, the stream falls back to blog posts.