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.

More Posts

Custom API error messages with Laravel 5+
I've been building an API using Laravel 5.6 and one of the things which I wanted to do was to...
Perfect PageSpeed score using Bootstrap and mod_pagespeed
I've never really gave the PageSpeed score of the websites that i've built too much consideration, as long as they...
Can't write image data to path - Intervention Image
I recently came across the following error when using Intervention Image with Laravel 5.6: "Can't write image data to path...
How to set file permissions for Laravel 5 on mac OSX
Every time I do a fresh install of Laravel I always run into the same error where laravel.log couldn't be...
Upload, resize and save images using Intervention and AWS S3
Uploading images is one thing but being able to modify them is very useful, especially when it comes to resizing...

Other Categories