- PHP 87.8%
- TypeScript 11.4%
- Shell 0.8%
|
Some checks failed
check / check (push) Failing after 4s
Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|---|---|---|
| .agents | ||
| .github/workflows | ||
| docs | ||
| packages/astro | ||
| plugin | ||
| scripts | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| CONTRIBUTING.md | ||
| GEMINI.md | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| skills-lock.json | ||
Blueline
Blueline makes WordPress a private CMS for a separately hosted frontend. WordPress is the newsroom. The frontend is the published edition. Preview is the proof. A rebuild is going to press.
This is not Faust for Astro. Faust is a Next.js + WPGraphQL + Gutenberg product with frontend WordPress cookies. Blueline is REST, a classic-editor-friendly CMS, and a fetch client. It does not add WPGraphQL, block hydration, or WordPress login for public visitors.
Start at docs/context/product.md. Module
contracts live in docs/.
Installables
| Package | Path | Role |
|---|---|---|
blueline/wordpress |
plugin/ |
WordPress Composer plugin (GPL-2.0-or-later) |
@blueline/astro |
packages/astro/ |
Typed fetch client for blueline/v1 |
Install
Installables are published on Forgejo
(rallendev/blueline). The
Composer package root is plugin/, so consumers use the package
registry rather than a VCS checkout of this monorepo.
Composer (blueline/wordpress)
{
"repositories": [
{
"type": "composer",
"url": "https://git.rallen.dev/api/packages/rallendev/composer"
}
],
"require": {
"blueline/wordpress": "^0.1"
},
"extra": {
"installer-paths": {
"web/app/mu-plugins/blueline/": ["blueline/wordpress"]
}
}
}
Then composer update blueline/wordpress. Prefer mu-plugins so the
package cannot be deactivated. Without that path, Composer installers
put the plugin in wp-content/plugins/wordpress/.
npm (@blueline/astro)
Pin the scope so peers such as astro still come from npmjs:
@blueline:registry=https://git.rallen.dev/api/packages/rallendev/npm/
pnpm add @blueline/astro
Set PUBLIC_BLUELINE_CMS_URL to the WordPress origin. See
packages/astro/README.md.
Local path (first consumer)
The first consumer can still map a path repository from
/Volumes/2TB SSD/Projects/PRSM/brand-v2/apps/cms/composer.json.
Do not edit that monorepo from this repository. Integration brief:
docs/architecture/consumers.md.
{
"repositories": [
{
"type": "path",
"url": "/Volumes/2TB SSD/Projects/rallen.dev/blueline/plugin"
}
],
"require": {
"blueline/wordpress": "*"
},
"extra": {
"installer-paths": {
"web/app/mu-plugins/blueline/": ["blueline/wordpress"]
}
}
}
Constants
Defined from env. Never stored in wp_options.
| Constant | Purpose |
|---|---|
BLUELINE_FRONTEND_URL |
Public frontend origin. Empty → fail-closed 404 on public WP requests |
BLUELINE_PERMALINK_STRUCTURE |
Optional; e.g. /blog/%postname%/ |
BLUELINE_WEBHOOK_URL |
Generic rebuild POST target |
BLUELINE_WEBHOOK_SECRET |
HMAC for X-Blueline-Signature |
BLUELINE_STATUS_URL |
Optional consumer status probe |
BLUELINE_BUILD_TOKEN |
Fail-closed GET blueline/v1/redirects |
BLUELINE_PREVIEW_SECRET |
HMAC for preview tokens |
BLUELINE_PREVIEW_MODE |
Optional token or rebuild |
BLUELINE_DROP_TABLES_ON_UNINSTALL |
If true, uninstall drops job/redirect tables |
Comment-only examples: plugin/.env.example.
Filters
| Filter | Default | Use |
|---|---|---|
blueline_login_site_link_text |
← Go to the website |
Login "go to site" label |
blueline_headless_unavailable_title |
Headless CMS |
Missing frontend wp_die title |
blueline_headless_unavailable_message |
headless-only copy | Missing frontend wp_die body |
blueline_public_post_types |
['post'] |
Types rewritten to the frontend |
blueline_rewritten_link |
rewritten URL | Last chance to adjust a public URL |
blueline_manage_sitemaps |
true |
Frontend owns sitemaps |
blueline_seo_frontend_url |
rewritten canonical | SEO seam |
blueline_rebuild_debounce_seconds |
45 |
Coalesce window |
blueline_rebuild_request |
outbound payload | Shape the webhook POST |
blueline_rebuild_status |
null |
Consumer status probe |
blueline_redirects_public |
false |
Opt in to public redirect export |
blueline_deleted_redirect_target |
null (410) |
301 deleted posts elsewhere |
blueline_content_types |
['post'] |
Types on GET blueline/v1/content |
blueline_content_taxonomies |
['category', 'post_tag'] |
Envelope taxonomy keys |
blueline_content_item |
mapped item | Extra envelope keys |
blueline_menu_locations |
['primary'] |
Menu locations |
blueline_preview_ttl |
900 |
Token lifetime |
blueline_preview_base |
/preview |
Frontend preview prefix |
blueline_preview_mode |
token |
token or SSG rebuild |
REST (blueline/v1)
Public frontends should call these routes, not wp/v2.
| Route | Purpose |
|---|---|
GET /content |
Published collection (X-Blueline-Total-Pages) |
GET /content/{slug} |
One published item |
GET /search |
Published search (q) |
GET /menus/{location} |
Nav tree |
GET /redirects |
Bakeable map (BLUELINE_BUILD_TOKEN or manage_options) |
POST /preview/verify |
{ token } → { post_id, exp } |
GET /preview/{id} |
Draft envelope; ?token= must match id |
POST /rebuilds/{id} |
Signed host callback |
GET /rebuild/status |
Latest job (manage_options) |
Features
| Slice | What you get |
|---|---|
| Headless core | Public 302 to the frontend; admin/API stay; theme lock |
| URL ownership | Permalinks and View links use the frontend origin |
| SEO | Rank Math / Yoast / core adapters; no hard require |
| Rebuilds | Debounced job table + generic webhook |
| Redirects | Slug-change export for the static host |
| Content | Stable envelope (html, path, seo, taxonomies, optional acf) |
| Menus / search | Public nav tree and published search |
| Preview | Signed token; latest revision overlay; frontend owns SSR |
@blueline/astro |
Fail-open published fetch; fail-closed preview; menus; sitemap bake |
| Operator UX | Settings, toolbar, notices, WP-CLI |
Demo WordPress (optional)
Tests do not need Docker or wp-env. composer -d plugin test stays
offline.
From plugin/:
npx @wordpress/env start
plugin/.wp-env.json boots vanilla WordPress with
this plugin and BLUELINE_FRONTEND_URL=http://localhost:4321. WordPress
core is downloaded by wp-env; it is not vendored in git.
Point the dummy frontend at a running Astro dev server:
# other terminal, any Astro app
pnpm astro dev --port 4321
Override the origin without committing secrets:
// plugin/.wp-env.override.json (gitignored)
{ "config": { "BLUELINE_FRONTEND_URL": "http://localhost:4321" } }
wp-admin: http://localhost:8888/wp-admin/ (see @wordpress/env docs for
the generated password).
Checks
pnpm check
Runs pnpm agent:check, plugin Pint + Pest, and @blueline/astro
tsc + Vitest. PHPStan/Psalm are not in the gate; see
docs/testing.md.
composer -d plugin i18n # regenerate plugin/languages/blueline.pot
License and contributing
GPL-2.0-or-later (LICENSE, plugin/LICENSE).
How to work in this repo: CONTRIBUTING.md.
How a human publishes: docs/architecture/release.md.
Changelog: CHANGELOG.md.