Download the PHP package justinholtweb/craft-live without Composer
On this page you can find all versions of the php package justinholtweb/craft-live. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download justinholtweb/craft-live
More information about justinholtweb/craft-live
Files in justinholtweb/craft-live
Package craft-live
Short Description Live blogging for Craft — publish updates in a keystroke, and put them on the site without touching the page cache.
License proprietary
Informations about the package craft-live
Live
Live blogging for Craft CMS 5. An editor types a sentence, presses ⌘↵, and it is on the site — without saving the parent entry, without breaking the page cache, and without a PHP process per reader.
That is a working live blog: server-rendered on first paint, updating itself afterwards.
What makes it fast
A live blog is a strange kind of content. It is written forty times an hour by someone watching something happen, and read by everyone at once. Most implementations treat each update as a content save on the parent entry, which means the entry's whole save pipeline — revisions, drafts, search index, cache invalidation — runs every time somebody types “corner”.
Live doesn't do that.
| An update is its own element | One lightweight save. No revisions, no provisional drafts, no search indexing, and the parent entry is never touched. |
| Order comes from a sequence, not a clock | Each update gets a per-post number allocated under a row lock, so two editors publishing in the same millisecond get 412 and 413 — and a reader that has seen 412 can ask for “everything after 412” with no clock skew in the conversation. |
| Delivery is static files | Each publish writes an immutable JSON file for the update and rewrites one ~180-byte head.json. Readers poll head; nginx or your CDN serves it without waking Craft. |
| The page cache is never invalidated | The HTML page can be cached for a day. Updates arrive over the top of it. That is the point. |
| Updates arrive pre-rendered | The JSON carries HTML rendered by your own Twig partial at publish time, so an appended update is byte-identical to a server-rendered one. There is no second implementation of the card in JavaScript. |
Requirements
Craft CMS 5.3+, PHP 8.2+.
Installation
Setting up
- Add a Live field to any entry type. That entry can now be live-blogged; the field's input is the composer.
- Add update types under Live → Update Types. One (“Update”) is created on install. Give each its own field layout — a Goal that asks for a scorer, a Photo that asks for an image.
- Render the feed in your template:
To take over the markup, copy live/_update.twig and live/_feed.twig into your own templates
directory. Craft looks there first, so a file you provide wins and the rest keep working.
Writing
The composer is a plain textarea and a row of buttons, one per update type. Markdown, then ⌘↵.
- Publishing never saves the entry, so two journalists on one match cannot overwrite each other.
- An update that fails to send is kept in a local queue and retried — a dropout in a press box costs you nothing.
- Editing an update leaves it where it is in the feed and bumps its revision, so readers holding the old copy quietly get the new one.
- There is a full-screen composer at Live → Posts for when the entry edit screen is in the way.
Twig
craft.live covers the same ground without a field handle: craft.live.feed(entry),
craft.live.updates({ type: 'goal', limit: 10 }), craft.live.posts('live'), craft.live.seq(entry).
Because feed.seq changes on every publish, it is a safe cache key:
Editions
| Lite | Pro | |
|---|---|---|
| Composer, update types, Twig, static snapshots, polling | ● | ● |
| Pinning, key moments, states | ● | ● |
| Other editors' presence and soft locks | ● | |
| Scheduled and embargoed updates | ● | |
| Server-sent events | ● | |
| CDN purging (Cloudflare, Fastly, webhook) | ● | |
| GraphQL | ● |
GraphQL (Pro)
A headless front end polls liveFeed — one indexed row — and fetches updates only when the sequence
moves. Same shape as the JavaScript client, same reasoning.
Then, when seq has moved:
liveUpdate, liveUpdateCount and the field itself are there too:
Ask for html and you get the update rendered through the site's own Twig partial — useful when the
front end wants the same markup the server would have produced. It costs a render per update, so it
is only ever produced when asked for.
Each update type is its own schema component (liveupdatetypes.<uid>:read), so a token can be given
the match commentary without being given the newsroom's internal feed. A type outside the schema
isn't merely filtered out of results — its GraphQL type doesn't exist for that token at all.
Testing
A PHP unit suite (no Craft, no database) and a JavaScript suite that runs against the shipped asset
files. See tests/README.md, which also lists the checks that need a real Craft install.
Console commands
A note on server-sent events
SSE is supported, and it is off by default. Every connected reader holds a PHP process open for as
long as they are connected, so on FPM your ceiling is pm.max_children — and you find out where that
ceiling is at exactly the moment a live blog goes well. Polling static JSON has no such ceiling. Turn
SSE on for an internal dashboard, not for a cup final.
Licence
Proprietary. See LICENSE.md.
All versions of craft-live with dependencies
ext-json Version *
craftcms/cms Version ^5.3.0
ezyang/htmlpurifier Version ^4.17