Compare commits

...

5 Commits

Author SHA1 Message Date
John Lancaster 57da7e001e reformatted skill 2026-06-16 23:51:59 -05:00
John Lancaster 35a3a8dbed reformatted to be more skill-like 2026-06-16 23:46:05 -05:00
John Lancaster c8906cef7b reorg 2026-06-16 23:39:45 -05:00
John Lancaster 8ada18b7fd pruning 2026-06-16 23:11:11 -05:00
John Lancaster bbbf7e6c7d customization skill 2026-06-16 22:50:22 -05:00
11 changed files with 934 additions and 387 deletions
+111
View File
@@ -0,0 +1,111 @@
---
icon: simple/markdown
---
# Markdown in 5min
## Headers
```
# H1 Header
## H2 Header
### H3 Header
#### H4 Header
##### H5 Header
###### H6 Header
```
## Text formatting
```
**bold text**
*italic text*
***bold and italic***
~~strikethrough~~
`inline code`
```
## Links and images
```
[Link text](https://example.com)
[Link with title](https://example.com "Hover title")
![Alt text](image.jpg)
![Image with title](image.jpg "Image title")
```
## Lists
```
Unordered:
- Item 1
- Item 2
- Nested item
Ordered:
1. First item
2. Second item
3. Third item
```
## Blockquotes
```
> This is a blockquote
> Multiple lines
>> Nested quote
```
## Code blocks
````
```javascript
function hello() {
console.log("Hello, world!");
}
```
````
## Tables
```
| Header 1 | Header 2 | Header 3 |
|----------|----------|----------|
| Row 1 | Data | Data |
| Row 2 | Data | Data |
```
## Horizontal rule
```
---
or
***
or
___
```
## Task lists
```
- [x] Completed task
- [ ] Incomplete task
- [ ] Another task
```
## Escaping characters
```
Use backslash to escape: \* \_ \# \`
```
## Line breaks
```
End a line with two spaces
to create a line break.
Or use a blank line for a new paragraph.
```
-387
View File
@@ -1,387 +0,0 @@
---
name: nicegui
description: Build and scaffold production-ready NiceGUI + FastAPI app architecture.
---
# NiceGUI
Build a production-ready, multi-page NiceGUI application that follows modern FastAPI project layout and architecture practices.
## Goal
Create a clean, maintainable app structure where:
- FastAPI is the underlying ASGI app.
- NiceGUI is mounted/initialized in a way that aligns with FastAPI best practices.
- Each page is implemented as a separate module in `pages/`.
- The project is easy to test, extend, and deploy.
## Requirements
- Prefer Pydantic settings with a `.env` example.
- Consider adding structured logging configuration.
- Use a `src/`-style layout with clear package boundaries.
- Use an app factory (`create_app`) and avoid global side effects at import time.
- Register NiceGUI pages from modules in `pages/`.
- Keep UI logic in page modules and shared UI helpers/components in a separate package.
- Include at least these pages:
- Home (`/`)
- Dashboard (`/dashboard`)
- About (`/about`)
- Include a health endpoint (`/healthz`) on the FastAPI side.
- Provide minimal test examples for FastAPI routes and page registration.
- Use FastAPI lifespan for startup/shutdown resource management.
## Recommendations
- Consider a shared navigation/header component and left drawer used by all pages.
- Consider including dev tooling basics (formatting/lint/test commands).
- Prefer clear separation of concerns:
- `db/` for engine/session/base/models/repositories (if needed)
- `api/` for HTTP endpoints
- `ui/` for NiceGUI pages/components
- `services/` for business logic
- If you need database access, a solid pattern is to use FastAPI + SQLAlchemy best practices:
- Use one engine per application process (do not create per request).
- Prefer a request-scoped session dependency using `yield`.
- Keep transaction boundaries explicit (commit/rollback) in service/repository flows.
- Avoid sharing a session across concurrent tasks.
- Consider production-minded pool settings (`pool_pre_ping=True` and sensible recycle/timeout values).
- Prefer Alembic for schema migrations.
## Suggested Project Structure
Base structure (no database required):
```text
.
├─ pyproject.toml
├─ .env.example
├─ README.md
├─ src/
│ └─ app/
│ ├─ __init__.py
│ ├─ main.py
│ ├─ config.py
│ ├─ logging.py
│ ├─ api/
│ │ ├─ __init__.py
│ │ └─ health.py
│ ├─ services/
│ │ ├─ __init__.py
│ │ └─ example_service.py
│ ├─ ui/
│ │ ├─ __init__.py
│ │ ├─ components/
│ │ │ ├─ __init__.py
│ │ │ └─ nav.py
│ │ └─ pages/
│ │ ├─ __init__.py
│ │ ├─ home.py
│ │ ├─ dashboard.py
│ │ └─ about.py
│ └─ bootstrap.py
└─ tests/
├─ test_health.py
└─ test_pages_registration.py
```
### Conceptual boundaries for the base structure
- `main.py`: application entrypoint only; wires `create_app()` and process startup concerns.
- `bootstrap.py`: app composition layer; owns app factory, router registration, page registration, and lifespan wiring.
- `config.py`: configuration boundary; centralizes settings parsing and typed config objects.
- `logging.py`: observability boundary; centralizes logging format/levels/handlers so modules do not configure logging ad hoc.
- `api/`: transport boundary for HTTP endpoints; validate/shape request-response objects and delegate business work to `services/`.
- `services/`: use-case/business boundary; orchestrates domain behavior and dependencies, independent of UI rendering.
- `ui/pages/`: route-level UI boundary; one module per page, focused on layout/event handling for that page.
- `ui/components/`: reusable presentation boundary; shared UI widgets/composition utilities with no business side effects.
- `tests/`: behavior boundary; verify public behavior (health endpoint, page registration, service outcomes), not private implementation details.
### Dependency direction to keep clear
- Prefer this dependency flow:
- `main/bootstrap` -> `config/logging` + `api` + `ui/pages` + `services`
- `api` -> `services`
- `ui/pages` -> `ui/components` + `services`
- `services` -> pure helpers/clients (and later `db/` if enabled)
- Avoid reverse imports (for example, `services` importing from `ui/pages` or `api`).
- Keep page modules and API handlers as thin adapters; keep business decisions in `services/`.
## Extending This Pattern with a Database (Optional)
If database access is needed, extend with:
```text
.
├─ alembic.ini
├─ alembic/
│ ├─ env.py
│ └─ versions/
├─ src/
│ └─ app/
│ └─ db/
│ ├─ __init__.py
│ ├─ base.py
│ ├─ session.py
│ ├─ models/
│ │ ├─ __init__.py
│ │ └─ example.py
│ └─ repositories/
│ ├─ __init__.py
│ └─ example_repo.py
└─ tests/
└─ test_db_session_dependency.py
```
### Recommended database layering
- Keep `db/` focused on persistence primitives:
- `session.py`: engine + session factory + dependency helpers
- `models/`: ORM table mappings only
- `repositories/`: query/persistence operations only
- Keep transaction orchestration in `services/`, not in UI pages.
- Keep `ui/pages/` free of SQLAlchemy details; pages call services.
- Keep API handlers thin and delegate data work to services/repositories.
### Session and transaction pattern to request
- Use one engine and one sessionmaker per process, initialized at app startup.
- Use a `get_db_session()` dependency with `yield` for request-scoped sessions.
- In write flows, always use context managers for commit/rollback safety.
- In read-only flows, avoid unnecessary transactions and keep queries narrowly scoped.
- Do not share a session across concurrent tasks; open a new session per task/unit of work.
### Migration and schema workflow
- Treat Alembic migrations as the source of truth for schema evolution.
- Prefer:
- `alembic revision --autogenerate -m "..."`
- review migration script
- `alembic upgrade head`
- Avoid relying on `metadata.create_all()` for production schema management.
- Include a lightweight startup check that logs current migration state (without mutating schema).
### Configuration and runtime concerns
- Read `DATABASE_URL` from settings (`pydantic-settings`) and keep secrets out of source control.
- Configure pool options appropriate for environment (for example: `pool_pre_ping`, timeout/recycle tuning).
- Keep SQL echo/debug logging disabled in production by default.
- Consider a readiness probe (`/readyz`) that verifies DB connectivity when your deployment needs it.
### Testing guidance for DB-enabled projects
- Unit test repositories against a disposable test database.
- Integration test `get_db_session()` lifecycle and rollback behavior on failures.
- Add migration tests that validate model changes are represented in Alembic revisions.
- Add API/service tests for critical read/write paths (including uniqueness and constraint errors).
- Keep DB tests isolated and deterministic (fresh schema + transactional cleanup per test module/session).
## Extending This Pattern with LangGraph (Optional)
If your app needs multi-step AI workflows, tool-calling loops, or human-in-the-loop approvals, a clean extension is to add a dedicated LangGraph domain layer.
### Recommended architecture shape
- Keep LangGraph logic out of `ui/pages/` and out of HTTP route handlers.
- Add an `ai/` package (or similar) and keep graph definition, state schema, tools, and orchestration there.
- Call the graph from `services/` so your UI and API both use the same orchestration entry points.
- Continue using FastAPI lifespan for shared resources (models, clients, stores/checkpointers).
### Suggested project extension
```text
.
└─ src/
└─ app/
├─ ai/
│ ├─ __init__.py
│ ├─ state.py # TypedDict / Pydantic state schemas + reducers
│ ├─ nodes/
│ │ ├─ __init__.py
│ │ ├─ llm.py
│ │ ├─ tools.py
│ │ └─ review.py # optional interrupt/human-review nodes
│ ├─ graphs/
│ │ ├─ __init__.py
│ │ └─ assistant_graph.py
│ ├─ runtime.py # compile() + checkpointer/store wiring
│ └─ contracts.py # input/output DTOs between services and graph
├─ services/
│ └─ ai_service.py # invoke/stream/resume wrappers
└─ api/
└─ ai.py # optional HTTP endpoints for run/stream/resume
```
### Idiomatic LangGraph practices to request
- Define explicit graph state schema (`TypedDict` or Pydantic) and use reducers for append/merge behavior where needed.
- Compile graphs with persistence primitives appropriate to environment:
- dev/testing: in-memory checkpointer/store
- production: durable checkpointer/store
- Always pass a stable `thread_id` in `configurable` for resumable sessions and conversation continuity.
- For interactive UX, prefer event streaming APIs and project-specific streaming adapters in service code.
- Use `interrupt()` for human approvals/reviews; resume with `Command(resume=...)` using the same `thread_id`.
- Keep interrupt payloads JSON-serializable.
- Place non-idempotent side effects after interrupts (or isolate them in separate nodes), because interrupted nodes re-run from the start.
- If using tools, prefer LangGraphs `ToolNode` (or an equivalent centralized tool-execution node) for consistent execution/error handling.
- Keep graph nodes deterministic and narrow in scope (single responsibility per node).
- Add observability with LangSmith tracing for graph runs, transitions, and latency debugging.
### Integration guidance for NiceGUI + FastAPI
- UI pages should call `ai_service` methods, not graph internals.
- If the UX needs live token/progress updates, expose streaming from service -> UI in a transport-appropriate way.
- For approval workflows, surface interrupt payloads in UI, collect user response, then resume via service with `Command(resume=...)`.
- Keep graph invocation boundaries typed (request/response contracts) so changes in graph internals do not leak into page modules.
### Testing recommendations for LangGraph additions
- Unit test node functions as pure transformations where possible.
- Integration test graph routes (happy path, tool path, interrupt/resume path).
- Add tests ensuring `thread_id` reuse resumes correctly and new IDs start fresh sessions.
- Add regression tests for state-schema evolution and serialization compatibility.
## Extending This Pattern with a Static Docs Site via Zensical (Optional)
If the app should also host a static documentation site, mount the generated docs output directory under a configurable route (default: `/docs`).
### Recommended docs workflow
- Initialize docs in the project root:
- `uv run zensical new .`
- Keep source markdown in Zensical's `docs_dir` (default: `docs/`).
- Build docs as part of release or startup pipeline:
- `uv run zensical build`
- Serve the generated static output from Zensical's `site_dir` (default: `site/`).
### Config to include in app settings
- `docs_enabled: bool = true`
- `docs_mount_path: str = "/docs"`
- `docs_site_dir: str = "site"`
- Optional for local/dev convenience:
- `docs_require_build: bool = false` (if true, fail startup when `site/` is missing)
### FastAPI/NiceGUI integration pattern
- Keep docs mounting in the app composition layer (`bootstrap.py`), not in page modules.
- Use FastAPI static serving to mount the built directory (for example via `StaticFiles(..., html=True)`).
- Ensure `docs_mount_path` is normalized (leading slash, no trailing slash) and does not conflict with app/API routes.
- If docs are disabled or build artifacts are missing, log a clear warning and continue (unless `docs_require_build=true`).
### Suggested project additions
```text
.
├─ zensical.toml
├─ docs/
│ ├─ index.md
│ └─ ...
├─ site/ # generated by `uv run zensical build`
└─ src/
└─ app/
├─ config.py # docs_enabled/docs_mount_path/docs_site_dir
└─ bootstrap.py # mount static docs route
```
### Deployment notes for docs mounting
- In CI/CD, run `uv run zensical build` before packaging/deploying the app image.
- If `project.site_dir` in `zensical.toml` is changed, keep `docs_site_dir` in app settings aligned.
- If hosting behind a reverse proxy with a path prefix, verify docs links and static assets with the final external base path.
- Add a test asserting requests to `docs_mount_path` return the built index page when docs are enabled.
## Implementation Notes
- Prefer an explicit page registration function pattern, for example:
- `register_pages()` in `ui/pages/__init__.py`
- Each page module exports `register_page()`
- Keep imports one-way to avoid circular dependencies.
- Keep page modules cohesive: route declaration + page layout for that route.
- Prefer FastAPI lifespan hooks where appropriate for startup/shutdown behavior.
- Prefer type hints throughout.
### Styling architecture notes
- Prefer class-first UI composition for structure and layout using normal NiceGUI mechanics (`.classes(...)` on containers/components).
- Keep structural concerns in Python page/component modules (layout grids, spacing systems, responsive breakpoints, alignment).
- Keep cosmetic concerns in static CSS files (colors, gradients, shadows, border polish, typography fine-tuning, transitions).
- Avoid large inline `style(...)` strings except for one-off dynamic values that must be computed at runtime.
- Centralize CSS entrypoints in a small, predictable set (for example `ui/static/css/base.css`, `ui/static/css/theme.css`, `ui/static/css/components.css`).
- Include CSS once at app bootstrap/startup so pages share the same style contract; avoid per-page ad hoc includes.
- Prefer semantic class names for reusable patterns (`app-shell`, `page-section`, `card-surface`) and utility classes only for local layout tweaks.
- If using design tokens, define them as CSS custom properties in `:root` and reference them from component classes.
- Keep page modules focused on structure and behavior; reusable visual patterns should live in shared UI components plus shared CSS.
### Database-specific notes (only if your app needs a DB)
- Prefer settings via `pydantic-settings` and read `DATABASE_URL` from environment/dotenv.
- Configure the SQLAlchemy engine once at app setup level; avoid creating engine/sessionmaker in endpoint functions.
- Provide `get_db_session()` via `yield` so sessions are consistently closed.
- Prefer a repository/service boundary to keep SQL details out of page modules.
- Prefer Alembic for schema changes and include commands for `revision --autogenerate` and `upgrade head`.
- Avoid `metadata.create_all()` in production startup flow; reserve it for optional local/dev bootstrap paths.
- Consider a light DB readiness check in health reporting (or a dedicated `/readyz`) when relevant.
- Ensure logs do not leak secrets (for example, avoid unsafe SQL echo in production).
## Output Format
The goal of the output is to produce an output
Return:
- A concise, high-level architecture explanation.
- An explanation of how the different parts of the concept will fit into this structure
- What are the core services?
- What are the main ui pages?
- What are the main ui components?
- Whether a database will be involved and whether the app owns the database
- Whether any AI will be used and what the workflow looks like
- A concrete implementation plan in the form of a checklist, organized into sections by concept which should roughly mirror the structure of sub-packages.
- Key functions/classes
- Configuration/settings available
- Migration or rollout notes (if relevant)
## Guardrails
- Do not put all pages in a single file.
- Never use globals, implicit or otherwise.
- Keep code minimal but production-minded.
- Being clear and concise is a higher priority than being verbose.
- Prefer clarity and maintainability over clever abstractions.
## Source Documentation (recommended references)
- FastAPI lifespan events:
- https://fastapi.tiangolo.com/advanced/events/
- FastAPI settings and environment variables:
- https://fastapi.tiangolo.com/advanced/settings/
- FastAPI dependencies with `yield` (session lifecycle pattern):
- https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/
- FastAPI SQL databases tutorial (when using a DB):
- https://fastapi.tiangolo.com/tutorial/sql-databases/
- SQLAlchemy engine configuration and pooling (when using a DB):
- https://docs.sqlalchemy.org/en/20/core/engines.html
- SQLAlchemy session basics and lifecycle guidance (when using a DB):
- https://docs.sqlalchemy.org/en/20/orm/session_basics.html
- Alembic tutorial and migration environment (when using a DB):
- https://alembic.sqlalchemy.org/en/latest/tutorial.html
- Pydantic settings management:
- https://pydantic.dev/docs/validation/latest/concepts/pydantic_settings/
- NiceGUI pages/routing and FastAPI integration:
- https://www.nicegui.io/documentation/section_pages_routing
- NiceGUI security best practices:
- https://www.nicegui.io/documentation/section_security
- LangGraph overview:
- https://docs.langchain.com/oss/python/langgraph/overview
- LangGraph quickstart:
- https://docs.langchain.com/oss/python/langgraph/quickstart
- LangGraph workflows and agents:
- https://docs.langchain.com/oss/python/langgraph/workflows-agents
- LangGraph persistence (checkpointer vs store):
- https://docs.langchain.com/oss/python/langgraph/persistence
- LangGraph memory concepts:
- https://docs.langchain.com/oss/python/concepts/memory
- LangGraph streaming:
- https://docs.langchain.com/oss/python/langgraph/streaming
- LangGraph interrupts / human-in-the-loop:
- https://docs.langchain.com/oss/python/langgraph/interrupts
+134
View File
@@ -0,0 +1,134 @@
---
name: nicegui-ui-customization
description: 'Design and implement production NiceGUI UIs with reusable components, Tailwind-first styling, event-driven interactions, and troubleshooting for uploads, state, and static assets. Use when building or refactoring NiceGUI pages and interaction flows.'
argument-hint: 'What UI outcome should this workflow produce?'
---
# NiceGUI UI Customization Workflow
Create, style, and ship production NiceGUI UI flows with a repeatable process. The workflow keeps structure in Python, favors Tailwind and Quasar APIs for styling, and uses event-driven interaction patterns over ad-hoc polling.
## When To Use
- Building a new NiceGUI page or dashboard
- Refactoring a page into reusable components
- Adding file upload, form submission, live status, or background-job UX
- Troubleshooting race conditions, stale assets, or inconsistent state updates
## Target Outcome
Deliver a responsive, accessible UI flow that:
- keeps clear boundaries between page adapters, reusable components, and services
- uses Tailwind-first styling with minimal custom CSS
- updates UI through events and bindings
- has validation, user feedback, and failure handling
- passes a production-readiness check at the end
## Progressive Loading References
Load these references only when needed:
- Architecture and styling rules: [./references/architecture-and-styling.md](./references/architecture-and-styling.md)
- Event and state interaction patterns: [./references/interaction-patterns.md](./references/interaction-patterns.md)
- Troubleshooting and release gates: [./references/troubleshooting-and-quality-gates.md](./references/troubleshooting-and-quality-gates.md)
## Procedure
### 1. Define the UI Slice
- Capture the user-visible outcome for this task in one sentence.
- Identify route-level page modules to touch.
- Identify service operations needed by the UI.
Completion check:
- You can name the target page, component candidates, and service calls before coding.
### 2. Choose Component Extraction Strategy
Decision point:
- If a layout pattern appears in 2 or more pages, extract it to `ui/components/`.
- If a pattern is page-specific, keep it in the page module.
Completion check:
- Reused UI patterns are encapsulated as callable components.
### 3. Build Responsive Layout First
- Use Tailwind utility classes for structure and spacing.
- Use responsive breakpoints (`sm:`, `md:`, `lg:`).
- Reserve `.style()` for dynamic values that cannot be expressed with classes.
Completion check:
- Layout works at mobile and desktop widths without custom CSS overrides.
### 4. Add Reactive State And Events
- Use bindable dataclasses for local page state.
- Prefer event handlers (`on_click`, `on_upload`, etc.) over periodic polling.
- Trigger explicit refreshes with `@ui.refreshable` where needed.
Decision point by interaction type:
- File upload: validate size/type, delegate storage to a service, notify success/failure.
- Form submit: bind inputs to dataclass fields, validate in service layer, clear state on success.
- Real-time status: use SSE or WebSocket for push updates.
- Long jobs: run in background task, update status endpoint or stream.
Completion check:
- Every user action has explicit positive and negative feedback via `ui.notify()`.
### 5. Apply Styling Strategy
Preferred order:
1. Tailwind utility classes
2. Quasar props
3. Reusable styled component functions
Only if absolutely necessary:
- Load minimal custom CSS once at startup in `bootstrap.py`.
- Keep custom CSS tokenized (variables) and documented.
Completion check:
- Styling is mostly class/props-driven and not dependent on scattered ad-hoc CSS.
### 6. Harden Against Common Failures
- Prevent duplicate submissions by disabling controls during in-flight operations.
- Avoid overlapping timers for the same state target.
- Serialize dependent updates (`await` service call before mutation/render).
- Verify static mount paths and cache behavior for changed assets.
Completion check:
- Race conditions and stale asset symptoms are addressed with explicit safeguards.
### 7. Final Production Readiness Review
Pass all checks:
- Structure: pages, components, services follow one-way dependency flow.
- Responsiveness: tested at small and large viewport widths.
- Accessibility: labels, button text, and action visibility are clear.
- Reliability: validation and exception paths produce user-facing notifications.
- Maintainability: repeated UI patterns are extracted; business logic stays in services.
If any check fails, return to the relevant step and iterate.
## Completion Contract
This workflow is complete when:
- the page flow meets the target outcome
- architecture boundaries are preserved
- chosen interaction pattern is implemented with explicit success and failure feedback
- troubleshooting checks pass
- production-readiness gate passes
@@ -0,0 +1,76 @@
# Architecture and Styling Reference
## Project Boundaries
Use this dependency direction:
- pages import components and services
- components contain presentation logic only
- services contain business logic and do not import UI
- static assets are mounted and loaded once at bootstrap
Suggested module split:
```text
src/app/
ui/pages/
ui/components/
ui/static/
services/
api/
bootstrap.py
```
## Component Extraction Rules
Extract to ui/components when a pattern appears in two or more pages.
Keep in-page if the layout is specific to a single route.
```python
def card_section(title: str, content: str) -> ui.card:
with ui.card().classes("w-full max-w-md") as card:
ui.label(title).classes("text-lg font-bold")
ui.label(content).classes("text-gray-600")
return card
```
## Tailwind-First Layout Pattern
Use Tailwind utility classes for structure and spacing.
Use breakpoint classes for responsive behavior.
Use .style() only for values that must be computed dynamically.
```python
with ui.column().classes("w-full"):
with ui.row().classes("w-full gap-4 flex-wrap sm:flex-nowrap"):
ui.card().classes("flex-1 min-w-64")
ui.card().classes("flex-1 min-w-64")
```
## Styling Decision Order
1. Tailwind utility classes
2. Quasar props
3. Reusable styled component functions
4. Minimal custom CSS loaded once at bootstrap (only when needed)
```python
from fastapi.staticfiles import StaticFiles
app.mount("/static", StaticFiles(directory="src/app/static"), name="static")
ui.add_css(open("src/app/static/css/base.css").read())
```
## Static Asset Rules
- Keep custom CSS small and tokenized with variables.
- Avoid per-page CSS injection.
- Verify static mount paths and reverse proxy rewrites.
## Links
- NiceGUI elements: https://nicegui.io/documentation/element
- NiceGUI binding: https://nicegui.io/documentation/section_binding_properties
- Tailwind: https://tailwindcss.com/docs/utility-first
- Quasar components: https://quasar.dev/vue-components
@@ -0,0 +1,109 @@
# Interaction Patterns Reference
## Reactive State
Use bindable dataclasses for local page state.
```python
from dataclasses import field
from nicegui import binding, ui
@binding.bindable_dataclass
class PageState:
selected_id: int | None = None
items: list = field(default_factory=list)
state = PageState()
ui.label().bind_text_from(state, "selected_id")
```
## File Upload Pattern
- Validate extension and size before storing.
- Delegate storage to a service method.
- Notify success and failure explicitly.
```python
async def handle_upload(e: ui.events.UploadEventArguments):
try:
if e.size > 10 * 1024 * 1024:
raise ValueError("File too large")
if not e.name.endswith(".pdf"):
raise ValueError("Only PDF allowed")
await file_service.store(e.content.read(), e.name)
ui.notify(f"Uploaded: {e.name}", type="positive")
except ValueError as err:
ui.notify(str(err), type="negative")
ui.upload(on_upload=handle_upload, auto_upload=True)
```
## Form Submission Pattern
- Bind UI inputs to dataclass fields.
- Perform validation in the service layer.
- Clear form state on success.
```python
@binding.bindable_dataclass
class FormData:
name: str = ""
email: str = ""
data = FormData()
ui.input("Name").bind_value(data, "name")
ui.input("Email").bind_value(data, "email")
async def on_submit():
try:
await user_service.create_user(name=data.name, email=data.email)
ui.notify("User created", type="positive")
data.name = data.email = ""
except ValueError as err:
ui.notify(str(err), type="negative")
ui.button("Submit").on_click(on_submit)
```
## Real-Time Updates Decision
Use SSE for one-way status streaming.
Use WebSocket for bidirectional messaging.
SSE endpoint example:
```python
@app.get("/events/status")
async def status_stream():
async def gen():
while True:
yield f"data: {await get_status()}\\n\\n"
await asyncio.sleep(1)
return StreamingResponse(gen(), media_type="text/event-stream")
```
## Background Work Pattern
- Start long jobs in FastAPI background tasks.
- Expose status via endpoint or streaming channel.
- Guard buttons against duplicate submissions during in-flight tasks.
## Explicit Refresh Pattern
Use @ui.refreshable and call refresh intentionally instead of polling unrelated state.
```python
@ui.refreshable
async def item_list():
items = await service.list()
for item in items:
ui.label(item.name)
ui.button("Refresh").on_click(lambda: item_list.refresh())
```
## Links
- NiceGUI action events: https://nicegui.io/documentation/section_action_events
- FastAPI SSE: https://fastapi.tiangolo.com/advanced/server-sent-events/
- FastAPI WebSockets: https://fastapi.tiangolo.com/advanced/websockets/
@@ -0,0 +1,39 @@
# Troubleshooting and Quality Gates
## Troubleshooting
### Upload Errors
- Validate extension and size before storage.
- Catch expected exceptions and return negative notifications.
- Log unexpected exceptions with request context.
### UI Race Conditions
- Disable triggering controls during async work.
- Remove duplicate timers and listeners targeting the same state.
- Ensure service call ordering is deterministic before render updates.
### Asset Caching
- Confirm static mount and proxy rewrite correctness.
- Add cache-busting query strings for changed assets.
- Avoid per-page CSS injection.
### Navigation and State Drift
- Avoid global mutable UI state.
- Keep state request-scoped or service-managed.
- Rehydrate page data during route load.
## Production Readiness Gate
Pass all checks before shipping:
- Structure: one-way dependencies between pages, components, and services.
- Responsiveness: UI validated at both small and large viewport widths.
- Accessibility: labels and actions are clear and readable.
- Reliability: validation and exception paths surface user feedback.
- Maintainability: repeated UI patterns are extracted; business logic remains in services.
If any check fails, return to the workflow step that owns that concern.
+180
View File
@@ -0,0 +1,180 @@
---
name: nicegui
description: 'Design and scaffold a production-ready NiceGUI + FastAPI application architecture. Use for multi-page app planning, package boundaries, optional DB/LangGraph/docs integration, and implementation checklists.'
argument-hint: 'What should this app include (pages, DB, AI, docs, constraints)?'
---
# NiceGUI
Design a production-minded NiceGUI + FastAPI architecture with clear boundaries, optional extensions, and a concrete implementation checklist.
## When to Use
- You need a reusable architecture plan before implementing a NiceGUI app.
- You want FastAPI app-factory structure and lifespan wiring.
- You need optional guidance for database, LangGraph workflows, or mounted static docs.
- You want output that is concise, structured, and implementation-ready.
## Inputs to Collect
Collect these inputs up front. If not provided, make safe defaults and state assumptions.
- Product scope and primary user journeys.
- Required pages and route map.
- Whether persistent data is required.
- Whether AI orchestration (multi-step, streaming, approvals) is required.
- Whether generated docs should be mounted in-app.
- Runtime/deployment constraints (single service vs split services, environment requirements).
## Outcome
Produce:
- A concise architecture explanation.
- How core services, UI pages, and UI components fit together.
- Explicit decision on DB ownership or involvement.
- Explicit decision on AI workflow (or no AI).
- A checklist implementation plan organized by package and domain.
## Procedure
1. Frame the baseline architecture.
2. Choose optional extensions (DB, AI, docs) using decision points below.
3. Map modules, dependencies, and key boundaries.
4. Define key functions/classes and configuration surfaces.
5. Produce phased checklist with rollout or migration notes when relevant.
6. Run completion checks before returning.
### 1) Baseline architecture
Use a src-layout with FastAPI as the ASGI app and NiceGUI registered via composition.
- App factory pattern: `create_app()`.
- Lifespan for startup and shutdown resource management.
- `api/` for HTTP handlers, `services/` for business logic.
- `ui/pages/` for page modules, `ui/components/` for shared UI.
- Health endpoint on FastAPI side: `/healthz`.
Recommended base shape:
```text
.
├─ pyproject.toml
├─ .env.example
├─ README.md
├─ src/
│ └─ app/
│ ├─ __init__.py
│ ├─ main.py
│ ├─ bootstrap.py
│ ├─ config.py
│ ├─ logging.py
│ ├─ api/
│ │ ├─ __init__.py
│ │ └─ health.py
│ ├─ services/
│ │ ├─ __init__.py
│ │ └─ example_service.py
│ └─ ui/
│ ├─ __init__.py
│ ├─ components/
│ │ ├─ __init__.py
│ │ └─ nav.py
│ └─ pages/
│ ├─ __init__.py
│ ├─ home.py
│ ├─ dashboard.py
│ └─ about.py
└─ tests/
├─ test_health.py
└─ test_pages_registration.py
```
### 2) Decision points
#### Database needed?
- If no: keep `services/` pure and skip persistence layers.
- If yes: add `db/` package with engine/session/model/repository layering.
- Prefer one process-level engine and request-scoped sessions via `yield`.
- Prefer Alembic migrations for schema changes.
#### AI workflow needed?
- If no: keep `services/` focused on app logic only.
- If yes: add `ai/` package (state, nodes, graph, runtime, contracts).
- Keep graph internals out of `ui/pages/` and API handlers.
- Use stable thread/session IDs for resumable flows.
#### Mounted docs needed?
- If no: skip docs mounting.
- If yes: mount generated static site under configurable route (default `/docs`).
- Keep docs mounting in composition layer, not page modules.
### 3) Page and component registration
- Require at minimum page modules for `/`, `/dashboard`, `/about`.
- Prefer explicit registration pattern:
- `ui/pages/__init__.py` exports `register_pages()`.
- Each page module exports `register_page()`.
- Shared shell components (header/nav/drawer) live in `ui/components/`.
### 4) Dependency direction rules
Prefer:
- `main/bootstrap` -> `config/logging` + `api` + `ui/pages` + `services`
- `api` -> `services`
- `ui/pages` -> `ui/components` + `services`
- `services` -> helpers/clients (and `db/` when enabled)
Avoid reverse imports from services into API or UI modules.
### 5) Testing minimums
- Test FastAPI health route behavior.
- Test page registration wiring.
- If DB enabled: session lifecycle and rollback behavior tests.
- If AI enabled: graph happy path and interrupt/resume coverage.
- If docs enabled: mounted docs route returns index page.
### 6) Styling architecture
- Keep structure and layout in Python modules using NiceGUI class composition.
- Keep visual polish in shared CSS files, loaded once at startup.
- Prefer semantic reusable classes over ad hoc per-page styling.
## Completion Checks
- Uses app factory and FastAPI lifespan.
- Pages are modularized (not single-file UI).
- Health endpoint exists on FastAPI side.
- Dependency direction is clean and one-way.
- Optional DB/AI/docs decisions are explicit and reflected in structure.
- Output includes architecture summary and package-organized checklist.
## Output Contract
Return:
- Concise high-level architecture.
- How core services, pages, and shared components fit.
- DB involvement and ownership stance.
- AI workflow stance and runtime flow.
- Checklist plan by package and domain:
- key functions/classes
- settings/config surfaces
- rollout/migration notes (when relevant)
## Guardrails
- Do not collapse all pages into one file.
- Do not use globals or implicit global side effects.
- Keep code minimal but production-minded.
- Prefer clarity and maintainability over clever abstractions.
## References
- Architecture and integration details: [NiceGUI architecture reference](./references/architecture.md)
- Source documentation links: [NiceGUI source documentation](./references/source-documentation.md)
+92
View File
@@ -0,0 +1,92 @@
# NiceGUI Architecture Reference
This reference expands the workflow in the main skill file and is loaded only when needed.
## Baseline package boundaries
- `main.py`: process entrypoint only.
- `bootstrap.py`: app composition, router wiring, page registration, lifespan orchestration.
- `config.py`: typed settings and env parsing.
- `logging.py`: centralized logging setup.
- `api/`: HTTP transport layer; delegates to services.
- `services/`: business/use-case logic.
- `ui/pages/`: route-level NiceGUI pages.
- `ui/components/`: shared UI building blocks.
## Required baseline behavior
- FastAPI is the base ASGI app.
- NiceGUI pages are modular and registered from page modules.
- Minimum pages: `/`, `/dashboard`, `/about`.
- FastAPI health route: `/healthz`.
- Lifespan handles startup/shutdown resources.
- No global side effects at import time.
## Optional extension: Database
Use only if persistence is required.
Suggested additions:
```text
src/app/db/
├─ __init__.py
├─ base.py
├─ session.py
├─ models/
└─ repositories/
```
Guidelines:
- One engine and one sessionmaker per process.
- Request-scoped session dependency using `yield`.
- Explicit transaction boundaries in service/repository flows.
- Avoid shared sessions across concurrent tasks.
- Use Alembic as schema source of truth.
## Optional extension: LangGraph AI
Use only for multi-step AI orchestration or human-in-the-loop workflows.
Suggested additions:
```text
src/app/ai/
├─ state.py
├─ nodes/
├─ graphs/
├─ runtime.py
└─ contracts.py
```
Guidelines:
- Keep graph internals outside API/UI modules.
- Invoke graph through `services/ai_service.py`.
- Use stable thread/session IDs for resumable sessions.
- Keep interrupt payloads JSON-serializable.
## Optional extension: Mounted static docs
Use only when generated docs should be served in-app.
Suggested settings:
- `docs_enabled`
- `docs_mount_path`
- `docs_site_dir`
- `docs_require_build` (optional)
Guidelines:
- Mount docs in composition layer (`bootstrap.py`).
- Normalize mount path and avoid route conflicts.
- Warn on missing build artifacts unless strict mode is enabled.
## Suggested output quality criteria
- Clear architecture summary with assumptions.
- Explicit decisions for DB, AI, and docs.
- Package-scoped implementation checklist.
- Minimal test plan aligned to enabled features.
@@ -0,0 +1,35 @@
# Source Documentation
Use these links for framework-specific details.
## FastAPI
- FastAPI lifespan events: https://fastapi.tiangolo.com/advanced/events/
- FastAPI settings and environment variables: https://fastapi.tiangolo.com/advanced/settings/
- FastAPI dependencies with yield: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/
- FastAPI SQL databases tutorial: https://fastapi.tiangolo.com/tutorial/sql-databases/
## SQLAlchemy and Alembic
- SQLAlchemy engine configuration and pooling: https://docs.sqlalchemy.org/en/20/core/engines.html
- SQLAlchemy session lifecycle basics: https://docs.sqlalchemy.org/en/20/orm/session_basics.html
- Alembic tutorial: https://alembic.sqlalchemy.org/en/latest/tutorial.html
## Pydantic
- Pydantic settings management: https://pydantic.dev/docs/validation/latest/concepts/pydantic_settings/
## NiceGUI
- NiceGUI pages/routing and FastAPI integration: https://www.nicegui.io/documentation/section_pages_routing
- NiceGUI security best practices: https://www.nicegui.io/documentation/section_security
## LangGraph
- LangGraph overview: https://docs.langchain.com/oss/python/langgraph/overview
- LangGraph quickstart: https://docs.langchain.com/oss/python/langgraph/quickstart
- LangGraph workflows and agents: https://docs.langchain.com/oss/python/langgraph/workflows-agents
- LangGraph persistence: https://docs.langchain.com/oss/python/langgraph/persistence
- LangGraph memory concepts: https://docs.langchain.com/oss/python/concepts/memory
- LangGraph streaming: https://docs.langchain.com/oss/python/langgraph/streaming
- LangGraph interrupts and human-in-the-loop: https://docs.langchain.com/oss/python/langgraph/interrupts
+136
View File
@@ -0,0 +1,136 @@
---
name: pytest-scaffolding
description: "Scaffold a maintainable, hierarchical pytest suite for core functionality first, then extend safely. Use when setting up tests, organizing fixtures by dependency, mirroring src structure in tests, or enforcing fast-by-default test runs."
argument-hint: "Target scope (for example: app/services/job, app/ai, or full repo)"
---
# Pytest Scaffolding
Create test scaffolding that is:
- Hierarchical: test layout roughly mirrors source layout.
- Fast by default: most tests run in under a second total for core units.
- Dependency-aware: slow/external dependencies are isolated behind markers and fixture scope.
- Extensible: minimal initial skeleton supports adding detailed tests later without refactors.
This repository currently uses:
- `uv run pytest` as the canonical test invocation.
- `pyproject.toml` pytest config under `[tool.pytest.ini_options]`.
- strict marker checking (`--strict-markers`).
Load [pytest references](./references/pytest-docs.md) when you need detailed rules.
## When To Use
- Bootstrapping tests for a new or existing Python repo.
- Reorganizing tests that have become flat, slow, or difficult to extend.
- Defining fixture boundaries before writing many assertions.
- Creating only the first-layer scaffold for core behavior (not exhaustive coverage yet).
## Inputs To Collect
1. Target test scope: full repo, package, or module.
2. Dependency profile: pure Python, DB, network/API, filesystem, UI/browser.
3. Runtime expectation: what must be instant vs allowed to be slower.
4. CI policy: which marker groups must block merges.
If these are missing, ask concise clarifying questions before editing.
## Workflow
1. Map source tree to test tree.
2. Classify tests by dependency cost.
3. Create minimal directories and placeholder test modules.
4. Create fixture layers (`tests/conftest.py` plus local `conftest.py` in subtrees only when needed).
5. Register markers and default selection behavior.
6. Run collection and fast path tests.
7. Report gaps and next extension points.
## Step 1: Map Source To Tests
Create a mirrored structure rooted at `tests/` that follows major source concepts.
Example mapping pattern:
- `src/app/services/job.py` -> `tests/app/services/test_job.py`
- `src/app/ai/graphs/transcription.py` -> `tests/app/ai/graphs/test_transcription.py`
- `src/app/api/routes.py` -> `tests/app/api/test_routes.py`
Rules:
- One initial test module per core source module.
- Prefer `test_<module>.py` naming.
- Keep directory mirrors shallow first; add deeper modules only where behavior is complex.
## Step 2: Classify By Dependency Cost
Assign each test module to one initial class:
- `unit`: no DB/network/filesystem side effects; instant execution.
- `integration`: touches DB, HTTP stack, workflow runtime, or external services.
- `smoke`: thin end-to-end confidence checks.
Decision logic:
- If logic can run with fakes/stubs, make it `unit`.
- If contract with framework/DB is essential, make it `integration`.
- If validating a user-critical path across layers, make it `smoke`.
## Step 3: Scaffold Minimal Test Modules
For each target module, scaffold:
- import section
- one happy-path test function
- one error/edge test function
- TODO comments indicating detail expansion points
Keep assertions minimal but behavior-focused. Avoid large fixtures in module files.
## Step 4: Fixture Layering Strategy
Use fixture scopes based on cost:
- `function` scope by default.
- broader scopes (`module`/`session`) only for expensive setup with clear teardown.
Layer fixtures by directory:
- `tests/conftest.py`: global, lightweight fixtures only (factories, deterministic defaults).
- subtree `conftest.py`: domain-specific fixtures (API client, DB session, AI runtime stubs).
Guidelines:
- Prefer yield fixtures for setup/teardown.
- Keep fixtures atomic (one state-changing responsibility per fixture).
- Avoid autouse except for truly universal behavior.
## Step 5: Marker Taxonomy And Config
Ensure marker names are explicit and registered in `pyproject.toml` because strict markers are enabled.
Recommended baseline markers:
- `unit`
- `integration`
- `smoke`
- `slow`
- `external` (requires network/service credentials)
Default run strategy:
- Fast local path: run only `unit` by default in day-to-day iteration.
- Full validation path: run all markers in CI or pre-release checks.
## Step 6: Execution And Verification
Run commands in this order:
1. `uv run pytest --collect-only -q`
2. `uv run pytest -m unit -q`
3. `uv run pytest -q` (if dependencies are available)
Optional targeted runs:
- by node id for one test
- by `-k` expression for focused iteration
## Step 7: Completion Checks
A scaffold pass is complete when all are true:
1. Every core source area has at least one corresponding test module.
2. Unit tests run quickly and deterministically.
3. Integration/external tests are isolated by marker and fixture boundaries.
4. No unregistered marker warnings/errors.
5. `tests/` structure is understandable without extra documentation.
6. A clear TODO path exists for deepening assertions later.
## Branching Scenarios
- If external APIs are required: provide stubs/mocks for unit tests; guard real calls behind `external` marker.
- If DB is required: build a dedicated integration fixture layer and keep unit tests DB-free.
- If tests become slow: split slow tests via marker and widen fixture scope only where safe.
- If naming conflicts appear: keep unique test module names or package test directories explicitly.
## Output Format
When applying this skill, provide:
1. Proposed test tree diff.
2. Marker and fixture plan.
3. Exact commands for fast path and full path.
4. Risks/open questions before writing detailed assertions.
@@ -0,0 +1,22 @@
# Pytest Documentation Notes
Primary references used:
- https://docs.pytest.org/en/stable/explanation/goodpractices.html
- https://docs.pytest.org/en/stable/how-to/fixtures.html
- https://docs.pytest.org/en/stable/example/markers.html
- https://docs.pytest.org/en/stable/reference/customize.html
- https://docs.pytest.org/en/stable/explanation/flaky.html
## Practical Guidance For This Skill
- Use src-aligned test layout and keep test discovery conventional.
- Keep fixtures small, composable, and explicit; use `yield` for teardown.
- Register custom markers and keep strict marker validation on.
- Separate quick unit runs from slower integration/external runs.
- Minimize flakiness by controlling shared state and avoiding hidden dependencies.
- Use `--collect-only` and marker-filtered runs to validate scaffold quality early.
## Commands Worth Remembering
- `uv run pytest --collect-only -q`
- `uv run pytest -m unit -q`
- `uv run pytest -m "not external" -q`
- `uv run pytest -q`