How to create a simple sitemap for Wink

Posted on: 11/09/2021. Last updated at: 14/09/2021


I recently switched over to Mohamed Said' Writing Ink, or Wink for short. It's a great feature rich tool for creating blog posts. I was previously using Voyager from TCG.

This also meant that i needed to update my sitemap to pull the posts and categories from a new Model / Database. There are quite a few ways to generate a sitemap, including the fantastic Spatie Laravel Sitemap package.

However for my blog, i know exactly what posts and categories i wanted to be indexed, so I only needed something simple to achieve this.

Step 1 - Create a Sitemap Controller

In your terminal create a new controller, you can call it whatever you want, but i've called mine SitemapController.

php artisan create:controller SitemapController

Seeing that I have more than one section that i want to index (posts and categories), I've created a sitemap index which lists out the two pages. These pages also have their own corresponding sitemaps. To create this you only need 3 methods. Here is the contents of my SitemapController:

namespace App\Http\Controllers;

use Wink\WinkPost;
use Wink\WinkTag;

class SitemapController extends Controller
{
    public function index()
    {
        $article = WinkPost::live()->orderBy('updated_at', 'desc')->first();
        return response()->view('sitemap.index', ['article' => $article])->header('Content-Type', 'text/xml');
    }

    public function articles()
    {
        $articles = WinkPost::live()->get();
        return response()->view('sitemap.posts', ['articles' => $articles])->header('Content-Type', 'text/xml');
    }

    public function categories()
    {
        $categories = WinkTag::all();
        return response()->view('sitemap.categories', ['categories' => $categories])->header('Content-Type', 'text/xml');
    }
}

As you can see, All we need to do is fetch all the posts and categories (Referred to as Tags in Wink) and return the data to blade views with a additional header of text/xml.

This will output the content type as XML which is what search engines need to read and parse your sitemaps. Next we'll create 3 new views in the resources/views/sitemap directory and enter the following code into each of them.

Step 2 - Create the sitemap views

resources/views/sitemap/index.blade.php

<?xml version="1.0" encoding="UTF-8"?>

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <sitemap>
        <loc>https://www.danielord.co.uk/sitemap/articles</loc>
        <lastmod>{{ $article->created_at->tz('UTC')->toAtomString() }}</lastmod>
    </sitemap>
    <sitemap>
        <loc>https://www.danielord.co.uk/sitemap/categories</loc>
        <lastmod>{{ $article->created_at->tz('UTC')->toAtomString() }}</lastmod>
    </sitemap>
</sitemapindex>

resources/views/sitemap/posts.blade.php

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    @foreach ($posts as $post)
        <url>
            <loc>https://www.danielord.co.uk/{{ $post->slug }}</loc>
            <lastmod>{{ $post->created_at->tz('UTC')->toAtomString() }}</lastmod>
            <changefreq>weekly</changefreq>
            <priority>0.6</priority>
        </url>
    @endforeach
</urlset>

resources/views/sitemap/categories.blade.php

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    @foreach ($categories as $category)
        <url>
            <loc>https://www.danielord.co.uk/categories/{{ $category->slug }}</loc>
            <lastmod>{{ $category->created_at->tz('UTC')->toAtomString() }}</lastmod>
            <changefreq>weekly</changefreq>
            <priority>0.6</priority>
        </url>
    @endforeach
</urlset>

The XML is pretty standard as far as sitemaps go and we simply iterate over each article / category using a foreach loop.

Step 3 - Create the routes

The final step is to create some routes in the routes/web.php file.

Route::get('/sitemap', 'App\Http\Controllers\SitemapController@index');

Route::get('/sitemap/articles', 'App\Http\Controllers\SitemapController@posts');

Route::get('/sitemap/categories', 'App\Http\Controllers\SitemapController@categories');

Now you can setup your sitemap urls in Google Search Console or any other search engines. You can use /sitemap and /sitemap/posts and this will render the XML we created earlier.



Picture of Daniel Ord
Daniel Ord

Building things for the Web. Follow me on Twitter or checkout my GitHub.