Skip to main content

Markdown blog to beautiful static HTML — write .md, customize CSS, publish.

Project description

xuanxin

Write Markdown blogs anywhere, generate beautiful static HTML with easy style customization.

Quick start

cd ~/xuanxin
pip install -e .

# Write posts in examples/content/*.md, then build:
xuanxin build -i examples/content -o examples/dist -t "My Blog"

# Open in browser
python -m http.server 8080 --directory examples/dist
# → http://localhost:8080

Write a post

Create content/my-post.md:

---
title: "My First Post"
slug: "my-first-post"
date: "2025-06-06"
author: "You"
tags: ["blog"]
description: "A short intro shown on the index page."
theme: "default"          # optional: default | dark | minimal
featured_image_url: "https://example.com/cover.jpg"
---

# Hello World

Your **markdown** content here.

Inline math: $E = mc^2$

https://youtu.be/VIDEO_ID   ← auto-embeds YouTube

Build commands

# Basic build
xuanxin build -i content/ -o dist/

# Dark theme
xuanxin build -i content/ -o dist/ --theme dark

# Custom CSS (overrides variables & adds rules)
xuanxin build -i content/ -o dist/ --css my-style.css

# Preview HTML body for one file
xuanxin preview content/my-post.md

# List built-in themes
xuanxin themes

Customize styles (3 ways)

1. Built-in themes

default, dark, minimal — pass --theme dark or set theme: dark in frontmatter.

2. CSS variables (copy a theme file)

Each theme is just a :root { ... } block. Copy xuanxin/static/themes/default.css and change colors:

:root {
  --color-primary: #059669;
  --color-bg: #fafafa;
  --font-serif: "Georgia", serif;
  --max-width: 800px;
}

Use with --css my-theme.css.

3. Full custom CSS

Pass any CSS file with --css. It loads after the base theme, so you can override anything:

:root { --color-primary: hotpink; }
.prose h2 { border-bottom: 2px dashed var(--color-primary); }
.post { box-shadow: none; border: 2px solid black; }

See examples/custom.css for a gradient-title example.

Python API

from pathlib import Path
from xuanxin import BlogBuilder, MarkdownProcessor

# Full site build
BlogBuilder(
    content_dir=Path("content"),
    output_dir=Path("dist"),
    site_title="My Blog",
    theme="dark",
    custom_css=Path("custom.css"),
).build()

# Single file MD → HTML
processor = MarkdownProcessor()
result = processor.process_file("content/post.md")
print(result["content"])   # HTML body
print(result["metadata"])  # title, slug, tags, ...

MD → HTML pipeline

  1. Parse YAML frontmatter (python-frontmatter)
  2. Protect LaTeX $...$ / $$...$$ from Markdown
  3. Convert with Python-Markdown (+ code highlighting, tables, TOC, fenced code)
  4. Custom extensions: image CSS classes, YouTube/Vimeo embeds
  5. Restore LaTeX (rendered client-side via MathJax in output HTML)
  6. Wrap in Jinja2 template → static .html files

Output structure

dist/
├── index.html           # post listing
├── manifest.json        # build metadata
├── assets/
│   ├── theme.css        # merged theme + base styles
│   └── custom.css       # your overrides (if --css used)
└── posts/
    ├── my-first-post.html
    └── ...

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xuanxin-0.1.1.dev0.tar.gz (35.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

xuanxin-0.1.1.dev0-py3-none-any.whl (36.9 kB view details)

Uploaded Python 3

File details

Details for the file xuanxin-0.1.1.dev0.tar.gz.

File metadata

  • Download URL: xuanxin-0.1.1.dev0.tar.gz
  • Upload date:
  • Size: 35.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for xuanxin-0.1.1.dev0.tar.gz
Algorithm Hash digest
SHA256 5a8179fbb84448b2974127bd8efddcc9fc96fbaa91f803f3c6fd14900e6aac95
MD5 aa150e674b5745ac50e25a990e82eafb
BLAKE2b-256 6ee73cff1171734a7b059d92bf5c3a4c34bb5abd84c58f7c008fbf1be3c369a2

See more details on using hashes here.

File details

Details for the file xuanxin-0.1.1.dev0-py3-none-any.whl.

File metadata

  • Download URL: xuanxin-0.1.1.dev0-py3-none-any.whl
  • Upload date:
  • Size: 36.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for xuanxin-0.1.1.dev0-py3-none-any.whl
Algorithm Hash digest
SHA256 23295e62913d03f4abb0d177b031c19b1c6b68700133ec7e4d19fcc24b63c9b6
MD5 4e31bb9c955c807d24621bd345d95537
BLAKE2b-256 6ac182764d4d23a68733eaea39be1f257566a1949cf47e1dd999a8ca616f798a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page