feat: empty states, onboarding checklist, PDF exports, and supporting data #114
@@ -0,0 +1,424 @@
|
||||
# Empty States, Onboarding & Professional Exports — Design Spec
|
||||
|
||||
> **Date:** 2026-03-16
|
||||
> **Product:** ResolutionFlow
|
||||
> **Approach:** Bottom-up (foundation → empty states → onboarding → exports)
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Make ResolutionFlow feel polished and professional by eliminating dead-end empty pages, guiding new users through setup, and providing client-ready PDF exports that MSPs can hand directly to customers.
|
||||
|
||||
---
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
1. Illustrative empty states across 8 pages with benefit-oriented copy and "Learn more" guide links
|
||||
2. Onboarding starter checklist widget on QuickStartPage (solo and team variants)
|
||||
3. Team branding settings (logo upload, company display name)
|
||||
4. PDF export via WeasyPrint with branded templates
|
||||
5. Supporting data capture during sessions (text snippets + screenshots)
|
||||
6. 7 in-app user guides linked from empty states
|
||||
7. Tests: backend integration, frontend unit, Playwright e2e
|
||||
|
||||
### Out of Scope
|
||||
|
||||
- Bring-your-own-storage (S3/Azure) for supporting data — future feature
|
||||
- Full file attachments beyond screenshots
|
||||
- Removing "Powered by ResolutionFlow" footer (potential premium tier)
|
||||
- Multi-browser Playwright matrix
|
||||
|
||||
---
|
||||
|
||||
## 1. Empty States
|
||||
|
||||
### Component Upgrade
|
||||
|
||||
Extend the existing `EmptyState.tsx` component to support the illustrative style:
|
||||
|
||||
- **SVG illustration slot** — optional prop, renders a brand-colored line-art illustration above the title
|
||||
- **Benefit-oriented description** — explains what the page does and why it matters, not just "no data"
|
||||
- **Primary CTA button** — navigates to the action that populates the page
|
||||
- **Secondary "Learn more" link** — navigates to the relevant in-app guide
|
||||
|
||||
### Pages (8 total)
|
||||
|
||||
| Page | Title | Description | CTA | Guide Link |
|
||||
|------|-------|-------------|-----|------------|
|
||||
| Flow Library (no flows) | Build your first troubleshooting flow | Flows guide your team through proven resolution paths, capturing every decision along the way. | Create a Flow | `/guides/creating-flows` |
|
||||
| Flow Library (no filter results) | No flows match your filters | Try adjusting your search or filters. | Clear Filters | — |
|
||||
| Analytics (My/Team) | Track your troubleshooting performance | Analytics show resolution times, common paths, and team efficiency. Data appears automatically as you complete sessions. | Run Your First Session | `/guides/understanding-analytics` |
|
||||
| Session History (empty) | Your session history will appear here | Every troubleshooting session is recorded with decisions, timing, and outcomes — ready for export or review. | Start a Session | `/guides/running-sessions` |
|
||||
| Integrations | Connect your PSA for seamless workflows | Link ConnectWise or other PSA tools to pull ticket context into sessions and push documentation back automatically. | Connect Integration | `/guides/psa-setup` |
|
||||
| Step Library (empty) | Build a reusable step library | Save common troubleshooting steps once, reuse them across flows. Keeps your team consistent and saves build time. | Browse Steps | `/guides/step-library` |
|
||||
| Script Library (empty) | Automate with script templates | Pre-built and custom scripts your team can reference during sessions. PowerShell, bash, and more. | Explore Templates | `/guides/script-templates` |
|
||||
| My Shares (empty) | Share session results with your team | Create shareable links to completed sessions for knowledge sharing and client communication. | View Sessions | `/guides/sharing-sessions` |
|
||||
|
||||
### Illustrations
|
||||
|
||||
Simple SVG line art using the cyan brand color palette (`#06b6d4` → `#22d3ee`). Each page gets a unique illustration relevant to its content. Lightweight — no complex animations or heavy graphics.
|
||||
|
||||
### Visual Style
|
||||
|
||||
- Container: centered content within the page's existing layout
|
||||
- Illustration: 60-80px height, `opacity: 0.3` → `0.5` range for subtlety
|
||||
- Title: `text-foreground`, 14px, `font-semibold`
|
||||
- Description: `text-muted-foreground`, 13px, max-width ~400px for readability
|
||||
- CTA: `bg-gradient-brand` primary button style
|
||||
- Learn more: `text-muted-foreground` with `→` arrow, hover brightens
|
||||
|
||||
---
|
||||
|
||||
## 2. Onboarding Starter Checklist
|
||||
|
||||
### Location
|
||||
|
||||
Dismissible `.glass-card` widget on QuickStartPage, positioned below the greeting and above the stats/activity sections.
|
||||
|
||||
### Visibility Rules
|
||||
|
||||
- Shows for users who haven't dismissed it and haven't completed all items
|
||||
- Auto-hides with a brief "You're all set!" state once all items are checked, then disappears
|
||||
- Dismissible at any time via "×" button
|
||||
- Dismissed/completed state stored in `user_preferences` (existing JSON column)
|
||||
- Never reappears once dismissed or completed
|
||||
|
||||
### Completion Tracking
|
||||
|
||||
No new database table. A single API endpoint queries existing data to determine completion status.
|
||||
|
||||
**Endpoint:** `GET /api/v1/users/onboarding-status`
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"created_flow": true,
|
||||
"ran_session": false,
|
||||
"exported_session": false,
|
||||
"tried_ai_assistant": false,
|
||||
"invited_teammate": false,
|
||||
"connected_psa": false,
|
||||
"is_team_user": true,
|
||||
"dismissed": false
|
||||
}
|
||||
```
|
||||
|
||||
**Completion queries:**
|
||||
|
||||
| Item | Condition |
|
||||
|------|-----------|
|
||||
| `created_flow` | User owns at least 1 tree |
|
||||
| `ran_session` | User has at least 1 session |
|
||||
| `exported_session` | User has at least 1 session with `exported=True` |
|
||||
| `tried_ai_assistant` | User has at least 1 assistant chat |
|
||||
| `invited_teammate` | Team has more than 1 member |
|
||||
| `connected_psa` | Team has at least 1 PSA connection |
|
||||
|
||||
**Dismiss endpoint:** `POST /api/v1/users/onboarding-status/dismiss` — sets `dismissed=true` in user preferences.
|
||||
|
||||
### Checklist Variants
|
||||
|
||||
**Solo pro (4 items):**
|
||||
|
||||
1. Create your first flow → navigates to Flow Library
|
||||
2. Run your first session → navigates to Flow Library
|
||||
3. Export a session → navigates to Session History
|
||||
4. Try the AI assistant → navigates to AI Chat
|
||||
|
||||
**Team admin (5 items):**
|
||||
|
||||
1. Create your first flow → navigates to Flow Library
|
||||
2. Invite a team member → navigates to Team Settings
|
||||
3. Run your first session → navigates to Flow Library
|
||||
4. Connect a PSA integration → navigates to Integrations
|
||||
5. Export a session → navigates to Session History
|
||||
|
||||
### Visual Design
|
||||
|
||||
- `.glass-card` container with `border-radius: 16px`
|
||||
- Cyan progress bar at top showing completion (e.g., "2 of 5 complete")
|
||||
- Section label: "Getting Started" in `font-label text-[0.625rem] uppercase tracking-[0.1em]`
|
||||
- Each item: checkbox (auto-checked with cyan fill when complete) + label + subtle navigation arrow
|
||||
- Completed items: muted text with cyan checkmark
|
||||
- Uncompleted items: `text-foreground` with hover highlight, clickable to navigate
|
||||
|
||||
---
|
||||
|
||||
## 3. Team Branding & Logo Upload
|
||||
|
||||
### Location
|
||||
|
||||
New "Branding" section on the existing Team Settings page. Team admin only. Solo pros get a simpler version on their Account Settings page.
|
||||
|
||||
### Fields
|
||||
|
||||
- **Company logo** — image upload (PNG, JPG, or SVG, max 2MB)
|
||||
- **Company display name** — text field, falls back to team name if empty
|
||||
- **Logo preview** — shows how the logo will appear on exports
|
||||
|
||||
### Backend
|
||||
|
||||
**New columns on `teams` table:**
|
||||
|
||||
- `logo_data` — Text, base64-encoded image data, nullable
|
||||
- `logo_content_type` — String (e.g., `image/png`), nullable
|
||||
- `company_display_name` — String, nullable (falls back to `team.name`)
|
||||
|
||||
**Endpoints:**
|
||||
|
||||
- `PATCH /api/v1/teams/{team_id}/branding` — upload logo (multipart form) + display name. Team admin only.
|
||||
- `GET /api/v1/teams/{team_id}/branding` — retrieve logo data + display name. Any team member.
|
||||
- `DELETE /api/v1/teams/{team_id}/branding/logo` — remove logo. Team admin only.
|
||||
|
||||
**Validation:**
|
||||
|
||||
- File size: max 2MB
|
||||
- Content type: `image/png`, `image/jpeg`, `image/svg+xml`
|
||||
- Solo pros: same fields stored on user record or preferences — decided during implementation
|
||||
|
||||
### Why Base64 in DB
|
||||
|
||||
Logos are small (< 2MB) and there's one per team. Avoids S3/file storage dependency entirely. Easy to migrate to object storage later when BYOS is implemented for supporting data.
|
||||
|
||||
---
|
||||
|
||||
## 4. PDF Export via WeasyPrint
|
||||
|
||||
### Backend
|
||||
|
||||
**New dependency:** `weasyprint` in `requirements.txt`
|
||||
|
||||
**Export service changes:**
|
||||
|
||||
- New `generate_pdf()` method in `export_service.py`
|
||||
- Renders a Jinja2 HTML template with session data + branding, then converts to PDF via WeasyPrint
|
||||
- Template location: `backend/app/templates/export_pdf.html`
|
||||
|
||||
**Existing endpoint change:**
|
||||
|
||||
- `POST /sessions/{session_id}/export` gains `format: "pdf"` option
|
||||
- Returns `application/pdf` with `Content-Disposition: attachment; filename="session-export-{id}.pdf"` header
|
||||
|
||||
### PDF Template Structure
|
||||
|
||||
Matches the approved mockup layout:
|
||||
|
||||
1. **Header** — Report type label (e.g., "Troubleshooting Report"), flow title, MSP logo or ResolutionFlow logo, company name
|
||||
2. **Metadata grid** — Engineer, Client, Ticket #, Date, Duration, Outcome (3×2 grid)
|
||||
3. **Summary** — AI-generated session summary (from existing feature)
|
||||
4. **Troubleshooting Path** — Visual timeline with cyan step dots, step titles, and decisions at each node. Final resolution step uses green dot.
|
||||
5. **Supporting Data** — Labeled text snippets (rendered as code blocks) + embedded screenshot images
|
||||
6. **Footer** — Generation timestamp (left) + "Powered by ResolutionFlow" (right)
|
||||
|
||||
### CSS/Styling
|
||||
|
||||
- White background, dark text (print-optimized)
|
||||
- Cyan accent color (`#06b6d4`) for section borders, timeline dots, and branding
|
||||
- `@page` rules for margins, header/footer positioning
|
||||
- Page break before Supporting Data section if content runs long
|
||||
- `break-inside: avoid` on individual supporting data items
|
||||
- JetBrains Mono for code/command output blocks
|
||||
|
||||
### Frontend Changes
|
||||
|
||||
- Add "PDF" to the format selector in `ExportPreviewModal`
|
||||
- PDF option triggers a direct file download (no textarea preview — PDFs aren't editable inline)
|
||||
- Show a loading spinner while PDF generates server-side
|
||||
- Existing formats (markdown, text, HTML, PSA) continue to work as before
|
||||
|
||||
### Branding Logic
|
||||
|
||||
1. If team has a logo → use team logo + company display name in header, "Powered by ResolutionFlow" in footer
|
||||
2. If no team logo → use ResolutionFlow logo in header, no "Powered by" footer (it's already the primary brand)
|
||||
3. Solo pro with logo → same as team logo behavior
|
||||
|
||||
---
|
||||
|
||||
## 5. Supporting Data Capture
|
||||
|
||||
### Database
|
||||
|
||||
**New table: `session_supporting_data`**
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | UUID | Primary key |
|
||||
| `session_id` | UUID | FK to sessions |
|
||||
| `label` | String(255) | User-provided label (e.g., "Port Scan Output") |
|
||||
| `data_type` | Enum | `text_snippet` or `screenshot` |
|
||||
| `content` | Text | Raw text or base64-encoded image |
|
||||
| `content_type` | String(50) | Nullable. e.g., `image/png` for screenshots |
|
||||
| `sort_order` | Integer | Display ordering |
|
||||
| `created_at` | DateTime(timezone=True) | Auto-set |
|
||||
|
||||
### API Endpoints
|
||||
|
||||
- `POST /api/v1/sessions/{session_id}/supporting-data` — add an item (label, type, content). Returns created item.
|
||||
- `GET /api/v1/sessions/{session_id}/supporting-data` — list all items for a session, ordered by `sort_order`.
|
||||
- `DELETE /api/v1/sessions/{session_id}/supporting-data/{id}` — remove an item.
|
||||
|
||||
### Validation
|
||||
|
||||
- Image size: max 5MB per screenshot
|
||||
- Text snippet: max 50,000 characters
|
||||
- Max 20 items per session
|
||||
- Only the session owner or team admins can add/delete
|
||||
|
||||
### Session Runner UI
|
||||
|
||||
- **"Add Supporting Data" button** — positioned near the existing notes input in both troubleshooting and procedural session runners
|
||||
- **Add modal** with two tabs/options:
|
||||
- **Text Snippet** — label input + multiline textarea
|
||||
- **Screenshot** — label input + drag-and-drop zone / file picker + clipboard paste (`Ctrl+V`) support
|
||||
- **Supporting data list** — collapsible section below session notes showing added items:
|
||||
- Each item: type icon (code bracket for text, image icon for screenshot) + label + preview (truncated text or thumbnail) + delete button
|
||||
- No reordering in v1 — items display in creation order
|
||||
|
||||
### Export Integration
|
||||
|
||||
Supporting data is included in all export formats:
|
||||
|
||||
| Format | Text Snippets | Screenshots |
|
||||
|--------|--------------|-------------|
|
||||
| Markdown | Labeled fenced code blocks | `` or `[Screenshot: label]` |
|
||||
| Plain Text | Labeled indented blocks | `[Screenshot: {label}]` placeholder |
|
||||
| HTML | `<pre>` blocks with labels | `<img>` tags with base64 src |
|
||||
| PSA | Labeled code blocks (markdown) | `[Screenshot: {label}]` placeholder |
|
||||
| PDF | Styled code blocks matching mockup | Embedded images |
|
||||
|
||||
---
|
||||
|
||||
## 6. User Guides
|
||||
|
||||
### Route
|
||||
|
||||
`/guides/:slug` — new frontend route inside the authenticated app shell.
|
||||
|
||||
### Implementation
|
||||
|
||||
- Markdown files stored in `frontend/src/content/guides/`
|
||||
- Rendered with `react-markdown` (or similar lightweight renderer)
|
||||
- Displayed in a `.glass-card-static` container within the standard app shell layout
|
||||
- Simple breadcrumb: "Guides → {title}"
|
||||
|
||||
### Guides (7)
|
||||
|
||||
| Slug | Title | Content Covers |
|
||||
|------|-------|---------------|
|
||||
| `creating-flows` | Creating Flows | Manual flow creation, AI-assisted creation, flow types (troubleshooting, procedural, maintenance), basic editor usage |
|
||||
| `understanding-analytics` | Understanding Analytics | What each metric means, how data populates over time, team vs personal views |
|
||||
| `running-sessions` | Running Sessions | Starting a session, navigating decisions, adding notes, adding supporting data, completing and exporting |
|
||||
| `psa-setup` | Connecting Your PSA | ConnectWise setup walkthrough, where to find API credentials, what the integration enables |
|
||||
| `step-library` | Using the Step Library | Browsing shared steps, adding steps to flows, creating reusable steps |
|
||||
| `script-templates` | Script Templates | Browsing templates, using scripts during sessions, creating custom templates |
|
||||
| `sharing-sessions` | Sharing Sessions | Creating share links, public vs account-only access, revoking shares |
|
||||
|
||||
### Guide Content Style
|
||||
|
||||
- Concise — each guide should be 300-600 words
|
||||
- Task-oriented — "How to do X" structure, not reference documentation
|
||||
- Include relevant screenshots/illustrations where helpful
|
||||
- End with a CTA that links back to the relevant feature page
|
||||
|
||||
---
|
||||
|
||||
## 7. Testing
|
||||
|
||||
### Backend Integration Tests (pytest)
|
||||
|
||||
**Onboarding status:**
|
||||
- Returns correct booleans for a fresh user (all false)
|
||||
- Returns `created_flow: true` after user creates a tree
|
||||
- Returns `ran_session: true` after user starts a session
|
||||
- Returns correct `is_team_user` flag
|
||||
- Dismiss endpoint sets `dismissed: true`
|
||||
|
||||
**Team branding:**
|
||||
- Upload logo — stores base64, returns success
|
||||
- Upload oversized file — returns 400
|
||||
- Upload invalid content type — returns 400
|
||||
- Retrieve branding — returns logo data + display name
|
||||
- Delete logo — clears logo data
|
||||
- Non-admin cannot update branding — returns 403
|
||||
|
||||
**Supporting data:**
|
||||
- Create text snippet — stores and returns item
|
||||
- Create screenshot — stores base64 and returns item
|
||||
- List items — returns in sort order
|
||||
- Delete item — removes from DB
|
||||
- Exceed 20 item limit — returns 400
|
||||
- Exceed 5MB screenshot — returns 400
|
||||
- Non-owner cannot add to session — returns 403
|
||||
|
||||
**PDF export:**
|
||||
- Generate PDF — returns valid PDF bytes with correct content type
|
||||
- PDF includes branding when team has logo
|
||||
- PDF uses ResolutionFlow defaults when no team logo
|
||||
- PDF includes supporting data items
|
||||
- PDF handles session with no supporting data gracefully
|
||||
|
||||
### Frontend Unit Tests (Vitest)
|
||||
|
||||
- `EmptyState` component — renders illustration, title, description, CTA, and learn more link with correct props
|
||||
- `EmptyState` without optional props — renders without illustration or learn more link
|
||||
- Onboarding checklist — renders correct items for solo vs team user
|
||||
- Onboarding checklist — completed items show cyan checkmark and muted style
|
||||
- Onboarding checklist — dismiss button calls dismiss endpoint
|
||||
- Export format selector — includes PDF option
|
||||
- Export modal — PDF selection triggers download behavior instead of textarea preview
|
||||
|
||||
### Playwright E2E Tests
|
||||
|
||||
- **Empty state flow** — log in as fresh user, navigate to Flow Library, verify empty state renders with CTA and "Learn more" link
|
||||
- **Onboarding checklist** — log in as fresh user, verify checklist visible on dashboard, create a flow, verify checklist item updates
|
||||
- **PDF export** — complete a session, navigate to session detail, select PDF format, verify download triggers
|
||||
- **Guide page** — click "Learn more" from an empty state, verify guide page loads with content
|
||||
|
||||
These Playwright tests focus on happy paths only — one representative flow per feature area.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order (Bottom-Up)
|
||||
|
||||
### PR 1: Backend Foundation
|
||||
- Team branding columns + migration
|
||||
- Branding CRUD endpoints
|
||||
- Supporting data table + migration
|
||||
- Supporting data CRUD endpoints
|
||||
- Onboarding status endpoint
|
||||
- WeasyPrint dependency + PDF generation in export service
|
||||
- Backend tests for all of the above
|
||||
|
||||
### PR 2: Empty States + Guides
|
||||
- Upgrade `EmptyState.tsx` component
|
||||
- Roll out across 8 pages
|
||||
- Create 7 markdown guides
|
||||
- Add `/guides/:slug` route
|
||||
- Frontend unit tests for EmptyState
|
||||
|
||||
### PR 3: Onboarding Checklist
|
||||
- QuickStartPage checklist widget
|
||||
- Solo vs team variant logic
|
||||
- Dismiss and auto-complete behavior
|
||||
- Frontend unit tests
|
||||
- Playwright test for checklist
|
||||
|
||||
### PR 4: PDF Export + Supporting Data UI
|
||||
- Supporting data capture in session runner
|
||||
- PDF format option in ExportPreviewModal
|
||||
- Team branding section on Team Settings page
|
||||
- Playwright tests for export and empty states
|
||||
|
||||
---
|
||||
|
||||
## Future Considerations
|
||||
|
||||
- **BYOS (Bring Your Own Storage):** Allow MSPs to configure their own S3/Azure blob storage for supporting data. Removes our storage burden and addresses data sovereignty.
|
||||
- **Premium branding tier:** Option to remove "Powered by ResolutionFlow" footer for higher-tier plans.
|
||||
- **Full file attachments:** Extend supporting data to accept arbitrary file types (logs, configs, CSVs) once object storage is in place.
|
||||
- **Export templates:** Let teams customize the PDF template layout, colors, and sections included.
|
||||
- **Onboarding expansion:** Feature tours, tooltips, and contextual help beyond the starter checklist.
|
||||
Reference in New Issue
Block a user