A lightweight document publishing web application built with FastAPI and PostgreSQL. Create, view, and edit rich-text documents with a Telegraph-style reading experience.
- Rich-text editor — Write documents using a Quill-based editor with full formatting support
- Document publishing — Publish documents with a unique URL key, auto-generated from the title and date
- Edit ownership — Cookie-based author tokens ensure only the original author can edit a document
- Markdown support — Documents are parsed and rendered as Markdown on the reader side
- HTML sanitization — Content is sanitized with
bleachon both save and serve to prevent XSS - Configurable upload limit — Maximum request body size is set via
max_upload_mbinconfig.toml(default: 50 MB) - Colored access logs — HTTP access log with status-code color coding
- About page — Static
/about.htmlroute served from a bundled asset - OpenAPI docs — Interactive API documentation available at
/docs
| Component | Library |
|---|---|
| Web framework | FastAPI |
| ASGI server | Uvicorn |
| Database driver | asyncpg (PostgreSQL) |
| HTML sanitization | bleach |
| Data validation | Pydantic |
| Markdown parsing | markdown |
| Config parsing | tomllib (Python ≥ 3.11 stdlib) |
- Python ≥ 3.12
- PostgreSQL database
git clone https://github.com/wulan17/mayuri-graph-git.git
cd mayuri-graph-git
pip install .Copy the example config and fill in your PostgreSQL connection string:
cp example_config.toml config.toml# config.toml
[app]
host = "0.0.0.0"
port = 5555
[postgresql]
URL = "postgresql://user:password@host:port/mayurigraph"python -m mayurigraphThe server host and port are read from config.toml. With the defaults above the server starts on http://0.0.0.0:5555.
Publish a new document.
Request body:
{
"question": "Document title",
"content": "<p>HTML content from the editor</p>",
"author": "Your name"
}Response:
{
"ok": true,
"result": {
"key": "Document-title-06-08",
"title": "Document-title",
"date": 1749398400.0,
"views": 0,
"length": 42
}
}Sets an author_token cookie (1-year expiry) that authorises future edits to this document.
Update an existing document. Requires the author_token cookie to match the document owner.
Request body: same as POST /api/v1/documents
Render a document as an HTML page. If the author_token cookie matches the document, an Edit button is shown.
Home page — rich-text editor for writing a new document.
Editor page pre-filled with the existing document content. Only accessible to the document owner.
Serves static assets (CSS, JS, images).
The schema is automatically created on startup:
CREATE TABLE IF NOT EXISTS documents (
key VARCHAR PRIMARY KEY,
author TEXT NOT NULL DEFAULT 'Anonymous',
question TEXT,
content TEXT,
date FLOAT,
author_token TEXT
);MIT