blogr.ai

Docs

Lovable

Publish articles and the inner pages from your topical map straight into your Lovable app. One prompt makes Lovable build the blog, the page routes, the SEO tags, and the endpoint blogr.ai delivers to.

How it works

Your Lovable app gets a blog section and a small receiving endpoint, both built by Lovable itself from a prompt we give you. When you click Publish on an article, blogr.ai sends it to that endpoint as a single JSON POST. Your app stores the post and serves it at /blog/{slug} with proper SEO meta tags — no plugin, no SDK, nothing from Lovable's roadmap needed.

Let Lovable build the blog

Copy this prompt into your Lovable app's chat. It creates the posts table, the blog listing and post pages with SEO meta tags and Article structured data, and the secured POST /api/articles endpoint. The full payload contract below is baked in.

I use blogr.ai to write and publish SEO articles for my website. Give this app a complete blog section that blogr.ai publishes into automatically, plus a way to receive the site pages blogr.ai designs (pricing, comparisons, services, locations) outside the blog. Use this app's existing backend (Lovable Cloud or Supabase), design system, and conventions.

1. Blog storage
- Create a blog_posts table (or reuse one if this app already has it) with columns for: blogr_id (number, unique), type ("post" or "page"), title, slug (unique), path (nullable, the site path of a page such as "/pricing/" or "/compare/acme-alternatives/"), content_html, content_markdown, meta_title, meta_description, cover_image_url, cover_image_alt, categories, tags, published_at.
- Posts and pages are managed only through the endpoint below — no admin UI needed.

2. Public blog pages
- A blog index at /blog listing posts (type "post") newest first, showing each post's cover image, title, and meta description.
- A post page at /blog/{slug} that renders content_html as-is (it is already sanitized). Set the page title from meta_title (fall back to title), the description meta tag from meta_description, the cover image as the og:image, and add Article JSON-LD structured data. These SEO tags must be present in the served HTML.
- Link the blog index from the site's navigation or footer.

3. Site pages
- A row with type "page" is a site page, not a blog post. Serve it at its "path" exactly, outside /blog — for example "/pricing/" at /pricing and "/compare/acme-alternatives/" at /compare/acme-alternatives — rendering content_html with the same SEO tags as a post but WebPage JSON-LD instead of Article. Never list pages on the blog index.
- If a hand-built route already exists at a page's path, keep the hand-built route and skip rendering the page there.

4. The receiving endpoint
- A backend endpoint at POST /api/articles that blogr.ai calls with a JSON body.
- Every request carries my access token in an "Authorization: Bearer" header. Store the expected token as a backend secret named BLOGR_ACCESS_TOKEN — ask me for the value, I will copy it from the Lovable card in blogr.ai. Respond 401 when the header is missing or wrong. Never hardcode the token.
- Test deliveries carry "test": true with a sample article. Real deliveries carry "test": false.

The JSON body:

{
  "event": "article.published (a blog post) or page.published (a site page)",
  "test": false,
  "article": {
    "id": 123,
    "type": "post or page",
    "title": "Article title",
    "slug": "article-title",
    "path": "null for a post; the site path for a page, e.g. /compare/acme-alternatives/",
    "content_markdown": "# Markdown body...",
    "content_html": "<h1>HTML body...</h1>",
    "seo": {
      "title": "SEO title, or null",
      "meta_description": "Meta description, or null"
    },
    "og_image_url": "https://... cover image, or null",
    "og_image_alt": "Image alt text, or null",
    "target_keyword": "keyword, or null",
    "categories": ["Category"],
    "tags": ["tag"],
    "published_at": "2026-01-01T00:00:00+00:00"
  },
  "website": {
    "domain": "example.com"
  }
}

What the endpoint must do:
1. Check the bearer token and respond 401 on a mismatch.
2. Respond 200 to test deliveries ("test": true) without saving anything.
3. For real deliveries, upsert the row: match on "article.id" (stored as blogr_id) or "article.slug" so a repeat delivery updates the existing row instead of duplicating it. Store "article.type" and "article.path".
4. Respond 200 with a JSON body of {"url": "..."} — blogr.ai saves it as the live URL. For a post that is https://<this app's public domain>/blog/<slug>; for a page it is https://<this app's public domain><path>.
5. Respond fast — blogr.ai times out after 15 seconds — and only respond non-2xx when something really failed.

