How I deploy my blog in 2022

edit ✏️

This is my first cfp for python web conf 2022 .

How I Continuously Deliver Content to my Blog with Markdown, GItHub, Python, and netlify

After being sick of long and broken builds from my javascript-based static site generator I decided it was time to switch to a language I was far more comfortable in. At the time I was really interested in learning how to build my own frameworks with pluggy, so a new static site generator was born.


Markata was born

The idea of markata is a plugins all the way down static site generator at the intersection of markdown and data. It comes with 6 defines lifecycle methods, 21 pre-defined plugins, a cache store built on diskcahe, and a configuration system. Creating new functionality is as easy as making as decorating lifecycle functions with a markata lifecycle method and adding it to the list of active plugins in your markata.toml.


All of the content on this site is written in markdown and always has been. Moving to the new site I chose to use pymdown-extensions so that I could potentially use some of their great existing extensions.


setting up extensions


self.markdown_extensions = [*DEFAULT_MD_EXTENSIONS, *markdown_extensions] = markdown.Markdown(extensions=self.markdown_extensions)


"""Define hook specs."""
import pluggy

HOOK_NAMESPACE = "markata"

hook_spec = pluggy.HookspecMarker(HOOK_NAMESPACE)
hook_impl = pluggy.HookimplMarker(HOOK_NAMESPACE)

from typing import TYPE_CHECKING

    from markata import Markata

class MarkataSpecs:
    Namespace that defines all specifications for Load hooks.

    glob -> load -> render -> save

    def glob(self, markata: "Markata") -> None:
        """Glob for files to load."""

    def load(self, markata: "Markata") -> None:
        """Load list of files."""

    def pre_render(self, markata: "Markata") -> None:
        """Pre render content from loaded data."""

    def render(self, markata: "Markata") -> None:
        """Render content from loaded data."""

    def post_render(self, markata: "Markata") -> None:
        """Post render content from loaded data."""

    def save(self, markata: "Markata") -> None:
        """Save content from data."""
self._pm = pluggy.PluginManager("markata")


Markata defines a diskcache cache for you.

    def cache(self):
        return FanoutCache(self.MARKATA_CACHE_DIR, statistics=True)

Markata provides a convenience function to help make your own unique cache key consistently.

def make_hash(self, *keys: str) -> str:
    str_keys = [str(key) for key in keys]
    return hashlib.md5("".join(str_keys).encode("utf-8")).hexdigest()

Plugins can access the cache, add to it, and set thier own expiration interval. Here is an example from the built in markdown rendering function.

def render(markata: "Markata") -> None:
    with markata.cache as cache:
        for article in markata.iter_articles("rendering markdown"):
            key = markata.make_hash(
                "render_markdown", "render", article["content_hash"]
            html_from_cache = cache.get(key)
            if html_from_cache is None:
                html =
                cache.add(key, html, expire=15 * 24 * 60)
                html = html_from_cache
            article.html = html
            article.article_html = html

## Configuration

everything is in toml

## GitHub Actions

Rendering the site inside of github actions with the cache is pretty
straightforward with these four steps.  Keying off of the configuration will
bust the cache every time we change the configuration.  You can hack a full
rebuild by changing anything inside of the configuration file.

``` yaml

- name: Cache 
uses: actions/cache@v2
    path: .markata.cache
    key: ${{ runner.os }}-${{ hashfiles('markata.toml') }}-markata

- name: Set up Python 3.8
uses: actions/setup-python@v1
    python-version: 3.8

- name: install markata
run: pip install git+ python-twitter background # checksumdir

- name: run markata
run: markata --no-rich


I deploy to netlify but any static site host would work.