Publish in rankveo, render the blog on your own Laravel site. The best SEO, GEO and AEO content tooling, on your domain — server rendered HTML, not an embed.
composer require rankveo/laravelRANKVEO_BLOG_API_KEY=rk_...That is the whole setup. The blog is live at /blog.
| Route | |
|---|---|
/blog |
Paginated listing |
/blog/page/2 |
Real paths, not ?page= — every page is crawlable |
/blog/{slug} |
Article, with Open Graph and BlogPosting JSON-LD |
/blog/tag/{tag}, /blog/category/{category} |
Filtered listings, paginated |
/blog/rss.xml |
RSS 2.0 |
/blog/sitemap.xml |
Sitemap with image entries — Google will not index an image it has to find by crawling |
Set a secret and rankveo calls you when an article is published, edited while live, unpublished or deleted:
RANKVEO_REVALIDATE_SECRET=$(openssl rand -hex 32)POST /blog/rankveo/revalidate then clears the blog cache. Without a secret the
route is not registered at all — an unauthenticated cache-busting endpoint is a
free way to make every request hit the API.
This is where Laravel beats a static site generator: there is a real cache to invalidate, so nothing has to rebuild or redeploy.
use Rankveo\Laravel\Facades\Rankveo;
$articles = Rankveo::getArticles(page: 0, limit: 10);
$article = Rankveo::findArticle('how-to-rank-in-ai-answers');
$site = Rankveo::getSite();Responses are cached in your configured store. Rankveo::fresh() bypasses the
cache; Rankveo::flush() clears it.
php artisan vendor:publish --tag=rankveo-views # Blade into resources/views/vendor/rankveo
php artisan vendor:publish --tag=rankveo-config # config/rankveo.phpThe views are plain Blade with semantic class names — the same ones every other
rankveo starter uses. Point layout.blade.php at your own layout and the blog
sits inside your existing site chrome.
To own the routes outright, set RANKVEO_ROUTES=false and write your own using
the facade.
- The key is server-side. It is never needed in the browser, so it does not belong in any variable your front end can read.
- Body images are already in
$article->html. Looping over$article->imagesas well prints them twice — usegalleryImages()for the ones that are not. - An article from a listing has no body.
hasBody()says so; it is the usual cause of a blank article page. - The stylesheet is served, not published. Publishing assets is a step people skip, and the result is an unstyled blog with no error explaining why.
The package sends its requests through Laravel's HTTP client, so Http::fake()
works in your own tests without knowing anything about this package.
MIT.