A Permalink is a unique URL for a page that doesn’t change. This is useful to avoid broken links when moving pages around. I have always used the folder structure for URLs, but this started feeling restrictive after a while.

This document explains the process of introducing this concept in 🌐 My Website Generator.

Requirements

Places that will most likely require changes:

  • Generate a file for URL rewrites
  • Website startup code in main.py to make sure that the URL rewrites are applied
  • Checking for duplicate permalinks
  • get_relative_url in SourceFile (this also impacts the generated Sitemap)
  • URL rewrites in _change_markdown_link_pages_prefix in MarkdownSourceFile

get_relative_url in SourceFile

Returns the permalink if it exists, otherwise, it returns the relative URL based on the folder for backward compatibility.

Untested code:

    def get_permalink(self):
        with open(self.source_path, 'r') as f:
            input = f.read()
        
        metadata = re.match(r'---(.*?)---', input, flags=re.DOTALL | re.MULTILINE)
 
        parsed_metadata = yaml.safe_load(metadata)
        return parsed_metadata['permalink']

Website startup code

An example of what this would look like in server.js:

var permalinks = [
  {
    old: '/test',
    new: '/topics/programming/'
  }
]
permalinks.forEach((element) => {
  app.get(element.old, (req, res, next) => {
    req.url = element.new
    next()
  })
})

Generate a file for URL rewrites

This will be very similar to the current structure of migrated-urls.yaml.

A folder structure makes it very easy to avoid duplicates because it’s not possible to store two files with the same path and filename. With permalinks, additional validation is required to prevent duplicates.