volfpeter/holm/holm-web

Claude Code and agent skill by volfpeter/holm

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when working on web apps built with holm, or to answer questions about holm. Covers file-system routing, layouts, pages, actions, page metadata, form handling, error handling, partial HTML and HTMX considerations.

Install

npx vskill@latest install volfpeter/holm/holm-web

SKILL.md

Building holm web applications

Architecture summary

  • FastAPI: underlying web framework; all holm pages, layouts, actions, and metadata are FastAPI dependencies (so they can all be async)
  • htmy: async, pure-Python HTML component engine; JSX-like syntax with html.div(...), full typing, async support, and context (no prop drilling)
  • FastHX (fasthx.htmy.HTMY): the rendering layer; htmy.page() renders HTML for all requests; htmy.hx() renders HTML only for HTMX requests, otherwise keeps FastAPI route behavior
  • holm: file-system based routing (similar to Next.js), automatic layout composition, page metadata, actions, and submit handlers
  • Optional Jinja2 layout/template support via layout.jinja and holm.JinjaTemplate — see references/jinja.md

Application initialization

python
from holm import App
app = App()

Call holm.App() directly within a module in the root application package

Optional:

  • pass a pre-configured FastAPI app
  • pass a custom fasthx.htmy.HTMY renderer

File-system based routing

FilePurposeHTTP method
page.pyPage callableGET /
page.py + handle_submitSubmit handlerPOST /
layout.pyLayout callable, wraps pages/layouts in subpackages—
layout.jinjaJinja2-based layout (alternative to layout.py)—
actions.pyAction functions decorated with @action.*custom paths/methods
api.pyAPIRouter (JSON or rendering APIs)custom paths/methods
error.py / errors.pyError handlers (root only)—

Dynamic routes: _id_ or {id} package names become path parameters (/user/{id})

Private packages: prefix with underscore (_components) — ignored entirely

The default path for actions is the decorated function's name, underscores replaced with hyphens

Apply REST principles whenever possible

URL construction

python
from fastapi import Request
def some_page(request: Request) -> ComponentType:
url = request.url_for("my_app.users.page")
return html.a("Users", href=str(url))
  • Pages and submit handlers: "my_app.page", "my_app.users.page" (path is the same, method is different)
  • Actions: "my_app.users.actions.enable_user"

Pages vs Actions

  • Pages (page.py) return full HTML (wrapped in layouts); they handle regular browser navigation requests
  • Actions (@action.*) return HTML fragments without layouts by default; ideal for HTML/HTMX partials

Reference files

FileLoad when…
references/layouts.mdCreating or modifying layouts
references/jinja.mdUsing Jinja2 templates/layouts (layout.jinja, JinjaTemplate)
references/pages.mdCreating or modifying pages or page metadata
references/actions.mdCreating actions or HTMX partials
references/forms.mdCreating submit handlers or form submissions
references/apis.mdCreating custom api.py routers with JSON or mixed rendering
references/htmx-integration.mdAdding HTMX interactivity, partial rendering, or boosted navigation
references/htmy-context.mdWorking with the htmy rendering context or request processors
references/htmy.mdCreating or modifying htmy components
references/error-handling.mdSetting up custom error handlers

Gotchas

  1. Forms without method="POST" submit as GET and hit page(), not handle_submit()
  2. page.py and actions.py and api.py in the same package have their routes merged into a single APIRouter
  3. Returning Response objects from pages, actions, or handlers bypasses rendering
  4. holm auto-wraps page() and layout() list/tuple returns in Fragment. Do not return a list/tuple unless it is a component sequence
  5. htmy does not flatten nested component sequences: [comp1, comp2] is valid, but [[comp1, comp2]] is not. Use list unpacking or Fragment when mapping/generating components
  6. Strongly prefer ComponentType and ComponentSequence return type annotations over Component to avoid component nesting problems!
  7. holm uses htmy.page() for both pages and actions automatically. Actions always return HTML; use api.py if you need standard FastAPI behavior
  8. Path parameters from _id_ or {id} packages are available as standard FastAPI dependencies in pages, layouts, actions, metadata, and APIs

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
132
Repository forks
4
7-day trend score
24

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/volfpeter/holm/holm-web/badge)](https://verified-skill.com/skills/volfpeter/holm/holm-web)

Something wrong with this skill or its page? Tell us.