2026-04-13 10:46:29 -05:00

214 lines
6.4 KiB
Markdown

---
name: vision-design
description: Applies Vision's official design, standards, and application builds.
license: Internal Use Only
---
# Vision Application Design
## Overview
Use this skill whenever developing for the Vision program — whether starting a new app, doing continual development on an existing one, or answering any questions about Vision. It covers architecture, design standards, authentication, app packaging, and backend conventions.
**Keywords**: vision, portal, dashboard, corporate identity, visual identity, post-processing, vision-frontend, vision-backendapi
**When making UI elements, always invoke the `brand-guidelines` skill.**
---
## Projects
Vision is split into two separate projects:
- **Vision-Frontend** — Houses all user interfaces, Django templates, session management, and user authentication. Does not store client data.
- **Vision-BackendAPI** — Houses the REST API, data warehouse, ETL pipelines, and cron jobs. Stores all client data. Cannot be reached directly from the frontend.
---
## Software Guidelines
### Language and Software Foundation
- Language: Python 3.11
- Framework: Django 5.2.11
- Database: Postgres (separate databases for frontend and backend)
- Reverse Proxy: Nginx
### Architecture
- Frontend and backend are fully decoupled
- Frontend communicates with the backend exclusively via API requests
- Rendering is done through Django templates
- Frontend database: user authentication and permissions only
- Backend database: client data warehouse
---
## Frontend Design
### Layout
Vision uses a consistent three-region layout across all pages:
- **Left sidebar** — navigation column, included via `{% include '_sidebar.html' %}`
- **Header** — top bar, included via `{% include '_header.html' %}`
- **Main window** — all app content renders here via `{% block content %}`
### Template Conventions
All templates extend `base.html`:
```html
{% extends 'base.html' %}
{% block extra_head %}
{# App-specific CSS or meta tags #}
{% endblock %}
{% block content %}
{# App UI renders here #}
{% endblock %}
{% block extra_scripts %}
{# App-specific JavaScript #}
{% endblock %}
```
Key blocks:
- `extra_head` — inject app-specific styles or meta into `<head>`
- `content` — primary render target for all apps
- `extra_scripts` — inject app-specific scripts before `</body>`
### CSS and Styling
- Custom CSS only — minimize third-party CSS dependencies
- Follow brand colors, typography, and spacing from the `brand-guidelines` skill
- Static files are served per-app from the app's own `static/` folder
---
## App Development
### Development Philosophy
- Vision has a core project and application
- Additional features are built as **separate Django apps**
- Apps are developed in isolation, then packaged and deployed to the main project
- This prevents feature conflicts and allows simultaneous development
### New App Structure
Every Vision app must include:
```
my_app/
├── static/
│ └── my_app/ # Namespaced static files
├── templates/
│ └── my_app/ # Namespaced templates
├── urls.py
├── views.py
├── models.py
├── apps.py
└── README.md # Required: installation instructions
```
The `README.md` must document:
- Any required entries in `INSTALLED_APPS`
- URL routing configuration to add to the host project
- Any required settings variables
- Migration steps if models are included
### App Scaffolding
New apps are generated from the **Vision app template repo**, which provides:
- A pre-provisioned `djangoappdev` Django project for local development
- Base templates matching the production layout (`base.html`, `_header.html`, `_sidebar.html`)
- Base static files matching production
Always start new apps from this template repo rather than from scratch.
### Packaging and Distribution
- Apps are packaged as pip-installable packages
- Distributed via Vision's **private PyPI repository**
- Installed into Vision-Frontend or Vision-BackendAPI via pip
---
## Security
### Data Isolation
- User authentication and permissions live in the **Vision-Frontend database only**
- Client data lives in the **Vision-BackendAPI database only**
- The backend database is not reachable from the frontend
### Authentication — Wristband SSO
Vision uses [Wristband](https://wristband.dev) for SSO and OAuth.
**Frontend (Vision-Frontend):**
- Handles the full OAuth authentication workflow
- Manages user sessions based on Wristband
- On successful auth, receives and stores a **bearer token**
- Includes the bearer token in all API requests to Vision-BackendAPI
- Uses **middleware** to enforce session/auth requirements across views
- Template `{% if %}` checks control whether UI elements are rendered based on user permissions/roles
**Backend (Vision-BackendAPI):**
- Validates incoming bearer tokens by calling Wristband's API, which returns the user's email
- Looks up that email in the Vision-Frontend database to verify permissions
- Does not manage sessions directly
### Permissions Model
- Users are assigned to **groups**, each representing a tenant/client
- Groups have **memberships** that grant tenants access to specific features
- Groups have **roles** that grant individual users permissions within a tenant
---
## Backend — Vision-BackendAPI
### ETL Pipelines
- ETLs pull vendor metrics for each client
- Data is normalized into a standardized format and stored in the data warehouse
- The data warehouse is consumed by Vision's custom LLM
### Cron Jobs
The backend manages scheduled tasks including:
- Refreshing and updating vendor data
- Updating user information
- Cleaning up stale data
- Sending queued messages to external tools and notification systems
---
## Technical Detail
### URL Routing
- Each app defines its own `urls.py`
- Apps are registered in the host project's root `urls.py` using `include()`
- Use app namespaces to avoid URL name collisions
### API Communication (Frontend → Backend)
- All requests include an `Authorization: Bearer <token>` header
- The backend never trusts the frontend's claim of who the user is — it always validates the token with Wristband
### Template Permission Checks
Use `{% if %}` guards in templates to conditionally render features:
```html
{% if user_has_feature %}
<a href="{% url 'my_app:index' %}">Feature Name</a>
{% endif %}
```
Never rely solely on URL access controls — template-level guards keep hidden features out of the rendered HTML entirely.