saccoai-client-portal

Installation
SKILL.md

This skill takes the output of saccoai-design-variations and turns it into a branded review experience for clients. Instead of sharing raw Vercel preview URLs, the client gets a polished portal with variation summaries, screenshots, direct preview links, and a feedback form.

Default output is a single self-contained HTML file the agent can open in the browser and the user can email or share directly. Enterprise mode scaffolds a lightweight Next.js app with auth, real-time feedback storage, and email notifications — deployed to Vercel as a separate project.

Inputs

Input Required Default Description
Variations path No .saccoai/variations/ Path to variations output from saccoai-design-variations
Mode No static static (single HTML file) or deployed (Next.js app on Vercel)
Client name No from project Display name shown in the portal header
Branding No saccoai defaults Logo URL and accent color hex for the portal

Execution Model

Single-agent sequential. All four phases run in order. No parallelism is needed — the portal is generated from already-available variation data, and feedback collection is a user-triggered step after the client has reviewed.

Preconditions

Before starting, check:

  1. Variations output exists: Check for .saccoai/variations/comparison.md. If missing, abort with: "No variations found at .saccoai/variations/comparison.md. Run saccoai-design-variations first to generate design alternatives."
  2. At least one variation present: Parse comparison.md for variation entries. If only the baseline (variation 0 / main) is listed, abort with: "No variations found beyond the baseline. Generate at least one design variation before creating a review portal."

Phase 1: Read Variations

Collect all the data the portal needs before generating any HTML.

  1. Parse comparison metadata: Read .saccoai/variations/comparison.md. Extract for each variation:

    • Variation number and label
    • Branch name
    • Preview URL (if present)
    • Visual anchor
    • Signature element
    • Key difference summary
  2. Read design briefs: For each variation directory under .saccoai/variations/variation-{N}-{label-slug}/, read design-brief.md. Extract:

    • Emotional territory
    • Typography (display font + body font)
    • Color strategy (primary, accent, background hex values)
    • Motion plan
    • Signature element description
  3. Collect screenshots: Check .saccoai/variations/variation-{N}-{label-slug}/ for any screenshot files (.png, .jpg, .webp). Also check for a screenshot.png at the variation root. If screenshot files exist, use them. If no screenshots exist and preview URLs are available, use agent-browser to take a fresh screenshot of each preview URL:

    • Navigate to the preview URL
    • Take a full-page screenshot at 1280×800 viewport
    • Save to .saccoai/variations/variation-{N}-{label-slug}/screenshot.png
    • If no preview URL and no screenshot, note the gap — the portal card will show a placeholder.
  4. Resolve portal config: Determine the final values for:

    • client_name: from user input → fall back to the project directory name → fall back to "Your Project"
    • logo_url: from user input → fall back to https://saccoai.com/logo.svg
    • accent_color: from user input → fall back to #E8411B (saccoai red)
    • portal_mode: from user input → default static

Phase 2: Generate Portal

Static Mode (default)

Generate a single self-contained HTML file at .saccoai/variations/review-portal.html. All CSS and JavaScript must be embedded inline — no external dependencies. The file must work when opened directly from the filesystem (no server required) and must be functional when emailed as an attachment.

Structure

Header

  • Client name in large type
  • saccoai logo (or custom logo if provided) in the top-right corner
  • Accent color applied to the logo area or header bar
  • Subtitle: "Design Review — please share your feedback"

Variation Cards Grid One card per variation (not including the current/main baseline unless explicitly requested). Each card contains:

  • Screenshot (or a styled placeholder with the variation label if no screenshot is available)
  • Variation label and visual anchor (e.g., "Editorial Warmth — typography-led")
  • Key difference sentence (1 line from comparison.md)
  • Typography preview: display font name + body font name
  • Color swatches: three small circles showing primary, accent, and background hex values
  • Signature element description (1 sentence)
  • "Preview live" button — opens the Vercel preview URL in a new tab (if URL available; hidden if not)
  • Feedback textarea: "Your notes on this direction (optional)"
  • "Choose this direction" radio button

Side-by-Side Toggle A toggle control above the cards grid:

  • "Single view" (default): cards laid out in a grid
  • "Compare two": select any two variation cards and view them side by side at full width

Submit Bar (sticky bottom)

  • "Submit review" button — active only when at least one "Choose this direction" radio is selected
  • On click: collect all feedback textarea values + chosen variation → serialize to JSON → trigger a browser download of feedback.json
  • JSON structure:
{
  "submitted_at": "{ISO timestamp}",
  "client_name": "{client_name}",
  "chosen_variation": "{variation label and number}",
  "feedback": {
    "variation-1-{slug}": "{textarea content or null}",
    "variation-2-{slug}": "{textarea content or null}"
  }
}

