Mobile: static video poster in gallery + design handoff brief
CI / policy (push) Has been cancelled
CI / backend (push) Has been cancelled
CI / profile (push) Has been cancelled
CI / mobile (push) Has been cancelled

- CardThumb: show a single static poster frame for video cards (extracted ~500ms
  in, cached) instead of cycling 3-4 frames, which read as flicker. Keep the ▶
  badge so video cards stay distinguishable.
- docs/DESIGN_BRIEF.md: full design handoff brief for the AI designer — product
  framing, visual language, screen-by-screen specs, flows, motion, and §11
  "Post-scan experiences" (a dozen scan-triggered experience concepts to mock).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-05 14:34:34 -05:00
co-authored by Claude Opus 4.8
parent b0b080981e
commit a66978910d
2 changed files with 295 additions and 28 deletions
+19 -28
View File
@@ -1,6 +1,6 @@
// Gallery thumbnail. Photo cards show their image; video cards extract a few // Gallery thumbnail. Photo cards show their image; video cards show a single
// frames and cycle them like a flipbook so they animate and stand out. Frames // static poster frame (no animation — it flickered) plus a ▶ badge so they're
// are cached per video path so re-visiting the gallery is instant. // still easy to tell apart. Posters are cached per video path.
import { MaterialCommunityIcons } from "@expo/vector-icons"; import { MaterialCommunityIcons } from "@expo/vector-icons";
import * as VideoThumbnails from "expo-video-thumbnails"; import * as VideoThumbnails from "expo-video-thumbnails";
@@ -8,45 +8,36 @@ import { useEffect, useState } from "react";
import { Image, StyleProp, StyleSheet, View, ViewStyle } from "react-native"; import { Image, StyleProp, StyleSheet, View, ViewStyle } from "react-native";
import { LocalCard } from "../stores/localCardsStore"; import { LocalCard } from "../stores/localCardsStore";
// Spread across the clip (not consecutive frames) so the flipbook shows motion. // A bit into the clip — the very first frame is often black.
const FRAME_TIMES = [0, 1200, 2400, 3600]; const POSTER_TIME = 500;
const FRAME_CACHE = new Map<string, string[]>(); const POSTER_CACHE = new Map<string, string>();
export function CardThumb({ item, style }: { item: LocalCard; style: StyleProp<ViewStyle> }) { export function CardThumb({ item, style }: { item: LocalCard; style: StyleProp<ViewStyle> }) {
const video = item.videoPath; const video = item.videoPath;
const [frames, setFrames] = useState<string[]>(() => (video && FRAME_CACHE.get(video)) || []); const [poster, setPoster] = useState<string | null>(() => (video && POSTER_CACHE.get(video)) || null);
const [idx, setIdx] = useState(0);
// Extract preview frames once per video.
useEffect(() => { useEffect(() => {
let cancelled = false; let cancelled = false;
if (!video || FRAME_CACHE.has(video)) return; if (!video || POSTER_CACHE.has(video)) return;
(async () => { (async () => {
const out: string[] = []; try {
for (const time of FRAME_TIMES) { const { uri } = await VideoThumbnails.getThumbnailAsync(video, {
try { time: POSTER_TIME,
const { uri } = await VideoThumbnails.getThumbnailAsync(video, { time, quality: 0.6 }); quality: 0.7,
out.push(uri); });
} catch { POSTER_CACHE.set(video, uri);
/* a frame failed to extract — skip it */ if (!cancelled) setPoster(uri);
} } catch {
/* couldn't extract — fall back to the placeholder */
} }
if (out.length) FRAME_CACHE.set(video, out);
if (!cancelled && out.length) setFrames(out);
})(); })();
return () => { return () => {
cancelled = true; cancelled = true;
}; };
}, [video]); }, [video]);
// Advance the flipbook. const fallback = item.imagePath || null;
useEffect(() => { const src = video ? poster || fallback : fallback;
if (frames.length < 2) return;
const h = setInterval(() => setIdx((i) => (i + 1) % frames.length), 450);
return () => clearInterval(h);
}, [frames.length]);
const src = video && frames.length ? frames[idx] : item.imagePath || null;
return ( return (
<View style={style}> <View style={style}>
+276
View File
@@ -0,0 +1,276 @@
# CardClaws — Design Handoff Brief
**Internal — Confidential (RedClaw Systems LLC).** Not for distribution outside RedClaw.
This brief describes what CardClaws is, every screen, the endtoend flows, the current
visual language, and where we explicitly want the designer to explore alternatives. The goal:
hand this to our AI designer to produce mockups we can compare and iterate on.
---
## 1. Product in one line
**CardClaws is a mobilefirst digital business card.** You build a beautiful, living card
(photo, AIgenerated scene, or AIgenerated video), flip it to reveal a QR code, and anyone who
scans it lands on your public profile with all your links and a onetap "Save Contact." It
replaces paper cards with something animated, shareable, and updatable.
**Tone:** premium, modern, a little futuristic. Think Apple Wallet × Linktree × a luxury
business card. Tactile, dark, highcontrast, motionforward.
---
## 2. Who it's for
- **Founders, creators, developers, consultants** who network and want to stand out.
- **Teams** (Pro/Enterprise) who want consistent, branded cards across employees.
- Primary device: **phone, portrait**. The card is meant to be shown screentoface or scanned.
---
## 3. The core object: "the card"
A card has **two sides** the user flips between with a 3D rotation:
- **Front** = the hero. A fullbleed **photo, AI image, or looping AI video**, with the person's
**name + title** overlaid. This is what you show someone.
- **Back** = the **utility**. A single **QR code** ("Scan to view everything") plus a tidy list
of labeled links (website, GitHub, publications, social, etc.).
The card is **fullscreen / fullbleed** when presented — it fills the entire device so it reads
as an object, not a UI panel. Flipping is a signature interaction (see §9).
---
## 4. Current visual language (starting point — open to reinvention)
We built a working dark theme. Treat this as **v0 to react to**, not a constraint. We want to
see this look refined *and* 23 distinct alternative directions.
| Token | Value | Use |
|---|---|---|
| Background | `#0a0a0c` / `#0e0e12` | App canvas, card back |
| Surface | `#15151a`, `#16161c` | Inputs, tiles, cards |
| Surface raised | `#222228`, `#26262e` | Buttons, chips, icon wells |
| **Accent / CTA** | **`#ff3b30`** (red) | Primary buttons, active chips, selected state |
| Destructive | `#ff453a` | Delete/remove |
| Text primary | `#f5f5f7` | Headings, values |
| Text secondary | `#9a9aa0` | Labels, captions |
| Text tertiary | `#6b6b70` | Placeholders, hints |
| Radius | 1220 px (tiles/inputs), **0 px** (fullbleed card) | — |
| Type | System (SF/Roboto), weights 600800 for emphasis | — |
**Motion is part of the brand.** Flip animation, ambient idle drift, entry fades, animated
gallery tiles. Designs should account for movement, not just static frames.
**Exploration we want:** alternate accent palettes (e.g., electric violet, neon cyan, warm gold),
lightmode option, glassmorphism vs. flat vs. neumorphic card surfaces, and 23 cardback layouts.
---
## 5. Screenbyscreen
> Screens marked **[built]** exist in the working app; **[roadmap]** are in the product vision
> (PRD) and should be mocked for the full experience.
### 5.1 Gallery — "Your cards" **[built]** (home screen)
The landing screen: a grid of the user's cards.
- Header: title "Your cards" + a "Sign in" affordance (topright).
- **Responsive grid that shrinks as it grows:** 2 columns for a few cards, 3 for more, 4 for many
— tiles get smaller so more fit per screen.
- **Tiles:** portrait (2:3) card thumbnails. Photo cards show the still; **video cards animate**
(a short looping flipbook of frames) and carry a small ▶ badge so they're distinguishable.
- Tile label: name + title (hidden on the smallest tiles).
- Floating **"+ New card"** button (bottom center).
- Empty state: "No cards yet — create your first."
- Tap a tile → opens that card (view/edit).
*Explore:* grid vs. carousel vs. stackedwallet metaphor; how a "live" video tile should feel
without being noisy.
### 5.2 Card editor — "Make your card" / "Edit card" **[built]**
Where a card is composed. Vertical form.
- **Live preview** at top (the chosen photo / AI image / looping video, 2:3).
- **Front media row 1:** `Take photo` · `Choose photo`.
- **Front media row 2 (AI):** `✨ AI scene` (magicwand icon) · `🎬 AI video` (movie icon).
- **Fields:** Name, Title, QR link (the profile URL).
- **"Back of card · scannable links":** a repeatable list editor — each entry has a **kind**
(Domain / GitHub / Paper / Link — sets its icon), a **label**, and a **URL**. Add / remove rows.
- Primary CTA: **Save card** (red). For existing cards, a **Delete card** link.
*Explore:* progressive disclosure (collapse AI + links until needed), a segmented "Front /
Back / Details" layout, inline validation, a clearer "this becomes your card front" framing.
### 5.3 AI scene generator **[built]** (single screen)
Reached from `AI scene`. Generates the cardfront **image** with Google's nanobanana model.
- "Describe your scene" — multiline text (e.g., *"a neonlit Tokyo street at night"*).
- "Style" chips: Cinematic · Minimal · Neon · Studio portrait · Nature · Abstract.
- "Mood" chips: Bold · Calm · Luxe · Playful · Dark.
- CTA: **Generate image** (shows a spinner; refines the brief with AI, then generates). On
success it returns to the editor with the image on the card front.
*Explore:* show example thumbnails per style; a "regenerate / variations" row; a before/after.
*(Note: a voicetotext mic for the description is planned but not yet shipped.)*
### 5.4 AI video generator **[built]** (single screen)
Reached from `AI video`. Generates a looping cardfront **video** with Google Veo.
- "Describe the motion" — multiline (e.g., *"slow drift across a city skyline as lights flicker on"*).
- "Motion style" chips: Parallax · Particles · Slow zoom · Liquid · Aurora · Glitch.
- "Length" chips: 3s · 5s · 8s.
- CTA: **Generate video.** This is **async (~1 minute)** — needs a clear, reassuring progress
state ("Generating with Veo — this takes about a minute…"). On success the looping clip lands
on the card front.
*Explore:* a richer waiting state (progress %, animated placeholder, "we'll notify you"), and how
to preview/scrub the result before accepting.
### 5.5 Card viewer (fullscreen) **[built]** — the signature moment
Tapping a saved card (or "Save") presents it **fullbleed**, status bar hidden.
- **Front:** the photo/AIimage/looping video fills the screen; **name + title stacked topright**.
A subtle hint: "Swipe or tap the card to flip →".
- **Flip:** swipe or tap → 3D `rotateY` flip (perspective, midflip face swap, haptic tick).
- **Back (the template):**
- Identity header (name + title).
- **One hero QR** on a white tile — caption "Scan to view everything" + the profile URL.
- A divider, then the **link list**: each row = kind icon + label + URL.
- Controls (Gallery · Edit) appear **only on the back**, so the front stays clean.
- Ambient idle: a gentle drift after a few seconds of no interaction (premium "alive" feel).
*Explore:* multiple **cardback templates/themes** (this is explicitly requested — give us 34:
e.g., "minimal", "grid of links", "socialfirst", "portfolio"), QR styling (rounded modules,
logo in center, color), and the flip's easing/feel.
### 5.6 Share sheet **[roadmap]**
How others receive the card without scanning in person:
- **QR** (the back), **share link** (`cardclaws.com/handle`), **NFC tag** write (tap a physical
sticker/card), **Add to Apple Wallet / Google Wallet** (the card as a wallet pass).
### 5.7 Auth **[roadmap, exists in backend]**
Sign up / sign in: **email + password, magic link, Sign in with Apple.** Minimal, trustbuilding.
### 5.8 Public web profile **[roadmap]** — `cardclaws.com/[handle]`
The page a scanner lands on (responsive web, not the app):
- Hero recreation of the card (with the flip), name/title/company.
- Sticky **contactactions bar**: Save Contact (.vcf), Call, Email, Map.
- The same links as the card back.
- Should feel like a continuation of the card, on the web.
### 5.9 Analytics **[roadmap]**
A simple dashboard per card: profile visits, contact saves, scans over time, rough geo. Clean,
glanceable, not enterpriseheavy.
### 5.10 Teams / settings / billing **[roadmap]**
- Tiers: **Free** (1 card), **Pro** (multiple cards, AI, video, analytics), **Team/Enterprise**
(seats, roles, central branded templates, aggregate analytics).
- Paywall / upgrade screens; team roster; brand template management.
---
## 6. Primary endtoend flows (storyboard these)
1. **First card (photo):** Gallery (empty) → New card → take/choose photo → fill name/title →
add a couple links → Save → fullscreen card → flip to QR.
2. **AI image card:** New card → AI scene → describe + style + mood → Generate → image on front →
Save → present.
3. **AI video card:** New card → AI video → describe + motion + length → Generate (wait ~1 min) →
looping video front → Save → present.
4. **Show & share:** open a card → present front → flip → someone scans the QR → lands on the web
profile → taps Save Contact.
5. **Manage many:** Gallery fills up → tiles shrink to fit → video tiles animate to stand out →
tap to edit/delete.
---
## 7. Animation & interaction notes (brandcritical)
- **Flip:** 3D rotateY with perspective, configurable ~250600 ms, target <450 ms; haptic on flip.
- **Entry:** card fades/scales in on present.
- **Ambient:** slow idle drift after ~5 s of inactivity.
- **Gallery video tiles:** ~2 fps frame flipbook (subtle, not distracting).
- **Generate states:** image = seconds (spinner); video = ~1 min (needs a real, calm progress UX).
- Everything should feel **fast, tactile, and physical** — the card is a real object.
---
## 8. Component inventory (for a design system)
Buttons (primary/secondary/destructive), selectable **chips**, text inputs (single + multiline),
the **card tile** (photo + animated video variants + badge), the **fullbleed card** (front +
back faces), **QR tile**, **link row** (icon + label + URL), **link editor row** (kind chips +
inputs + remove), floating action button, section headers, empty states, progress/loading states,
nav header. Icon set currently from Material Community Icons (web, github, book, link, microphone,
movie, play, magicwand).
---
## 9. Hard constraints (don't break these)
- **Mobilefirst, portrait.** The card front is **fullbleed** (no chrome) when presented.
- **One QR per card** on the back (links are listed, not individually coded).
- Front carries **name + title**; back carries the **QR + links**.
- The flip is the hero interaction — design around it.
- Dark is the default we've built, but **propose a light mode** too.
## 10. What we want from the designer
1. A **refined version** of the current dark direction (polish what exists).
2. **23 alternative visual directions** (different palette/material/personality).
3. **34 cardback templates/themes** to choose from.
4. Mockups for every **[built]** screen + the key **[roadmap]** ones (web profile, share, auth).
5. The **5 flows** in §6 as clickthrough storyboards.
6. Treatments for **motion** (flip, ambient, generate/progress, animated gallery tiles).
Deliver as comparable options so we can A/B the looks quickly.
---
## 11. Postscan experiences (concepts to mock)
The moment someone **scans the QR** is the product's payoff. Today it just opens the web profile
(§5.8). We want to explore *designed experiences* triggered on scan — each is a **distinct
landingpage look**, so these double as design directions to compare. Mock **34** of these as
alternative postscan screens (mobileweb, portrait, fastloading). The default polished profile +
"Save Contact" is the baseline; these are modes on top of it.
> Architecturally these all ride one lever: the scan can carry an *experience + context* selector,
> so one card triggers many experiences. Designers don't need to worry about that — just treat each
> as its own landing screen.
**A · Remember the moment**
1. **"We Met"** — a twoway, time/placestamped meeting ("Met at SXSW · Austin · Jun 5"); both
people get added to each other's "People I met." Reciprocal shareback. *Design:* a warm
confirmation + connection card + a list.
2. **Auto followup** — schedule a nudge or send a "great meeting you" with your links. *Design:* a
tiny scheduling/confirmation moment.
3. **Memory note** — a oneline context ("the climber building fintech") attached to the connection.
**B · Adapt to the moment**
4. **One QR, many faces** — work / social / creator modes of the same person. *Design:* show how the
profile reskins per mode.
5. **Event companion** — eventthemed profile + event CTAs ("Catch my 3pm talk, Room B").
6. **Geo / localeaware** — localized language/links based on where the scanner is.
**C · Deliver the goods**
7. **"Book me"** — live availability → pick a slot → on both calendars. *Design:* an inline
booking widget.
8. **Payload drop** — the scan hands over the *thing* (deck, resume, menu, discount, playlist,
tip/pay link). *Design:* a focused "here's your file/offer" screen.
9. **Live "now" feed** — your latest post/video/status, always fresh. *Design:* a feed/now block.
**D · Delight & spread**
10. **AI welcome** — a personalized AI image/video greeting plays on the landing (powered by our
nanobanana + Veo). *Design:* a cinematic hero moment.
11. **AR / collectible** — AR card/avatar in the camera, and/or a collectible deck of people you've
met (rare/holographic variants). *Design:* AR overlay + a collection/“deck” view.
12. **Surprise & delight** — confetti, a custom line, an event microsite, or a tiny quiz that ends
in your contact. *Design:* a playful, reactive landing.
**Recommended to mock first:** #1 "We Met", #7 "Book me", #10 AI welcome — they cover relationship,
conversion, and our AI differentiator.