When you are done, tell me the full public URL of the POST /api/articles endpoint, so I can paste it into the Lovable card in blogr.ai.

Connect your Lovable app

  1. In your dashboard, open Setup → Publishing and choose Lovable. We generate your access token there.
  2. Copy the prompt above into Lovable. When Lovable asks for the BLOGR_ACCESS_TOKEN secret, paste the access token from the Lovable card.
  3. Lovable tells you the endpoint URL when it's done — something like https://your-app.lovable.app/api/articles. Paste it into the endpoint field. Your app must be published, since blogr.ai can only deliver to public https URLs.
  4. Click Send test to deliver a sample article, then Save.

A website publishes to one destination: connecting Lovable replaces any other integration on that website.

The delivery request

Every delivery — test or real — is an HTTP POST with these headers:

POST /api/articles HTTP/1.1
Host: your-app.lovable.app
Authorization: Bearer <your access token>
Content-Type: application/json
Accept: application/json
  • Redirects are not followed — the endpoint URL must respond directly.
  • Deliveries time out after 15 seconds. The endpoint should store the post and respond right away.
  • Any 2xx response counts as delivered. Anything else — or no response — marks the article as failed to publish.

The payload

The request body is one JSON object — the same contract as our Webhooks integration:

{
  "event": "article.published",
  "test": false,
  "article": {
    "id": 812,
    "type": "post",
    "title": "How to Choose a Laravel Hosting Provider",
    "slug": "how-to-choose-a-laravel-hosting-provider",
    "path": null,
    "content_markdown": "# How to Choose a Laravel Hosting Provider\n\nPicking a host…",
    "content_html": "<h1>How to Choose a Laravel Hosting Provider</h1>\n<p>Picking a host…</p>",
    "seo": {
      "title": "How to Choose a Laravel Hosting Provider (2026 Guide)",
      "meta_description": "Compare Laravel hosting providers on speed, pricing, and deploys."
    },
    "og_image_url": "https://blogr.ai/storage/articles/laravel-hosting-9f2c41ab.png",
    "og_image_alt": "How to Choose a Laravel Hosting Provider (2026 Guide) — laravel hosting",
    "target_keyword": "laravel hosting",
    "categories": ["Hosting", "Laravel"],
    "tags": ["laravel hosting"],
    "published_at": "2026-07-08T09:30:00+00:00"
  },
  "website": {
    "domain": "example.com"
  }
}

content_html is sanitized and ready to render as-is. article.id is stable across retries — the endpoint Lovable builds upserts on it, so a repeat delivery updates the post instead of duplicating it. The field-by-field reference on the Webhooks page applies to Lovable deliveries unchanged.

Inner pages from your topical map (pricing, comparisons, services, locations) arrive the same way with event page.published, type "page", and path set to where the page belongs on your site, such as /compare/acme-alternatives/. The prompt above tells Lovable to serve those rows at their path, outside /blog. If you built your app with an earlier version of the prompt, paste the current prompt into Lovable again before publishing pages, or they would be stored as blog posts.

Test deliveries

The Send test button on the setup screen delivers a fake article with the exact shape shown above, flagged with "test": true. The endpoint Lovable builds responds 200 to test deliveries without saving anything, so nothing test-shaped ever shows up on your blog.

Responding to a delivery

Respond with any 2xx status code to confirm the delivery. When the JSON response includes a url, blogr.ai records it as the article's published URL and links to it from your workspace:

{
  "url": "https://your-app.lovable.app/blog/how-to-choose-a-laravel-hosting-provider"
}

Failed deliveries and retries

If your app is unreachable or responds with a non-2xx status, the article is marked "Failed to publish" in your workspace with the reason on the article row — for example "Your Lovable app responded 500". Nothing is lost: paste the error into Lovable's chat to fix the endpoint, then click Retry publish to deliver the article again.

Securing the endpoint

  • The endpoint verifies the Authorization header on every request against the BLOGR_ACCESS_TOKEN secret and rejects anything else with a 401.
  • The token is generated for you and stored encrypted — treat it like a password. Rotate it anytime by entering a new value in Setup → Publishing and updating the secret in Lovable.
  • Keep the token in Lovable's secrets manager, never in the app's frontend code — frontend code is visible to every visitor.