cjm-fasthtml-app-core
Install
pip install cjm_fasthtml_app_coreProject 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 → title → detail → 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."