一键导入
pages
Publish dynamic web pages for dashboards, trackers, or any data viewable in a browser. Server-side Python runs on every request.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Publish dynamic web pages for dashboards, trackers, or any data viewable in a browser. Server-side Python runs on every request.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Extract and summarise content from URLs, YouTube videos, podcasts, and files. Use when the user shares a link, asks "what's this about", "summarise this", wants a transcript, or references web/video/podcast content.
Fetch X/Twitter timeline and bookmarks. Use when the user asks about their Twitter feed, "what's on my timeline", "my bookmarks", "what have I bookmarked", or wants raw tweet data.
General-purpose lists — shopping, questions for appointments, packing lists, etc. Use when the user wants to create a list, add items, "shopping list", "questions for appointments", "what's on my list", or manages grouped items around a theme or event.
Manage reminders — one-off and recurring. Use when the user says "remind me", "set a reminder", "what reminders do I have", "cancel that reminder", or needs time-based nudges. Wraps the cron system with history and categories.
Personal knowledge base using the Zettelkasten method. Use when the user wants to save a note, look up knowledge, connect ideas, "what do I know about X", "save this", "note this down", or asks about their notes/knowledge base.
Query Garmin Connect health and fitness data including activities, sleep, heart rate, HRV, stress, and body battery. Use when the user asks about their Garmin data, "how did I sleep", "resting heart rate", "HRV", "stress levels", "body battery", "training status", "Garmin activities", or wants to analyze health metrics from Garmin Connect.
| name | pages |
| description | Publish dynamic web pages for dashboards, trackers, or any data viewable in a browser. Server-side Python runs on every request. |
Drop a .py file in pages/ with a render(request) function and it's live as a web page. Any Python logic — DB queries, API calls, file reads — runs server-side on every request. The server wraps your HTML in a shared dark mode layout with auto-discovered navigation.
Available at http://jeeves:8080 over Tailscale.
Create, edit, and delete .py files in workspace/skills/pages/pages/. Changes are live on next request — no publish step, no restart.
# pages/status.py
TITLE = "Status" # display name (default: slug titlecased)
ICON = "📊" # emoji for nav/home (default: 📄)
PINNED = True # show in bottom tab bar (default: False)
POSITION = 1 # tab sort order, lower = left (default: 99)
def render(request):
"""Return an HTML string. Can be sync or async."""
from datetime import datetime
now = datetime.now().strftime("%H:%M")
return f'<h1 class="text-2xl font-bold">Status</h1><p>Last checked: {now}</p>'
render(request) is required — receives a FastAPI Request, returns HTMLPath(__file__) gives the module's location for relative DB/file paths_ are skipped (use for shared helpers)request.query_params for URL parameters (e.g. ?date=2026-01-01)Use a directory with __init__.py for nested pages:
pages/
├── status.py # /status
└── items/ # /items, /items/new, /items/42
├── __init__.py # /items (index) + fallback for /items/{id}
└── new.py # /items/new (exact match)
The __init__.py handles the index and any unmatched sub-paths via request.path_params.get("subpath", "").
Page changes are live immediately. Only restart if server.py itself changes:
# Start
nohup uv run workspace/skills/pages/scripts/server.py > /tmp/jeeves-pages.log 2>&1 &
# Restart
pkill -f 'skills/pages/scripts/server.py'; nohup uv run workspace/skills/pages/scripts/server.py > /tmp/jeeves-pages.log 2>&1 &
Tailwind CSS is available via CDN. Custom theme colours:
bg (#1a1a2e), card (#16213e), border (#2a2a4a), accent (#e94560), muted (#8a8a9a)
Use as Tailwind classes: bg-card, border-border, text-accent, text-muted, etc.