--- 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 `` - `content` — primary render target for all apps - `extra_scripts` — inject app-specific scripts before `` ### 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 ` 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 %} Feature Name {% endif %} ``` Never rely solely on URL access controls — template-level guards keep hidden features out of the rendered HTML entirely.