Files
resolutionflow/docs/superpowers/specs/2026-03-16-empty-states-onboarding-exports-design.md
chihlasm 9897b660dd docs: fix test spec screenshot size to match 2MB validation limit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:59:04 -04:00

20 KiB
Raw Blame History

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.40.7 range (needs to be visible on #101114 dark background)
  • Title: text-foreground, text-lg (18px), font-semibold (matches existing EmptyState.tsx)
  • 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 a new onboarding_dismissed Boolean column on the users table (requires migration). Not using JSON — a simple column is clearer and queryable.
  • 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:

{
  "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 onboarding_dismissed=True on the user record.

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: branding columns (logo_data, logo_content_type, company_display_name) added directly to the users table. Same schema as teams. Solo pros without a team still get branded exports.

Why Base64 in DB

Logos are small (< 2MB raw, ~2.67MB base64-encoded) and there's one per team/user. The 2MB validation limit applies to the raw uploaded file size (before base64 encoding). 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

System dependencies (required by WeasyPrint):

  • libpango1.0-dev, libcairo2-dev, libgdk-pixbuf2.0-dev, libffi-dev
  • Must be added to the Railway Dockerfile via apt-get install
  • Local dev: install via system package manager (apt-get on Ubuntu/Debian)
  • CI: add to the e2e job's setup step

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
  • Update SessionExport schema: change format field pattern from ^(text|markdown|html|psa)$ to ^(text|markdown|html|psa|pdf)$
  • PDF format returns Response(content=pdf_bytes, media_type="application/pdf") with Content-Disposition: attachment; filename="session-export-{id}.pdf" header (different return type from the existing PlainTextResponse used by other formats — endpoint must branch on format)
  • Non-PDF formats continue returning PlainTextResponse as before

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). The modal should switch to a "download-only" mode when PDF is selected: hide the textarea, show a download button with loading state. The format selector stays visible for switching between formats.
  • Show a loading spinner while PDF generates server-side
  • Existing formats (markdown, text, HTML, PSA) continue to work as before with the textarea preview

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
updated_at DateTime(timezone=True) Auto-set, auto-update

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.
  • PATCH /api/v1/sessions/{session_id}/supporting-data/{id} — update label or content.
  • DELETE /api/v1/sessions/{session_id}/supporting-data/{id} — remove an item.

Validation

  • Image size: max 2MB per screenshot (keeps DB growth manageable — at 20 items × 2.67MB base64 = ~53MB worst case per session)
  • Text snippet: max 50,000 characters
  • Max 20 items per session
  • Only the session owner or team admins can add/delete
  • Monitor DB size growth in production — if supporting data exceeds expectations, prioritize BYOS migration

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 ![label](data:image/...) 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/
  • Written as React components in frontend/src/pages/guides/ (avoids react-markdown dependency for only 7 short pages). Each guide is a simple functional component using existing typography classes.
  • Displayed in a .glass-card-static container within the standard app shell layout
  • Simple breadcrumb: "Guides → {title}"
  • Images/illustrations stored in frontend/public/guides/ and referenced via absolute paths
  • Unknown slugs show a "Guide not found" empty state with a link back to the dashboard

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 2MB 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

  • onboarding_dismissed column on users table + migration
  • Team branding columns (logo_data, logo_content_type, company_display_name) on teams table + migration
  • Solo pro branding columns on users table + migration (can combine with onboarding migration)
  • Branding CRUD endpoints
  • Supporting data table + migration
  • Supporting data CRUD endpoints (POST, GET, PATCH, DELETE)
  • Onboarding status endpoint + dismiss endpoint
  • WeasyPrint dependency + system deps in Dockerfile + PDF generation in export service
  • Update SessionExport schema format pattern to include pdf
  • 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.