How to create a simple sitemap for Wink

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.


More Posts

How do Enums work in PHP?

Ever been unsure about Enums or why you'd use them? In this post i'll show you real world examples and...