A blogging website written in Python 3.9 using the flask framework. Licensed under the MIT License. See it live at www.stefanonsoftware.com.
- Modern, fully type-hinted Python3 syntax with black, isort, and pyflakes linting.
- Web UI rendered using Jinja templates and using bootstrap4 for responsiveness.
- Backend sqlite3 database connection implemented using sqlalchemy.
- Custom Markdown rendering built on top of markdown2. Supports custom XML tags for images and colored code blocks powered by pygments.
- Simple user accounts and permissions implemented using flask-login.
- RESTful API fully defined in OpenAPI 3.0.0.
- Automatically-generated Python API client using openapi-python-client.
- API contract validation implemented using marshmallow.
- Client-side click scripts that allow for uploading, updating, and managing blog posts on the site.
- Email list integration with sendinblue using their official Python SDK.
- A simple Python GUI program for cropping images written with tkinter.
- Decent unit test coverage with pytest.
Along with this site, I'm also working on two sibling projects:
- simple-search: A simple search engine written in Python. It powers queries made via the website search bar.
- site-analytics: A simple web server that collects website traffic and makes it available for analysis.
This repository contains code and templates, but no blog articles. My long-term goal is to make it 100% configurable and extensible, so that anyone could use it to build their own blog.
example-post
: an example post including Markdown text, images, and configuration.stefan-on-software
: the website implementation. Contains the backend Flask code and the Jinja templates used to render the website.stefan-on-software-api-client
: client code for the website's API. Most code is auto-generated based onapi.yaml
. See thebin
directory for scripts to upload, update, and manage blog posts.stefan-on-software-renderer
: code for rendering article Markdown into HTML. Supports custom XML elements.tk-image-cropper
: a Python GUI program used to crop images to a specified size.api.yaml
: the website's API definition.
The website does not (yet) have a graphical interface for writing posts. Therefore, posts are created on your local computer and uploaded to the website via the scripts in stefan-on-software-api-client/bin
. Each post should have a separate directory that includes:
- The Markdown content of the post in a file called
post.md
- The post configuration/metadata (e.g. Title, Byline, Tags) in a file called
post-meta.json
See the provided example post (in the example-post
directory) for more information.
Upgrade pip (recommended) and install the required packages:
python -m pip install --upgrade pip
pip install -r requirements.txt
See the package-specific READMEs for more information.
Code should be linted using black and isort. Furthermore, before pushing, you should run pyflakes and ensure that there are no errors.
black . && isort . && pyflakes .
This project uses openapi-python-client to automatically generate a Python client library based on the website's OpenAPI definition. To generate or update the client library, install openapi-python-client in a separate virtual environment. Then, from the root directory of this project, run openapi-python-client update --path api.yaml
.