Laravel Published

Redirects in HydePHP

Using a HydePHP extension that generates static redirect pages from configuration without relying on server-side routing or hosting-specific features.

HydePHP is a static site generator based on Laravel, but with the ability to write in Markdown. It gives you the power and freedom to use the power of Blade or the simplicity of Markdown. That's why I switched from good old WordPress to HydePHP. Not that there's something wrong with WordPress, actually it is great for an easy to setup blog, but for my use case a static site was a better fit.

One of the trade-offs of static site generation is the lack of runtime routing logic. When URLs change, whether due to restructuring content, improving SEO, or renaming pages—you still need a clean way to handle redirects.

To address this, I built a lightweight HydePHP extension that lets you define redirects declaratively and have them compiled into static HTML redirect pages at build time.

The problem challenge

The theory

In a traditional Laravel application, redirects are trivial, you define them in routes or middleware. In a static site, however, there’s no request lifecycle. That means redirects must exist as actual files.

Real-life

In WordPress I was using the /<year>/<month>/<slug>/ url structure, while HydePHP uses /posts/{slug}. To prevent ending up with a lot of 404's, I would rather redirect the user to the new post url. While HydePHP has a lot of functionality and helpers, it didn't have one for redirects, so I decided to built my own extension for it.

The goal

The goal was simple:

  • Define redirects in configuration
  • Automatically generate redirect pages
  • Keep everything framework-native and minimal

The approach

HydePHP provides an extension system that allows you to hook into the build process. Specifically, we can inject pages into the PageCollection during discovery.

The extension I've built to support redirects, utilizes this mechanism, especially the discoverPages method:

use Hyde\Foundation\Concerns\HydeExtension;
use Hyde\Foundation\Kernel\PageCollection;
use Hyde\Pages\InMemoryPage;

class RedirectsExtension extends HydeExtension
{
    public function discoverPages(PageCollection $collection): void
    {
        foreach (config('redirects', []) as $path => $destination) {
            if (! is_string($path) || ! is_string($destination) || $path === '' || $destination === '') {
                continue;
            }

            $collection->addPage(InMemoryPage::make(
                identifier: trim($path, '/'),
                matter: ['destination' => trim($destination, '/')],
                view: 'redirect',
            ));
        }
    }
}

When benchmarking this solution against our goals, we see that it ticks all the boxes.

The actual redirect

This extension still doesn't perform the actual redirect, it just generates the necessary pages. Each generated page uses a simple Blade view that performs an instant redirect using a meta refresh.

@php
    use Hyde\Hyde;

    $resolvedDestination = Hyde::relativeLink($destination)
@endphp
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="refresh" content="0;url='{{ $resolvedDestination }}'" />
    <link rel="canonical" href="{{ $resolvedDestination }}" />
    <title>Redirecting to {{ $resolvedDestination }}</title>
</head>
<body>
Redirecting to <a href="{{ $resolvedDestination }}">{{ $resolvedDestination }}</a>.
</body>
</html>

The meta refresh ensures the client immediate redirects to the destination while the canonical link helps search engines understand the target URL.

Relative URL resolution via Hyde::relativeLink() ensures compatibility with different base paths and deployments. Make sure to only use relative URL's in the redirects.php file.

Example output

In your config/redirects.php you would define redirects like this:

return [
    '/old-page' => '/new-page',
    '/blog/legacy-post' => '/blog/updated-post',
];

When you build the site, it will generate the following files:

/old-page/index.html
/blog/legacy-post/index.html

Each file contains a redirect to the new URL.

Considerations with this approach

This is a simple but effective approach, although there are a few considerations.

SEO

The meta refresh redirects are generally respected by search engines, but they are not as decent as HTTP 301 redirects. If you can perform redirects at the server-level (i.e. with a load balancer, redirects at your registrar, etc.), you may still want to prefer that approach over this one.

Hosting

This method works across all static hosts since it relies purely on HTML—no server configuration required. So if you are using something like GitHub pages, your redirects will work.

Validation

The extension includes basic validation to skip invalid configuration entries. When multiple people are working on the static site or you are building a larger site, you may want to improve this extension with logging or stricter checks.

Benefits of this approach

This solution stays fully aligned with HydePHP’s architecture. It uses the offical extension API and keeps everything deterministic at build time.

It’s also flexible, you could extend this further to support redirect status codes, wildcard or pattern-based redirects and even redirects to external URL's.

Closing thoughts

Redirects are one of those small but critical pieces of site maintenance. With this extension, they become just another part of your configuration—version-controlled, predictable, and easy to manage.

So if you are using HydePHP for your static site and need simple redirect functionality without relying on the features of your hosting, this approach is both clean and effective.

Keep reading

Related posts