launchmind / craft-launchmind-blog
Publish your Launchmind AI-generated SEO & GEO blog on your Craft CMS site.
Package info
github.com/Promesses-alfa/launchmind-craft
Type:craft-plugin
pkg:composer/launchmind/craft-launchmind-blog
Requires
- php: >=8.2
- craftcms/cms: ^5.0.0
Requires (Dev)
- craftcms/ecs: dev-main
- craftcms/phpstan: dev-main
README
Publish your Launchmind AI-generated SEO & GEO blog on your Craft CMS 5 site. Choose how the content lives on your site:
- Render mode (default): articles are pulled live from the Launchmind API and cached — nothing is written to your Craft database, and your content always reflects the latest from Launchmind.
- Sync mode: articles are synced into a local "Launchmind Articles" section as real Craft entries, so all content is stored in your own database and belongs to you outright. New articles and updates keep flowing in via periodic background syncs.
Requirements
- Craft CMS 5.0.0 or later
- PHP 8.2 or later
- A Launchmind account and API key
Installation
From the Plugin Store: search for Launchmind Blog and click Install.
Or with Composer:
composer require launchmind/craft-launchmind-blog php craft plugin/install launchmind-blog
Setup
- Go to Settings → Plugins → Launchmind Blog.
- Paste your API key (find it in your Launchmind dashboard under
Settings → Connectors). You can also reference an environment variable,
e.g.
$LAUNCHMIND_API_KEY. - Set the Blog path (default
blog). - Click Test connection, then Save.
Your blog is now live at /blog (list) and /blog/<slug> (articles).
Tip: use the API key
lm_test_demo1234567890to preview the plugin with sample content before connecting a real account.
Two ways to render
Bundled templates (zero config). The plugin ships starter templates and
registers the routes for you. Override them by copying any file from
vendor/launchmind/craft-launchmind-blog/src/templates/launchmind-blog/ into
templates/launchmind-blog/ in your own project.
Your own templates (full control). Pull the data wherever you like:
{% set posts = craft.launchmind.posts({ limit: 6 }) %}
{% for post in posts %}
<a href="{{ url(craft.launchmind.blogPath ~ '/' ~ post.slug) }}">
<h2>{{ post.title }}</h2>
<p>{{ post.excerpt }}</p>
</a>
{% endfor %}
{# A single article #}
{% set post = craft.launchmind.post('my-article-slug') %}
{{ post.html|raw }}
Each post exposes: id, slug, title, excerpt, html, coverImage,
tags, author, publishedAt, language, availableLanguages, wordCount,
isVoiceArticle, and seo.title / seo.description.
Sync mode: store articles in your own database
Set Storage mode to Store articles as local entries in the plugin
settings. The first sync creates a Launchmind Articles channel section
(handle launchmindArticles) with its own entry type and plain-text fields,
then upserts every article as a Craft entry keyed on its Launchmind id.
- Entry URLs use your blog path (
/blog/<slug>), rendered by the bundledentry.twigtemplate (overridable like the others). The article list at/blogreads from the local section. - Syncs run automatically on Craft's queue at the configured interval, on the
Sync now settings button, and via
php craft launchmind-blog/syncif you prefer a real cron job. - Updated articles are updated in place; articles removed from your Launchmind feed are disabled, never deleted. Uninstalling the plugin leaves the section and entries untouched — the content is yours.
- The first sync changes the project config (section + fields), so it must run
in an environment where
allowAdminChangesis enabled. After that, syncs only write entry content and run in any environment. - Images stay on Launchmind's CDN (absolute URLs in the article HTML).
Configuration file (optional)
Create config/launchmind-blog.php to manage settings in code / per environment:
<?php return [ 'apiKey' => '$LAUNCHMIND_API_KEY', 'blogPath' => 'blog', 'cacheTtl' => 600, 'enableTracking' => true, 'storageMode' => 'render', // or 'sync' for local entries 'syncInterval' => 3600, ];
Caching & reliability
Responses are cached with stale-while-revalidate: if the Launchmind API is ever
briefly unreachable, your blog keeps serving the last-known-good content for up
to 24 hours. Conditional requests (ETag / If-None-Match) keep bandwidth low.
Clear the cache any time from the settings page.
SEO
The bundled single-article template emits a canonical tag, Open Graph tags,
hreflang alternates for translated articles, and BlogPosting JSON-LD. If you
use SEOmatic, render the article inside your own layout and let SEOmatic own the
meta tags.