A lightweight async Python CMS for crafting modern websites
Project description
Skrift
A modern Litestar-powered content management framework with multi-provider OAuth authentication, role-based access control, and WordPress-like template resolution.
Features
- Multi-Provider OAuth: Authenticate with Google, GitHub, Microsoft, Discord, Facebook, or Twitter/X
- Role-Based Access Control: Flexible permission system with Admin, Editor, Author, and Moderator roles
- Setup Wizard: Guided first-time configuration without manual file editing
- Admin Interface: Web-based management for users, pages, and site settings
- WordPress-like Templates: Hierarchical template resolution for content pages
- Dynamic Controllers: Load controllers from
app.yamlconfiguration - SQLAlchemy Integration: Async database support with SQLite/PostgreSQL
- Client-Side Sessions: Encrypted cookie sessions for horizontal scalability
Quick Start
Prerequisites
- Python 3.13+
Installation
# Install Skrift
pip install skrift
# Or install from git
pip install git+https://github.com/ZechCodes/skrift.git
Getting Started
Create a project directory and set up your environment:
mkdir mysite && cd mysite
# Create minimal environment file
echo "SECRET_KEY=$(python -c 'import secrets; print(secrets.token_urlsafe(32))')" > .env
# Start Skrift
skrift
Open http://localhost:8080 to launch the setup wizard.
Setup Wizard
The setup wizard guides you through initial configuration:
- Database Configuration: Choose SQLite (dev) or PostgreSQL (production)
- Authentication Providers: Configure OAuth credentials
- Site Settings: Set site name, tagline, and copyright info
- Admin Account: Create your first admin user via OAuth login
After completing the wizard, an app.yaml configuration file is created in your project directory.
Manual Configuration
Alternatively, create app.yaml manually:
controllers:
- skrift.controllers.auth:AuthController
- skrift.admin.controller:AdminController
- skrift.controllers.web:WebController
db:
url: sqlite+aiosqlite:///./app.db
auth:
redirect_base_url: http://localhost:8080
providers:
google:
client_id: $GOOGLE_CLIENT_ID
client_secret: $GOOGLE_CLIENT_SECRET
scopes: [openid, email, profile]
Then run migrations and start the server:
skrift-db upgrade head
skrift
Documentation
- Full Documentation: Comprehensive guide covering all features
- Deployment Guide: VPS, Docker, and Kubernetes deployment
- CSS Framework: Styling documentation
Project Structure
skrift/
├── skrift/ # Main Python package
│ ├── asgi.py # Application factory
│ ├── config.py # Settings management
│ ├── controllers/ # Route handlers
│ ├── admin/ # Admin panel
│ ├── auth/ # RBAC and guards
│ ├── db/ # Models and services
│ ├── lib/ # Template resolver
│ └── setup/ # Setup wizard
├── templates/ # Jinja2 templates
├── static/ # Static assets
├── alembic/ # Database migrations
├── docs/ # Documentation
├── app.yaml # Application config (generated)
└── main.py # Development entry point
Configuration
Environment Variables
| Variable | Required | Description |
|---|---|---|
SECRET_KEY |
Yes | Session encryption key |
DEBUG |
No | Enable debug mode (default: false) |
DATABASE_URL |
No | Database connection string |
OAUTH_REDIRECT_BASE_URL |
No | OAuth callback base URL |
OAuth credentials are configured per-provider (e.g., GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET).
app.yaml
Application configuration is stored in app.yaml (generated by setup wizard):
controllers:
- skrift.controllers.auth:AuthController
- skrift.admin.controller:AdminController
- skrift.controllers.web:WebController
db:
url: $DATABASE_URL
pool_size: 5
auth:
redirect_base_url: $OAUTH_REDIRECT_BASE_URL
providers:
google:
client_id: $GOOGLE_CLIENT_ID
client_secret: $GOOGLE_CLIENT_SECRET
Environment variables (prefixed with $) are interpolated at runtime.
Deployment
Minimal VPS Deployment
# Install Skrift
pip install skrift
# Create project directory
mkdir -p /opt/skrift && cd /opt/skrift
# Configure environment
cat > .env << EOF
SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
DATABASE_URL=sqlite+aiosqlite:///./app.db
OAUTH_REDIRECT_BASE_URL=https://yourdomain.com
EOF
# Start server (use setup wizard or create app.yaml manually)
skrift
Production with Gunicorn
pip install gunicorn
gunicorn skrift.asgi:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8080
See the Deployment Guide for detailed instructions including Docker, Docker Compose, and Kubernetes deployments.
Database Migrations
# Apply migrations
skrift-db upgrade head
# Create new migration
skrift-db revision --autogenerate -m "description"
# Rollback
skrift-db downgrade -1
Template Resolution
Templates follow WordPress-like hierarchical resolution:
| URL Path | Templates Tried |
|---|---|
/about |
page-about.html -> page.html |
/services/web |
page-services-web.html -> page-services.html -> page.html |
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file skrift-0.1.0a3.tar.gz.
File metadata
- Download URL: skrift-0.1.0a3.tar.gz
- Upload date:
- Size: 62.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1cc2a495ec674d7a3db1f0746a779205a1071f4d25e6fdddc30162550e072ea9
|
|
| MD5 |
f15444e6ce1411e079cd195f48c436f1
|
|
| BLAKE2b-256 |
28ab0ffe94b80a2c8470ea904bce1a4cbc5f022cd25186be8589ec3e30477079
|
File details
Details for the file skrift-0.1.0a3-py3-none-any.whl.
File metadata
- Download URL: skrift-0.1.0a3-py3-none-any.whl
- Upload date:
- Size: 89.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b2db9529d68feb6c623b7cdcee58c3d5a887070fd44ddef93468e417d4bd067
|
|
| MD5 |
cd820665151396270d7cc7fdbefd6ce5
|
|
| BLAKE2b-256 |
58eaacc375c504f36a46b37e3de248b78c3f6c594b246834fb753e7b393b18fe
|