Responsive Design

The portal must be fully functional on mobile (clients may review on their phone):

  • Cards stack to a single column below 768px
  • Side-by-side compare is hidden on mobile (toggle shows a notice: "Compare view is available on desktop")
  • Touch targets for radio buttons and the submit button must be at least 44×44px
  • Font sizes must remain legible at 375px viewport width

Visual Style

Use saccoai's default style unless overridden by the branding inputs:

  • Background: #FAFAF8 (warm off-white)
  • Text: #1A1A1A
  • Accent color: from portal config (default #E8411B)
  • Font: system-ui stack (no external font loads — the portal must work without internet access)
  • Card border: 1px solid #E5E5E5 with border-radius: 12px
  • Subtle box shadow on cards: 0 2px 8px rgba(0,0,0,0.06)
  • The accent color is applied to: selected card border highlight, "Choose this direction" radio fill, "Submit review" button background

Save to: .saccoai/variations/review-portal.html


Deployed Mode

Scaffold a lightweight Next.js app for enterprise review workflows with multiple reviewers.

Scaffold Structure

{client-slug}-review/
├── app/
│   ├── layout.tsx              # Portal branding + auth wrapper
│   ├── page.tsx                # Main review page (variation cards + feedback form)
│   ├── api/
│   │   ├── feedback/route.ts   # POST: save feedback to Upstash Redis
│   │   └── submit/route.ts     # POST: mark a direction as chosen, trigger notifications
│   └── auth/
│       └── page.tsx            # Password entry page (simple shared secret)
├── components/
│   ├── variation-card.tsx      # Individual variation card
│   ├── compare-toggle.tsx      # Side-by-side comparison control
│   └── submit-bar.tsx          # Sticky bottom submit bar
├── lib/
│   ├── redis.ts                # Upstash Redis client
│   └── email.ts                # Resend email client
├── public/
│   └── screenshots/            # Copied from .saccoai/variations/
├── .env.local                  # REDIS_URL, RESEND_API_KEY, PORTAL_PASSWORD (with placeholder values)
└── package.json

Auth

Simple shared-secret auth: a password input page at /auth. On correct password, set a cookie portal-auth=1 (24-hour expiry). Middleware blocks all routes except /auth until the cookie is present. The password is set via the PORTAL_PASSWORD environment variable.

No user accounts. Multiple reviewers share the same password. Each reviewer identifies themselves by entering their name in a "Your name" field on the main review page before submitting feedback.

Real-Time Feedback Storage

Use Upstash Redis (provisioned via Vercel Marketplace):

  • Each feedback submission is stored as a hash: feedback:{variation-slug}:{reviewer-name}{notes, chosen: true/false, submitted_at}
  • The "chosen" state for the whole portal is stored as a key: portal:chosen{variation-slug, chosen_by, chosen_at}
  • When a reviewer submits, all previously submitted feedback from other reviewers is shown as a read-only summary below the form

Email Notifications

Use Resend:

  • When any reviewer submits feedback: send a notification email to saccoai (configurable NOTIFY_EMAIL env var)
  • When a decision-maker clicks "Choose this direction" and submits: send a "Direction chosen" email to NOTIFY_EMAIL with the chosen variation details and all reviewer feedback

Deployment

  1. Install Upstash Redis via Vercel Marketplace: vercel marketplace add upstash-redis
  2. Set environment variables: PORTAL_PASSWORD, RESEND_API_KEY, NOTIFY_EMAIL
  3. Deploy: vercel deploy --name {client-slug}-review
  4. The project deploys to {client-slug}-review.vercel.app (or the assigned Vercel URL)

Phase 3: Present

Static Mode

Open the generated HTML file in the default browser:

open .saccoai/variations/review-portal.html

Then tell the user:

"The review portal is ready at .saccoai/variations/review-portal.html. Send this file to your client — they can open it in any browser without needing an internet connection. When they've made their choice, they'll download a feedback.json file. Bring that file back here and I'll process the feedback."

If the user wants a shareable link instead of a file attachment, suggest: "You can also upload review-portal.html to any static host (e.g., Vercel, Netlify Drop, GitHub Pages) to get a URL."

Deployed Mode

After deployment completes, collect the deployment URL from vercel deploy output. Then tell the user:

"The review portal is live at: {deployment-url}

Send this link to your client. The password is set in PORTAL_PASSWORD — share it with your reviewers.

When the client has made their choice, come back and I'll fetch the feedback from the database and process it."

Also print the portal password if it was auto-generated, so the user can share it.

Phase 4: Collect Feedback

This phase is user-triggered. It runs after the client has submitted their review. The user initiates it by saying something like "the client submitted their feedback" or "process the feedback.json".

Static Mode

Ask the user for the path to the feedback.json file the client downloaded:

"Please provide the path to the feedback.json file the client downloaded (e.g., ~/Downloads/feedback.json)."

Read the file. Parse:

  • chosen_variation: the variation the client selected
  • feedback: any per-variation notes the client left

Output a summary:

"The client chose: {variation label} ({visual anchor}).

Their notes:

  • Variation 1 ({label}): {notes or 'No notes'}
  • Variation 2 ({label}): {notes or 'No notes'} ...

Ready to finalize? I'll run saccoai-design-variations Phase 6 cleanup to merge this variation into main and remove the others."

If the user confirms, invoke saccoai-design-variations Phase 6 with the chosen variation.

Deployed Mode

Fetch the stored feedback from Upstash Redis:

  1. Read the REDIS_URL from the portal project's .env.local (or ask the user)
  2. Query portal:chosen to get the chosen variation
  3. Query feedback:* to get all reviewer feedback
  4. Parse and present the same summary as static mode

Then offer to run saccoai-design-variations Phase 6 cleanup.

Passing to Phase 6

When invoking saccoai-design-variations Phase 6, pass:

  • The chosen variation number and label
  • The client's feedback notes (stored to .saccoai/variations/client-feedback.json for the record)

saccoai-design-variations Phase 6 handles the git merge, branch cleanup, and design brief promotion.

Composition

saccoai-design-variations (Phase 5) ──→ saccoai-client-portal ──→ saccoai-design-variations (Phase 6 cleanup)

This skill sits between variation presentation and cleanup. It replaces the manual "share these Vercel URLs and wait for an email" workflow with a structured review experience.

  • Upstream: saccoai-design-variations. This skill reads .saccoai/variations/ output. It should be run immediately after saccoai-design-variations Phase 5 completes.
  • Downstream: saccoai-design-variations Phase 6. Once client feedback is collected (Phase 4 of this skill), it triggers Phase 6 cleanup to merge the chosen variation and remove the others.

Also composes with the broader rebuild pipeline:

saccoai-website-rebuild
  └──→ saccoai-design-variations  (Phases 1-5: generate + deploy N branches)
           └──→ saccoai-client-portal  (Phases 1-4: portal + client review)
                    └──→ saccoai-design-variations  (Phase 6: merge chosen, cleanup)
                             └──→ production deploy

Standalone Usage

Invoke this skill directly when:

  • saccoai-design-variations has already run and you want to present the variations to the client
  • A client needs a more polished review experience than raw Vercel preview URLs
  • Multiple stakeholders need to review variations simultaneously (use --mode deployed)
  • The user says "create a review portal", "send variations to the client", or "let the client choose"

When invoked standalone, ask for: the variations path (default .saccoai/variations/), the mode (default static), the client name, and any branding overrides. Then run all four phases.

Edge Cases

  • No preview URLs: If preview URLs are missing from comparison.md (e.g., Vercel integration was skipped in saccoai-design-variations), take fresh screenshots using agent-browser. If agent-browser is unavailable, the portal cards will show a styled placeholder — note this to the user and advise running saccoai-design-variations Phase 4 first.
  • No screenshots and no preview URLs: Generate the portal without images. Cards show the variation label and design brief details only. Note the gap in the Phase 3 "Present" message.
  • Single variation only: The portal still works with one variation. The comparison toggle is hidden since there's nothing to compare.
  • Deployed mode — Vercel not linked: Abort with instructions: "Run vercel link in the portal directory, then re-run Phase 2 deployed mode."
  • Deployed mode — Upstash Redis not provisioned: Prompt the user to run vercel marketplace add upstash-redis and provide the REDIS_URL, then retry.
  • feedback.json already exists in .saccoai/variations/: A previous review was already completed. Ask the user: "A feedback.json already exists — was this portal already reviewed? Do you want to re-run the portal or process the existing feedback?"
  • Client opens portal offline (static mode): The portal is fully self-contained. The only feature that requires internet is the "Preview live" button (which opens Vercel preview URLs). All other features work offline.

Output

.saccoai/variations/
├── review-portal.html          # Static mode output
└── client-feedback.json        # Saved after Phase 4 completes (both modes)

# Deployed mode also produces:
{client-slug}-review/           # Next.js app scaffold (in cwd or parent directory)
Related skills

More from saccoai/agent-skills

Installs
1
First Seen
Mar 27, 2026