<div align="center">
<img src="logo.png" alt="Kinglet Logo" width="200" height="200">
<h1>Kinglet</h1>
<p><strong>Lightning-fast Python web framework for Cloudflare Workers</strong></p>
[](https://github.com/mitchins/Kinglet/actions/workflows/ci.yml)
[](https://sonarcloud.io/summary/new_code?id=mitchins_Kinglet)
[](https://codecov.io/github/mitchins/kinglet)
[](https://badge.fury.io/py/kinglet)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
</div>
## Quick Start
Install: `pip install kinglet` or add `dependencies = ["kinglet"]` to pyproject.toml
```python
from kinglet import Kinglet, CorsMiddleware, cache_aside_d1
app = Kinglet(root_path="/api")
# Flexible middleware (v1.4.2+)
app.add_middleware(CorsMiddleware(allow_origin="*"))
@app.post("/auth/login")
async def login(request):
data = await request.json()
return {"token": "jwt-token", "user": data["email"]}
@app.get("/api/data")
@cache_aside_d1(cache_type="api_data", ttl=1800) # D1 caching (v1.5.0+)
async def get_data(request):
return {"data": "cached_in_prod_fresh_in_dev"}
```
## Why Kinglet?
| Feature | Kinglet | FastAPI | Flask |
|---------|---------|---------|-------|
| **Bundle Size** | 272KB | 7.8MB | 1.9MB |
| **Testing** | No server needed | TestServer required | Test client required |
| **Workers Ready** | ✅ Built-in | ❌ Complex setup | ❌ Not compatible |
## Key Features
**Core:** Decorator routing, typed parameters, flexible middleware, auto error handling, serverless testing
**Cloudflare:** D1/R2/KV helpers, D1-backed caching, environment-aware policies, CDN-aware URLs
**Database:** Micro-ORM for D1 with migrations, field validation, bulk operations (v1.6.0+)
**Security:** JWT validation, TOTP/2FA, geo-restrictions, fine-grained auth decorators
**Developer:** Full type hints, debug mode, request validation, zero-dependency testing
## Examples
**Typed Parameters & Auth:**
```python
@app.get("/users/{user_id}")
async def get_user(request):
user_id = request.path_param_int("user_id") # Validates or returns 400
token = request.bearer_token() # Extract JWT
limit = request.query_int("limit", 10) # Query params with defaults
return {"user": user_id, "token": token}
```
**Flexible Middleware & Caching:**
```python
# Configure middleware with parameters
cors = CorsMiddleware(allow_origin="*", allow_methods="GET,POST")
app.add_middleware(cors)
# D1-backed caching (v1.5.0+) - faster and cheaper for <1MB responses
@app.get("/api/data")
@cache_aside_d1(cache_type="api_data", ttl=1800) # D1 primary, R2 fallback
async def get_data(request):
return {"data": "expensive_query_result"}
# R2-backed caching for larger responses
@app.get("/api/large")
@cache_aside(cache_type="large_data", ttl=3600) # Environment-aware
async def get_large_data(request):
return {"data": "large_expensive_query_result"}
```
**D1 Micro-ORM (v1.6.0+):**
```python
from kinglet import Model, StringField, IntegerField
class Game(Model):
title = StringField(max_length=200)
score = IntegerField(default=0)
# Simple CRUD with field validation
game = await Game.objects.create(db, title="Pac-Man", score=100)
top_games = await Game.objects.filter(db, score__gte=90).order_by("-score").all()
```
**Security & Access Control:**
```python
@app.get("/admin/debug")
@require_dev() # 404 in production (blackhole)
@geo_restrict(allowed=["US"]) # HTTP 451 for other countries
async def debug_endpoint(request):
return {"debug": "sensitive data"}
```
**Testing (No Server):**
```python
def test_api():
client = TestClient(app)
status, headers, body = client.request("GET", "/users/123")
assert status == 200
```
## Documentation
- **[Examples](examples/)** - Quick start examples
- **[ORM Guide](docs/ORM.md)** - D1 micro-ORM with migrations (v1.6.0+)
- **[Middleware Guide](docs/MIDDLEWARE.md)** - Flexible middleware system (v1.4.2+)
- **[Caching Guide](docs/CACHING.md)** - Environment-aware caching (v1.4.3+)
- **[Security Guide](docs/SECURITY_BEST_PRACTICES.md)** - Critical security patterns
- **[TOTP/2FA Guide](docs/TOTP.md)** - Two-factor authentication
---
Built for Cloudflare Workers Python community. **[Need help?](https://github.com/mitchins/Kinglet/issues)**
Raw data
{
"_id": null,
"home_page": null,
"name": "kinglet",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "cloudflare, workers, python, routing, web, framework, asgi, lightweight",
"author": null,
"author_email": "Mitchell Currie <mitchell@mitchins.dev>",
"download_url": "https://files.pythonhosted.org/packages/5f/51/e1e840817b3f259b892dd628916a4f088ee9de5af06ba28c9212f8295d49/kinglet-1.6.1.tar.gz",
"platform": null,
"description": "<div align=\"center\">\n <img src=\"logo.png\" alt=\"Kinglet Logo\" width=\"200\" height=\"200\">\n <h1>Kinglet</h1>\n <p><strong>Lightning-fast Python web framework for Cloudflare Workers</strong></p>\n\n [](https://github.com/mitchins/Kinglet/actions/workflows/ci.yml)\n [](https://sonarcloud.io/summary/new_code?id=mitchins_Kinglet)\n [](https://codecov.io/github/mitchins/kinglet)\n [](https://badge.fury.io/py/kinglet)\n [](https://www.python.org/downloads/)\n [](https://opensource.org/licenses/MIT)\n</div>\n\n## Quick Start\n\nInstall: `pip install kinglet` or add `dependencies = [\"kinglet\"]` to pyproject.toml\n\n```python\nfrom kinglet import Kinglet, CorsMiddleware, cache_aside_d1\n\napp = Kinglet(root_path=\"/api\")\n\n# Flexible middleware (v1.4.2+)\napp.add_middleware(CorsMiddleware(allow_origin=\"*\"))\n\n@app.post(\"/auth/login\")\nasync def login(request):\n data = await request.json()\n return {\"token\": \"jwt-token\", \"user\": data[\"email\"]}\n\n@app.get(\"/api/data\")\n@cache_aside_d1(cache_type=\"api_data\", ttl=1800) # D1 caching (v1.5.0+)\nasync def get_data(request):\n return {\"data\": \"cached_in_prod_fresh_in_dev\"}\n```\n\n## Why Kinglet?\n\n| Feature | Kinglet | FastAPI | Flask |\n|---------|---------|---------|-------|\n| **Bundle Size** | 272KB | 7.8MB | 1.9MB |\n| **Testing** | No server needed | TestServer required | Test client required |\n| **Workers Ready** | \u2705 Built-in | \u274c Complex setup | \u274c Not compatible |\n\n## Key Features\n\n**Core:** Decorator routing, typed parameters, flexible middleware, auto error handling, serverless testing\n**Cloudflare:** D1/R2/KV helpers, D1-backed caching, environment-aware policies, CDN-aware URLs\n**Database:** Micro-ORM for D1 with migrations, field validation, bulk operations (v1.6.0+)\n**Security:** JWT validation, TOTP/2FA, geo-restrictions, fine-grained auth decorators\n**Developer:** Full type hints, debug mode, request validation, zero-dependency testing\n\n## Examples\n\n**Typed Parameters & Auth:**\n```python\n@app.get(\"/users/{user_id}\")\nasync def get_user(request):\n user_id = request.path_param_int(\"user_id\") # Validates or returns 400\n token = request.bearer_token() # Extract JWT\n limit = request.query_int(\"limit\", 10) # Query params with defaults\n return {\"user\": user_id, \"token\": token}\n```\n\n**Flexible Middleware & Caching:**\n```python\n# Configure middleware with parameters\ncors = CorsMiddleware(allow_origin=\"*\", allow_methods=\"GET,POST\")\napp.add_middleware(cors)\n\n# D1-backed caching (v1.5.0+) - faster and cheaper for <1MB responses\n@app.get(\"/api/data\")\n@cache_aside_d1(cache_type=\"api_data\", ttl=1800) # D1 primary, R2 fallback\nasync def get_data(request):\n return {\"data\": \"expensive_query_result\"}\n\n# R2-backed caching for larger responses\n@app.get(\"/api/large\")\n@cache_aside(cache_type=\"large_data\", ttl=3600) # Environment-aware\nasync def get_large_data(request):\n return {\"data\": \"large_expensive_query_result\"}\n```\n\n**D1 Micro-ORM (v1.6.0+):**\n```python\nfrom kinglet import Model, StringField, IntegerField\n\nclass Game(Model):\n title = StringField(max_length=200)\n score = IntegerField(default=0)\n\n# Simple CRUD with field validation\ngame = await Game.objects.create(db, title=\"Pac-Man\", score=100)\ntop_games = await Game.objects.filter(db, score__gte=90).order_by(\"-score\").all()\n```\n\n**Security & Access Control:**\n```python\n@app.get(\"/admin/debug\")\n@require_dev() # 404 in production (blackhole)\n@geo_restrict(allowed=[\"US\"]) # HTTP 451 for other countries\nasync def debug_endpoint(request):\n return {\"debug\": \"sensitive data\"}\n```\n\n**Testing (No Server):**\n```python\ndef test_api():\n client = TestClient(app)\n status, headers, body = client.request(\"GET\", \"/users/123\")\n assert status == 200\n```\n\n## Documentation\n\n- **[Examples](examples/)** - Quick start examples\n- **[ORM Guide](docs/ORM.md)** - D1 micro-ORM with migrations (v1.6.0+)\n- **[Middleware Guide](docs/MIDDLEWARE.md)** - Flexible middleware system (v1.4.2+)\n- **[Caching Guide](docs/CACHING.md)** - Environment-aware caching (v1.4.3+)\n- **[Security Guide](docs/SECURITY_BEST_PRACTICES.md)** - Critical security patterns\n- **[TOTP/2FA Guide](docs/TOTP.md)** - Two-factor authentication\n\n---\n\nBuilt for Cloudflare Workers Python community. **[Need help?](https://github.com/mitchins/Kinglet/issues)**\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A lightweight routing framework for Python Workers",
"version": "1.6.1",
"project_urls": {
"Bug Tracker": "https://github.com/mitchins/Kinglet/issues",
"Homepage": "https://github.com/mitchins/Kinglet",
"Repository": "https://github.com/mitchins/Kinglet"
},
"split_keywords": [
"cloudflare",
" workers",
" python",
" routing",
" web",
" framework",
" asgi",
" lightweight"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "45f83cd8befa7cf9c456a9f9852008cb49c62a8f6be76a0971825c1de6f658f2",
"md5": "a8cf1fcb5280fd3ac241339c69850a3a",
"sha256": "1501b5d451b5fc68c21b55d8f1d37b5ed9e4b690f6b261df7390e6532afbd60a"
},
"downloads": -1,
"filename": "kinglet-1.6.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a8cf1fcb5280fd3ac241339c69850a3a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 66154,
"upload_time": "2025-09-04T09:42:19",
"upload_time_iso_8601": "2025-09-04T09:42:19.581500Z",
"url": "https://files.pythonhosted.org/packages/45/f8/3cd8befa7cf9c456a9f9852008cb49c62a8f6be76a0971825c1de6f658f2/kinglet-1.6.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "5f51e1e840817b3f259b892dd628916a4f088ee9de5af06ba28c9212f8295d49",
"md5": "9c40bb15839f74101b4aecdd63b0e518",
"sha256": "fe98e59906bcca8a95c34a305fcb52182ad815d9fc4292dcb5af9be6db1d391e"
},
"downloads": -1,
"filename": "kinglet-1.6.1.tar.gz",
"has_sig": false,
"md5_digest": "9c40bb15839f74101b4aecdd63b0e518",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 141523,
"upload_time": "2025-09-04T09:42:21",
"upload_time_iso_8601": "2025-09-04T09:42:21.200931Z",
"url": "https://files.pythonhosted.org/packages/5f/51/e1e840817b3f259b892dd628916a4f088ee9de5af06ba28c9212f8295d49/kinglet-1.6.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-04 09:42:21",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mitchins",
"github_project": "Kinglet",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "kinglet"
}