Compare commits
5 Commits
5649b9ace6
...
57da7e001e
| Author | SHA1 | Date | |
|---|---|---|---|
| 57da7e001e | |||
| 35a3a8dbed | |||
| c8906cef7b | |||
| 8ada18b7fd | |||
| bbbf7e6c7d |
@@ -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")
|
||||

|
||||

|
||||
```
|
||||
|
||||
## 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.
|
||||
```
|
||||
@@ -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 LangGraph’s `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
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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`
|
||||
Reference in New Issue
Block a user