Skip to content

Blog / journal

When Blog is included in your purchase, staff publish a storefront journal at /blog/ — long-form articles with their own workflow, SEO, and internal linking. This is not CMS (homepage bands and policy pages). If Blog screens aren’t in your admin, they aren’t enabled for this store — contact support to change what’s included.

Open Content → Blog (admin.your-domain.com/dashboard/blog).

Two presets sit under Users & roles:

Role For Can
Blog author Writers View, create, and edit drafts. Cannot publish.
Blog editor The desk Author permissions plus publish, archive, reusable blocks, media, and AI drafting tools.

Manage webhooks is not on the editor preset — owner/manager keep that. Server-side RBAC enforces the same gates as the menu. An author who PATCHes an article to published gets 409, not a live URL.

New article asks for a title. The editor then covers:

  1. Title and slug — changing the slug on a live article creates a redirect from the old /blog/{from} URL. Confirm that before you save.
  2. Excerpt — used on the index, RSS, and as the SEO description fallback.
  3. SEO — title, description, canonical URL, robots. JSON-LD for Article / FAQ / breadcrumb is generated for you; an override replaces the whole graph.
  4. Featured image — pick from the file manager.
  5. Body — TipTap. Headings, lists, links, images (stored as a file id), reusable blocks, and CTA embeds. Autosave keeps drafts after a short pause.
  6. History — restore an autosaved or published snapshot into the editor; publish again to make it live.

Bangla and other locales are separate article rows in the same content group — each with its own slug, status, and publish date. Create a translation from the article editor when you need another locale.

Statuses move in a fixed graph. The rail on the right only offers the next legal step for your role:

draftin_reviewapprovedpublished

Side doors: changes_requested, scheduled, archived. Publishing sets published_at. Unpublish returns the article to draft and fires an unpublished webhook if you have one.

Indented under Blog:

  • Blocks — reusable TipTap fragments you embed in an article body.
  • CTAs — heading, body, button. Optional scroll depth (25 / 50 / 75) shows that CTA as a storefront overlay at that point in the article instead of the inline stack.
  • Featured images and in-body images go through the file manager. Unsplash search is available only when UNSPLASH_ACCESS_KEY is set on the API — without it the picker returns 404, which is expected.

Content → Webhooks (permission blog.manage_webhooks). Create a URL and a secret. Events: published, unpublished, archived, updated. An empty event list means all four.

Deliveries run on Celery, not in the request. The body is JSON; the header is X-Nudova-Signature: sha256=… (HMAC of the raw body). Failed posts retry up to five times. The secret is write-only — the list never returns it.

Content → Health shows the last background scan — not a live computation on page load:

  • Orphan articles — published pieces with no inbound internal links.
  • Decaying articles — published more than 90 days ago with zero recorded views.
  • Link suggestions — another published title is mentioned in the body but not linked.

The scan runs on the hourly Celery beat task. An empty dashboard means the scan has not run yet, not that the journal is perfect.

Published articles render at https://your-domain.com/blog/{slug}. Retired slugs 301 to the live slug. The index accepts category, tag, year, and search query params.

Also generated when Blog is enabled:

  • /blog/rss.xml — RSS 2.0 of published articles.
  • /sitemap.xml — includes those article URLs.

Tenant config extra can set gtm_container_id (GTM-… only) and google_site_verification. Empty or malformed values are ignored — the storefront will not inject a guessed tag.

Article bodies opt into bionic reading (leading letters wrapped after mount) and a readable measure on paragraphs. Emotional scores in the editor (Trust / Urgency / Curiosity / Relief / Authority) are cached on the article and never block save.

Agents with a staff token and blog.use_ai call POST /api/v1/blog/mcp/. Tools: search, get, draft, suggest metadata, suggest internal links. Every call is audit-logged. Brand deny-list and required-review live on the tenant as extra.blog_guardrails:

{ "deny_list": ["banned-phrase"], "required_review": true }

required_review defaults to on. Drafts from this channel still cannot publish until a human approves them.

Related: CMS / content · Users & roles · Blog API.