Published

All published posts

2717 posts latest post 2026-11-11
Publishing rhythm
Oct 2026 | 30 posts
If you’re into interesting projects, don’t miss out on knossos, created by modrinth. [Archived] Former repo of the Modrinth frontend
Just starred markata-todoui by WaylonWalker. It’s an exciting project with a lot to offer. A todo plugin for markata. It is a tui (text user interface) that runs in the terminal using textual. It gives me a trello-board feel from the terminal. I can create, update, delete, move, and fully manage my todo items from the terminal with it.
Check out giscus and their project giscus. A comment system powered by GitHub Discussions.:octocat: 💬 💎

Astronauts stunting some stylish color explosion

A long needed feature of markata has been the ability to really configure out templates with configuration rather. It’s been long that you needed that if you really want to change the style, meta tags, or anything in the head you needed to write a plugin or eject out of the template and use your own.

Adding some Head #

Now you can add some extra style to your site with the existing built-in template.

[[markata.head]]
text = """
<style>
img {
  width: 100%;
  height: auto;
}
ul {
  display: flex;
  flex-wrap: wrap;
}
</style>
"""

You can have more than one Head #

Each text entry in markata.head just gets appended raw into the head.

[[markata.head]]
text = """
<style>
img {
  width: 100%;
  height: auto;
}
ul {
  display: flex;
  flex-wrap: wrap;
}
</style>
"""

[[markata.head]]
text = """
<script>
console.log('hey there')
</script
"""

Still need more? #

If this does not take you far enough yet, you can still eject out and use your own template pretty easy. If you are going for a full custom site it’s likely that this will be the workflow for awhile. Markata should only get better and make this required less often as it matures.

[markata]
post_template = "pages/templates/post_template.html"

Once you have this in your markata.toml you can put whatever you want in your own template.

