cjm-fasthtml-app-core

Core utilities and reusable patterns for FastHTML applications including page layouts, HTMX request handling, alerts, and navbar components.

Install

pip install cjm_fasthtml_app_core

Project Structure

nbs/
├── components/ (4)
│   ├── confirm_modal.ipynb     # Generic destructive-confirm modal — Cancel-on-left, Confirm-on-right, with backdrop click-to-dismiss and defensive form-submission guards. Codifies **Convention V12 (Destructive-confirm composition)** as running code.
│   ├── empty_state.ipynb       # Generic empty-state component — a centered icon-above-title-above-detail composition optionally including a call-to-action, composing V8 anatomy slots into a single rendering helper. Codifies **Convention V8 (Empty-state anatomy)** as running code per the V12 convention/implementation split: V8 anatomy stays design-system-owned (`cjm-fasthtml-design-system/nbs/empty_states.ipynb`); the rendering helper that composes those slots into FT lives here.
│   ├── navbar.ipynb            # Responsive navigation bar components with mobile support
│   └── step_header_band.ipynb  # Step-level header band rendering helper — the title + optional subtitle on the left, optional trailing slot on the right composition that introduces each workflow step inside StepFlow's per-step render. Composes V2 anatomy slots into a single FT-returning helper. Codifies **Convention V2 (Step header band anatomy)** as running code per the V12 convention/implementation split: V2 anatomy stays design-system-owned (`cjm-fasthtml-design-system/nbs/step_chrome.ipynb`); the rendering helper that composes those slots into FT lives here.
└── core/ (4)
    ├── html_ids.ipynb  # Base HTML ID constants for FastHTML applications
    ├── htmx.ipynb      # Utilities for handling HTMX requests and responses
    ├── layout.ipynb    # Page layout utilities for wrapping content with common page structure
    └── routing.ipynb   # Routing utilities for FastHTML applications

Total: 8 notebooks across 2 directories

Module Dependencies

graph LR
    components_confirm_modal[components.confirm_modal<br/>Confirm Modal]
    components_empty_state[components.empty_state<br/>Empty State]
    components_navbar[components.navbar<br/>Navbar]
    components_step_header_band[components.step_header_band<br/>Step Header Band]
    core_html_ids[core.html_ids<br/>HTML IDs]
    core_htmx[core.htmx<br/>HTMX Utilities]
    core_layout[core.layout<br/>Layout]
    core_routing[core.routing<br/>routing]

    components_navbar --> core_html_ids
    core_layout --> core_html_ids

2 cross-module dependencies detected

CLI Reference

No CLI commands found in this project.

Module Overview

Detailed documentation for each module in the project:

Confirm Modal (confirm_modal.ipynb)

Generic destructive-confirm modal — Cancel-on-left, Confirm-on-right, with backdrop click-to-dismiss and defensive form-submission guards. Codifies Convention V12 (Destructive-confirm composition) as running code.

Import

from cjm_fasthtml_app_core.components.confirm_modal import (
    render_confirm_modal
)

Functions

def render_confirm_modal(
    modal_id:str, # HTML id for the <dialog> element
    body_id:str, # HTML id for the inner Div HTMX targets for message text
    title:str="Confirm Action?", # Modal title (rendered in <h3>)
    confirm_label:str="Confirm", # Right-button label
    confirm_icon:Optional[str]=None, # Optional Lucide icon name (e.g. "trash-2") prefixed to the confirm label
    cancel_label:str="Cancel", # Left-button label
    confirm_attrs:Optional[Dict[str, Any]]=None, # Caller-supplied attrs for the confirm button (hx_post / hx_vals / hx_swap / etc.)
) -> FT: # Dialog element implementing V12
    "Render a destructive-confirm modal (V12). Cancel-LEFT, Confirm-RIGHT, backdrop click-to-dismiss, defensive type=button. Body populated via HTMX swap into body_id."

Empty State (empty_state.ipynb)

Generic empty-state component — a centered icon-above-title-above-detail composition optionally including a call-to-action, composing V8 anatomy slots into a single rendering helper. Codifies Convention V8 (Empty-state anatomy) as running code per the V12 convention/implementation split: V8 anatomy stays design-system-owned (cjm-fasthtml-design-system/nbs/empty_states.ipynb); the rendering helper that composes those slots into FT lives here.

Import

from cjm_fasthtml_app_core.components.empty_state import (
    render_empty_state
)

Functions

