PageKit is a versatile, high-performance web server designed to serve content from various sources, making it easy to publish websites directly from git repositories or a local directory. It is built with Python and FastAPI, offering a lightweight and powerful solution for personal and organizational web hosting.
At its core, PageKit dynamically serves web content based on the incoming request. It can operate in different modes, allowing it to be a simple static site server for local development, a GitHub/Gitea Pages-like server for git repositories, or a full-fledged multi-tenant SaaS platform.
Key features include:
- Markdown-to-HTML Conversion: Automatically renders Markdown files as HTML pages.
- Jinja2 Templating: Uses the powerful Jinja2 templating engine to build dynamic and reusable layouts.
- Frontmatter Support: Extracts metadata (like
title,author,layout) from Markdown files to use within templates. - Flexible Configuration: Easily configured through environment variables.
PageKit can be run in one of three modes, configured via the APP_MODE environment variable.
This is the default and most powerful mode. It serves content directly from a git repository (like Gitea). The server interprets the request's hostname to determine which organization and repository to pull content from.
Example: A request to my-org.pages.yourdomain.com will look for a repository (e.g., pagekit) within the my-org organization on your configured git instance.
Ideal for development, testing, or simple single-site hosting. In this mode, PageKit serves files directly from a specified local directory on the filesystem. It provides the same Markdown rendering and templating capabilities as the repo mode.
This mode is designed for multi-tenant, SaaS-like deployments. It will use a database to manage different users/organizations, allowing each to have their own repository configurations and access tokens.
Note: This mode is currently under development.
PageKit is configured using an .env file in the project root.
| Variable | Description | Required For | Default Value |
|---|---|---|---|
APP_MODE |
The operating mode. Can be repo, local, or platform. |
All | "repo" |
REPO_URL |
The full URL to your git instance (e.g., https://gitea.example.com). |
repo mode |
(None) |
REPO_TOKEN |
A git API token with read-access to the repositories. | repo mode |
(None) |
DEFAULT_REPO |
The default repository name to look for within an organization if not specified as a subdomain. | repo mode |
"pagekit" |
LOCAL_CONTENT_DIR |
The absolute or relative path to the directory containing your content and templates for local serving. | local mode |
(None) |
DATABASE_URL |
The connection string for the database. | platform mode |
(None) |
DEBUG |
Set to true to enable debug logging and verbose error messages. |
All | false |
-
Set the Environment Variables: In your
.envfile, configure the following:APP_MODE="local" LOCAL_CONTENT_DIR="docs" # Or your own content directory DEBUG=true -
Create Content: Your
LOCAL_CONTENT_DIRshould contain your website's files (index.md,styles.css, etc.) and atemplatesdirectory for your Jinja2 layouts. See theexamples/docsdirectory for an example structure. -
Run the Server:
uvicorn pagekit.main:app
Visit
http://localhost:8000in your browser.
-
Set the Environment Variables: In your
.envfile, configure the following:APP_MODE="repo" REPO_URL="https://your-gitea-instance.com" REPO_TOKEN="your-secret-gitea-token" DEFAULT_REPO="my-website" DEBUG=true -
Run the Server:
uvicorn pagekit.main:app
-
Access Your Site: To access the content, you need to simulate a request with the correct hostname. You can do this by editing your local
/etc/hostsfile to point a custom domain to127.0.0.1:127.0.0.1 my-org.localhostThen, visit
http://my-org.localhost:8000in your browser. PageKit will fetch content from themy-websiterepository in themy-orgorganization on your Gitea instance.
Create content pages using Markdown. At the top of your .md file, you can include a YAML frontmatter block to define metadata.
Example: about.md
---
title: About Our Company
layout: layouts/page.html
author: John Doe
---
# Welcome to our page!
This is where you can write your content in Markdown...title: The title of the page, often used in the<title>tag or a heading.layout: Specifies which template file to use from thetemplatesdirectory. If omitted, it defaults tolayouts/page.html.- Any other variables (e.g.,
author) are passed directly to the template.
Templates are located in the templates subdirectory of your content source (LOCAL_CONTENT_DIR or the git repo). You can use the full power of Jinja2 to create reusable layouts.
Example: templates/layouts/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<header>
<h1>{{ title }}</h1>
</header>
<main>
{{ content | safe }}
</main>
</body>
</html>{{ title }}: Renders thetitlefrom the frontmatter.{{ content }}: This is where the rendered HTML from your Markdown file will be injected. Use the| safefilter to ensure HTML is not escaped.
For production, it is recommended to run PageKit as a Docker container, ideally within a Kubernetes cluster. The project includes a Dockerfile and sample Kubernetes manifests in the /k8s directory to get you started. Please refer to the README.md for more detailed deployment instructions.