“An astronaut working in a lab, colorful explosion, powder, particles, smoke, 35mm, bokeh, fog, f1.2, shallow depth of field, experiments running, beakers, test tubes, cyberpunk, octane render, trending on artstation, neon lighting, volumetric lighting, pink lighting” -s50 -W800 -H450 -C7.5 -Ak_lms -S2678273305
I recently discovered stable-diffusion-videos by nateraw, and it’s truly impressive. Create 🔥 videos with Stable Diffusion by exploring the latent space and morphing between text prompts
Looking for inspiration? markata-slides by WaylonWalker. A slides plugin for markata that allows you to create presentations in markdown from the comfort of your favorite editor. Each new h2 tag (## in markdown) becomes a new slide. This plugin leverages the built-in feeds plugin for navigation, and adds in some hotkeys (j/k) to go the the previous and next slides.
I’m really excited about small-group-notes, an amazing project by pypeaday. It’s worth exploring! Landing zone for small group notes - plan is to make this a nicer website for all things small group related
I’m really excited about meetgor.com, an amazing project by Mr-Destructive. It’s worth exploring! My Personal Blog and Portfolio made with Markata SSG and Python

I’m really getting into using hatch as my go to build system, and I am really liking it so far. I am slowly finding new things that just work really well. hatch new is one of those things that I didn’t realize I needed until I had it.

Hatch new cover image

creating new versions created by myself with stable diffusion

hatch-new-cli.webp
❯ pipx run hatch new --help
Usage: hatch new [OPTIONS] [NAME] [LOCATION]

  Create or initialize a project.

Options:
  -i, --interactive  Interactively choose details about the project
  --cli              Give the project a command line interface
  --init             Initialize an existing project
  -h, --help         Show this message and exit.

Note! I am running all of these commands with pipx. I like to use pipx for all of my system level cli applications. To emphasis this point in the article I am going to use pipx run hatch, but you can pipx install hatch then just run hatch from there.

Interacively create a new project #

Running hatch new -i will ask let you interactivly choose details about the project, such as the project’s name.

pipx run hatch new -i

After running and naming the project Hatch New we end up with the following filetree.

❯ tree .
.
├── hatch_new
│   ├── __about__.py
│   └── __init__.py
├── LICENSE.txt
├── pyproject.toml
├── README.md
└── tests
    └── __init__.py

Non-Interative #

You can also fill in the project name ahead of time, and it will run without any questions.

hatch-new-another-project.webp
❯ pipx run hatch new "Another Project"
another-project
├── another_project
│   ├── __about__.py
│   └── __init__.py
├── tests
│   └── __init__.py
├── LICENSE.txt
├── README.md
└── pyproject.toml

Note! all of these examples will create a project directory within your current working directory.

“An astronaut working in a lab, there is a series of eggs ready to hatch baby snakes on the table, experiments running, beakers, test tubes, cyberpunk, octane render, trending on artstation, neon lighting, volumetric lighting, pink lighting” -s50 -W800 -H450 -C10.0 -Ak_lms -S324995023

–init #

existing project

hatch new has an --init flag in order to initialize a new hatch pyproject.toml in an existing project. This feels like it would be useful if you are converting a project to hatch, or if like me you sometimes start making something before you realize it’s something that you want to package. Honestly this doesn’t happen too much anymore I package most things, and I hope hatch new completely breaks this habbit of mine.

Let’s say I have the following existing project.

❯ tree
.
└── hatch_init
    └── __init__.py

1 directory, 1 file

I can setup packaging with hatch by running.

pipx run hatch new --init
hatch-init-existing.webp

The pyproject.toml that comes out is pretty similar to the one that comes out of the normal hatch new, but without any other files.

Note that you will need to setup a __about__.py yourself for the dynamic versioning that it has setup for you.

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "hatch-init"
description = 'initialize an existing project using hatch'
readme = "README.md"
requires-python = ">=3.7"
license = "MIT"
keywords = []
authors = [
  { name = "Waylon S. Walker", email = "[email protected]" },
]
classifiers = [
  "Development Status :: 4 - Beta",
  "Programming Language :: Python",
  "Programming Language :: Python :: 3.7",
  "Programming Language :: Python :: 3.8",
  "Programming Language :: Python :: 3.9",
  "Programming Language :: Python :: 3.10",
  "Programming Language :: Python :: 3.11",
  "Programming Language :: Python :: Implementation :: CPython",
  "Programming Language :: Python :: Implementation :: PyPy",
]
dependencies = []
dynamic = ["version"]

[project.urls]
Documentation = "https://github.com/unknown/hatch-init#readme"
Issues = "https://github.com/unknown/hatch-init/issues"
Source = "https://github.com/unknown/hatch-init"

[tool.hatch.version]
path = "hatch_init/__about__.py"

[tool.hatch.envs.default]
dependencies = [
  "pytest",
  "pytest-cov",
]
[tool.hatch.envs.default.scripts]
cov = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=hatch_init --cov=tests"
no-cov = "cov --no-cov"

[[tool.hatch.envs.test.matrix]]
python = ["37", "38", "39", "310", "311"]

[tool.coverage.run]
branch = true
parallel = true
omit = [
  "hatch_init/__about__.py",
]

[tool.coverage.report]
exclude_lines = [
  "no cov",
  "if __name__ == .__main__.:",
  "if TYPE_CHECKING:",
]

cli #

hatch new does not stop there, it also has a --cli flag to give you a cli out of the box as well.

❯ pipx run hatch new "new cli" --cli
new-cli
├── new_cli
│   ├── cli
│   │   └── __init__.py
│   ├── __about__.py
│   ├── __init__.py
│   └── __main__.py
├── tests
│   └── __init__.py
├── LICENSE.txt
├── README.md
└── pyproject.toml

When you use the --cli flag you also get click as a dependency and project.scripts setup automatically.

[project]
name = "new-cli"

# ...

dependencies = [
  "click",
]

# ...

[project.scripts]
new-cli = "new_cli.cli:new_cli"

“An astronaut working in a lab, there is a series of eggs ready to hatch baby snakes on the table, experiments running, beakers, test tubes, cyberpunk trending on artstation” -s50 -W800 -H450 -C7.5 -Ak_lms -S98801549

what’s in the cli #

It’s a hello-world click application.

# SPDX-FileCopyrightText: 2022-present Waylon S. Walker <[email protected]>
#
# SPDX-License-Identifier: MIT
import click

from ..__about__ import __version__


@click.group(context_settings={'help_option_names': ['-h', '--help']}, invoke_without_command=True)
@click.version_option(version=__version__, prog_name='new cli')
@click.pass_context
def new_cli(ctx: click.Context):
    click.echo('Hello world!')

sneak peek #

I’ll dive more into environments and the run command later, but we can run the cli pretty damn quick with two commands. In under 5s I was able to run this cli that it created. This is a pretty incredible startup time.

pipx-run-hatch-hello-world.webp
“An astronaut working in a lab, there is a series of eggs ready to hatch baby snakes on the table, experiments running, beakers, test tubes, cyberpunk trending on artstation, neon lighting, volumetric lighting, pink lighting” -s50 -W800 -H450 -C7.5 -Ak_lms -S2274808816

Hatch has an amazing versioning cli for python packages that just works. It takes very little config to get going and you can start bumping versions without worry.

Hatch version cover image

creating new versions created by myself with stable diffusion

project layout #

For trying out the hatch version cli let’s make a simple project with the terrible name pkg.

❯ tree .
.
├── pkg
│   ├── __about__.py
│   └── __init__.py
├── pyproject.toml
└── README.md

1 directory, 4 files

pyproject.toml #

The main hero of this post is the pyproject.toml. This is what defines all of our PEP 517 style project setup.

[project]
name = "pkg"
description = "Show how to version packages with hatch"
readme = "README.md"
dynamic = [
 "version",
]

[build-system]
requires = [
 "hatchling>=1.4.1",
]
build-backend = "hatchling.build"

[tool.hatch.version]
path = "pkg/__about__.py"

statically versioning #

project.version

It is possible to set the version number inside the pyproject.toml statically. This is fine if you just want to version your package manually, and not through the hatch cli.

[project]
name = "pkg"
version = "0.0.0"
# ...

Statically versioning in pyproject.toml will not work with hatch version

hatch-static-version-error.webp
Cannot set version when it is statically defined by the `project.version` field

dynamically Versioning #

project.dynamic

Setting the project verion dynamically can be done by changing up the following to your pyproject.toml. Hatch only accepts a path to store your version. If you need to reference it elsewhere in your project you can grab it from the package metadata for that file. I would not put anything else that could possibly clash with the version, as you might accidently change both things.

If you really need to set it in more places use a package like bump2version.

[project]
name = "pkg"
dynamic = [
  "version"
]
# ...
[tool.hatch.version]
path = "pkg/__about__.py"

Note: you can configure hatch to use a different pattern https://hatch.pypa.io/1.2/version/#configuration, but I have not found it to be something that I need.

about.py #

The hatch project itself uses a about.py to store it’s version. It’s sole content is a single __version__ variable. I don’t have any personal issues with this so I am going to be following this in my projects that use hatch.

__version__ = "0.0.0"

versioning #

hatch version docs

Hatch has a pretty intuitive versioning api. hatch version gives you the version. If you pass in a version like hatch version "0.0.1" it will set it to that version as long as it is in the future, otherwise it will error.

# print the current version
hatch version

# set the version to 0.0.1
hatch version "0.0.1"

bumping #

You can bump parts of the semver version.

# minor bump
hatch version minor

# beta pre-release bump
# If published to pypi this can be installed with the --pre flag to pip
hatch version b

# bump minor and beta
hatch version minor,b

# release all of the --pre-release flags such as alpha beta rc
hatch release

Example #

Here is a screenshot of bumping a projet along.

hatch-version-cli.webp

GitOps #

In my github actions flow I will be utilizing this to automate my versions. In my side projects I use the develop branch to release –pre releases. I have all of my own dependent projets running on these –pre releases, this allows me to cut myself in my own projects before anyone else. Then on main I automatically release this beta version.

GitHub Actions #

Here is what the ci/cd for markata looks like. There might be a better workflow strategy, but I use a single github actions workflow and cut branches to release –pre releases and full release. These steps will bump, tag, commit, and deploy for me.

      - name: automatically pre-release develop branch
        if: github.ref == 'refs/heads/develop'
        run: |
          git config --global user.name 'autobump'
          git config --global user.email '[email protected]'
          VERSION=`hatch version`
          # if current version is not already beta then bump minor and beta
          [ -z "${b##*`hatch version`*}" ] && hatch version b || hatch version minor,b
          NEW_VERSION=`hatch version`
          git add markta/__about__.py
          git commit -m "Bump version: $VERSION → $NEW_VERSION"
          git tag $VERSION
          git push
          git push --tags

      - name: automatically release main branch
        if: github.ref == 'refs/heads/main'
        run: |
          git config --global user.name 'autobump'
          git config --global user.email '[email protected]'
          VERSION=`hatch version`
          hatch version release
          NEW_VERSION=`hatch version`
          git add markta/__about__.py
          git commit -m "Bump version: $VERSION → $NEW_VERSION"
          git tag $VERSION
          git push
          git push --tags

      - name: build
        run: |
          python -m build

      - name: pypi-publish
        if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main'
        uses: pypa/[email protected]
        with:
          password: ${{ secrets.pypi_password }}

Hatch Version Action #

I am setting up a github custom action waylonwalker/hatch-version-action that will lint, test, bump, and publish for me in one step. More on that in the future.

Just starred cloak.nvim by laytan. It’s an exciting project with a lot to offer. Cloak allows you to overlay *’s over defined patterns in defined files.

Markata is a great python framework that allows you to go from markdown to a full website very quickly. You can get up and running with nothing more than Markdown. It is also built on a full plugin architecture, so if there is extra functionality that you want to add, you can create a plugin to make it behave like you want.

Full transparancy… I built markata.

The talk #

The talk is live on YouTube. Make sure you check out the other videos from the conference. There were quite a few quality talks that deserve a watch as well.

https://youtu.be/Wq9YBamSgs0

“An astronaut working in a lab, hacking on a computer terminal, htop is running, shallow depth of field beakers, test tubes, volumetric lighting, pink lighting, by victo ngai, killian eng vibrant colours, dynamic lighting, digital art” -s50 -W768 -H448 -C7.5 -Ak_lms -S3617210203

Packages I Maintain

Markata I open sourced the static site framework that I use to build my-blog among other side projects. It’s a plugins all the way down static site generator, that makes me happy to use. {% gh_repo_list_topic “waylonwalker”, “markata” %} Repos used to build this blog my-blog is built on a number of small repos. I set it up this way so that creating content is fast and easy to do. I don’t have to worry about carrying around large images with my lightweight text files just to make some posts. {% gh_repo_list_topic “waylonwalker”, “personal-website” %} Kedro I am a heavy user of the kedro framework, and a big advocate for using some sort of DAG framework for your data pipelines. kedro is built all in python which makes it easy for a python dev like me to extend, run, maintain, and deploy. {% gh_repo_list_topic “waylonwalker”, “kedro” %} Neovim Plugins I use vim for all of my text editing needs. It brings me joy to make any part of it just a bit smoother. I have written a few plugins that…