def render_empty_state(
    message:str, # Primary empty-state message (single sentence in the title slot)
    detail:Optional[str]=None, # Optional supporting line rendered below the title in the detail slot
    icon_name:Optional[str]=None, # Optional Lucide icon name; rendered at V11 icons.empty_state size with V8 icon opacity
    cta:Optional[FT]=None, # Optional call-to-action element appended as the last wrapper child (typically Button with V1 buttons.primary_action)
    id:Optional[str]=None, # Optional outer Div id (for HTMX targeting or consumer ID-schema integration)
) -> FT: # Div implementing V8 empty-state anatomy
    "Render a canonical empty-state component per V8 anatomy (icon &rarr; title &rarr; detail &rarr; CTA child ordering, all slots optional except message)."

HTML IDs (html_ids.ipynb)

Base HTML ID constants for FastHTML applications

Import

from cjm_fasthtml_app_core.core.html_ids import (
    AppHtmlIds
)

Classes

class AppHtmlIds:
    "Base HTML ID constants for FastHTML applications."
    
    def as_selector(
            id_str:str # The HTML ID to convert
        ) -> str: # CSS selector with # prefix
        "Convert an ID to a CSS selector format."

HTMX Utilities (htmx.ipynb)

Utilities for handling HTMX requests and responses

Import

from cjm_fasthtml_app_core.core.htmx import (
    is_htmx_request,
    handle_htmx_request
)

Functions

def is_htmx_request(
    request # FastHTML request object
) -> bool: # True if request is from HTMX
    "Check if a request is an HTMX request."
def handle_htmx_request(
    request, # FastHTML request object
    content_fn:Callable, # Function to generate content
    *args, # Positional arguments for content_fn
    wrap_fn:Optional[Callable]=None, # Optional wrapper function for full page requests
    **kwargs # Keyword arguments for content_fn
): # Content or wrapped content based on request type
    "Handle HTMX vs full page response pattern."

Layout (layout.ipynb)

Page layout utilities for wrapping content with common page structure

Import

from cjm_fasthtml_app_core.core.layout import (
    wrap_with_layout
)

Functions

def wrap_with_layout(
    content:FT, # The main content to display
    navbar:Optional[FT]=None, # Optional navbar component
    footer:Optional[FT]=None, # Optional footer component
    container_id:str=AppHtmlIds.MAIN_CONTENT, # ID for the main content container
    container_tag:str="div" # HTML tag for the container
) -> FT: # Main element with navbar and content
    "Wrap content with the full page layout including optional navbar and footer."

routing (routing.ipynb)

Routing utilities for FastHTML applications

Import

from cjm_fasthtml_app_core.core.routing import (
    register_routes,
    APIRouter
)

Functions

def register_routes(
    app,  # FastHTML app instance
    *routers  # One or more APIRouter instances to register
) -> None:  # No return value
    "Register multiple APIRouter instances to a FastHTML app at once."

Classes

class APIRouter(APIRouter):
    """
    APIRouter override that derives route URLs and rt_funcs names from
    `func.__name__` rather than FastHTML 0.14's `nested_name()` (which
    prepends the containing function's name to routes defined inside
    factory functions).
    
    Restores pre-0.14 flat URL behavior for the `init_*_router(prefix)`
    factory pattern used across the cjm-* ecosystem.
    
    Also overrides `__getattr__` to raise a clean `AttributeError` when an
    attribute lookup falls through. FastHTML 0.14's base implementation
    calls `super().__getattr__(self, name)`, but `object` has no
    `__getattr__`, so that path produces a confusing
    `'super' object has no attribute '__getattr__'` error instead of the
    expected `AttributeError` for any non-route attribute access.
    """
    

Step Header Band (step_header_band.ipynb)

Step-level header band rendering helper — the title + optional subtitle on the left, optional trailing slot on the right composition that introduces each workflow step inside StepFlow’s per-step render. Composes V2 anatomy slots into a single FT-returning helper. Codifies Convention V2 (Step header band anatomy) as running code per the V12 convention/implementation split: V2 anatomy stays design-system-owned (cjm-fasthtml-design-system/nbs/step_chrome.ipynb); the rendering helper that composes those slots into FT lives here.

Import

from cjm_fasthtml_app_core.components.step_header_band import (
    render_step_header_band
)

Functions

def render_step_header_band(
    "Render a canonical step-level header band per V2 anatomy (title block on the left, optional trailing on the right). Responsive compression at the M2/M3 boundary is encoded in the V2 slot class strings; no per-call knobs needed."