Apply all design collaboration skills in a complete end-to-end project — from design brief through Figma handoff, developer implementation, QA, documentation, and impact measurement for a real feature.
This capstone project applies every collaboration skill from this module to a realistic scenario: designing, handing off, implementing, quality-assuring, and measuring the impact of a Course Recommendation feature for DevBootstrap.
You will work through the complete pipeline from design brief to impact measurement — experiencing every handoff point, quality gate, and communication challenge that occurs in real design-development collaboration.
This project is designed to be completed over 3-4 hours or spread across multiple sessions. It produces a complete collaboration artifact set that demonstrates all skills from the module.
Before any design work begins, establish the brief and success metrics.
Design Brief: Course Recommendation Feature
1## Design Brief: Course Recommendations
2
3### Problem Statement
4Users who complete a course do not know what to learn next.
560% of users who finish a course do not return within 30 days.
6Goal: Reduce 30-day post-completion churn from 60% to 45%.
7
8### User
9Learner who just completed a course on DevBootstrap.
10They are motivated (just finished something), but uncertain about next steps.
11They may be a beginner who needs a clear path, or an advanced learner
12who wants to build specific skills.
13
14### Success Metrics
15Primary: 30-day retention after course completion (60% → 45% target)
16Secondary:
17 - Recommendation click-through rate > 15%
18 - Enrollment from recommendations > 5%
19Measurement window: 6 weeks post-launch
20
21### Constraints
22Technical:
23 - Recommendations from existing GET /recommendations?userId=X API
24 - No new API work available this sprint
25 - Must work without JavaScript (SSR requirement)
26 - Mobile-first: 375px primary target
27
28Design:
29 - Use existing course card component (no redesign)
30 - Add to course completion page (existing page)
31 - Single new design element: recommendation section with CTA
32
33Timeline: Sprint 4, 2-week implementation
34
35### Out of Scope
36- AI/ML recommendation algorithm (uses existing rule-based API)
37- A/B testing the algorithm (future sprint)
38- Recommendation on homepage or course list (later scope)Design scope (2 days design):
Developer scope (3 days implementation):
Complete handoff package for the Course Recommendation feature.
Figma named version:
'Sprint 4 / Course Recommendations — Final v1.0'
Handoff announcement:
1[Slack: #design-dev-sprint4]
2@developer-name — Sprint 4 Course Recommendations ready!
3
4Figma: figma.com/file/xxx (Sprint 4 / Course Recommendations — Final v1.0)
5Loom: loom.com/share/xxx (7 min: full walkthrough)
6
7New tokens (add to tokens.css):
8 --color-recommendation-bg: var(--prim-blue-50); /* #EFF6FF */
9 --color-recommendation-border: var(--prim-blue-200); /* #BFDBFE */
10
11Key specs from Loom:
12 Section header: 24px/600/#111827 + subtitle 15px/400/#6B7280
13 Horizontal scroll: gap 16px, scroll-snap-type x mandatory
14 Card: existing CourseCard component (no changes)
15 'Not for me' button: 13px/500/#6B7280, X icon 16px
16
17Dismiss behavior:
18 - POST /recommendations/:id/dismiss
19 - Card animates out: opacity 0 + scale 0.95, 200ms ease
20 - If only card left after dismiss: show empty state
21
22Please review Loom and post Figma questions by Thursday morning.
23I will answer during my Thursday session.Component spec (key sections):
1## RecommendationSection Component Spec
2
3### States
4| State | Trigger | Visual
5|---------|----------------------|-------
6| Loading | API call in progress | 3 skeleton cards
7| Filled | API returns ≥1 rec. | Card grid + dismiss buttons
8| Empty | API returns [] | Empty state illustration + CTA
9| Error | API error | Error message + retry button
10
11### Dismiss Behavior
121. User clicks 'Not for me' on card
132. Optimistic: card begins animation (opacity 0, scale 0.95, 200ms ease)
143. API: POST /recommendations/:id/dismiss
154. On API success: card removed from DOM, remaining cards shift left
165. On API error: card returns to full opacity (rollback), show toast error
176. If 0 cards remaining: transition to empty state
18
19### Accessibility
20- 'Not for me' button: aria-label='Dismiss [course title] recommendation'
21- Horizontal scroll: keyboard accessible with Tab navigation
22- Cards: role='listitem' inside role='list'
23- Empty state: aria-live='polite' for screen reader announcement
24- Skeleton: aria-busy='true' on container, aria-label='Loading recommendations'Figma annotations on key elements:
Implementation specifications extracted from Figma specs.
New CSS tokens:
1/* Add to tokens.css */
2--color-rec-bg: var(--prim-blue-50, #eff6ff);
3--color-rec-border: var(--prim-blue-200, #bfdbfe);Recommendation section CSS:
1.rec-section {
2 background-color: var(--color-rec-bg);
3 border-top: 1px solid var(--color-rec-border);
4 border-bottom: 1px solid var(--color-rec-border);
5 padding: 2rem 0; /* 32px top/bottom, no horizontal (handled by inner) */
6}
7
8.rec-header {
9 padding: 0 1.5rem; /* 24px horizontal matching card grid padding */
10 margin-bottom: 1rem;
11}
12
13.rec-title {
14 font-size: 1.5rem; /* 24px */
15 font-weight: 600;
16 color: var(--color-text-primary, #111827);
17 margin: 0 0 0.25rem;
18}
19
20.rec-subtitle {
21 font-size: 0.9375rem; /* 15px */
22 font-weight: 400;
23 color: var(--color-text-muted, #6b7280);
24 margin: 0;
25}
26
27/* Horizontal scroll container */
28.rec-scroll {
29 display: flex;
30 flex-direction: row;
31 gap: 1rem; /* 16px */
32 padding: 0 1.5rem; /* 24px horizontal padding matches header */
33 overflow-x: auto;
34 scroll-snap-type: x mandatory;
35 -webkit-overflow-scrolling: touch;
36 scroll-padding-left: 1.5rem;
37 /* Hide scrollbar on desktop, keep functionality */
38 scrollbar-width: thin;
39 scrollbar-color: var(--color-border, #e5e7eb) transparent;
40}
41
42/* Each card wrapper: snap target + relative for dismiss button */
43.rec-card-wrap {
44 flex-shrink: 0;
45 width: 17.5rem; /* 280px matches course card width */
46 scroll-snap-align: start;
47 position: relative;
48
49 /* Dismiss animation */
50 transition: opacity 200ms ease, transform 200ms ease;
51}
52
53.rec-card-wrap[data-dismissed='true'] {
54 opacity: 0;
55 transform: scale(0.95);
56 pointer-events: none;
57}
58
59/* 'Not for me' dismiss button */
60.rec-dismiss {
61 position: absolute;
62 top: 0.5rem; /* 8px */
63 right: 0.5rem;
64 display: flex;
65 align-items: center;
66 gap: 0.25rem;
67 padding: 0.25rem 0.5rem;
68 background-color: rgb(255 255 255 / 0.9);
69 border: 1px solid var(--color-border, #e5e7eb);
70 border-radius: 0.375rem;
71 font-size: 0.8125rem; /* 13px */
72 font-weight: 500;
73 color: var(--color-text-muted, #6b7280);
74 cursor: pointer;
75 transition: background-color 150ms ease, color 150ms ease;
76}
77
78.rec-dismiss:hover {
79 background-color: #ffffff;
80 color: var(--color-text-primary, #111827);
81}
82
83.rec-dismiss:focus-visible {
84 outline: 2px solid var(--color-border-focus, #2563eb);
85 outline-offset: 2px;
86}
87
88/* Loading skeleton */
89.rec-skeleton {
90 width: 17.5rem;
91 height: 21rem; /* matches course card height */
92 border-radius: 0.75rem;
93 background-color: var(--color-border, #e5e7eb);
94 background-image: linear-gradient(
95 90deg,
96 transparent 0%,
97 rgb(255 255 255 / 0.6) 50%,
98 transparent 100%
99 );
100 background-size: 200% 100%;
101 animation: skeleton-sweep 1.5s ease-in-out infinite;
102}
103
104@keyframes skeleton-sweep {
105 from { background-position: 200% 0; }
106 to { background-position: -200% 0; }
107}
108
109/* Empty state */
110.rec-empty {
111 padding: 2rem 1.5rem;
112 text-align: center;
113}
114
115.rec-empty__icon {
116 width: 3rem;
117 height: 3rem;
118 color: var(--color-text-muted, #6b7280);
119 margin: 0 auto 1rem;
120}
121
122.rec-empty__title {
123 font-size: 1rem;
124 font-weight: 600;
125 color: var(--color-text-primary, #111827);
126 margin: 0 0 0.5rem;
127}
128
129.rec-empty__message {
130 font-size: 0.875rem;
131 color: var(--color-text-muted, #6b7280);
132 margin: 0 0 1.5rem;
133}Design QA and documentation complete the collaboration project.
Design QA checklist results:
1COURSE RECOMMENDATION SECTION — QA REPORT
2Date: Sprint 4 Week 2
3Reviewer: @designer
4
5LAYOUT
6✓ Section background: #EFF6FF (matches Figma)
7✓ Border colors: #BFDBFE top and bottom
8✓ Horizontal scroll works, cards snap correctly
9✓ 3 skeleton cards during loading
10
11TYPOGRAPHY
12✓ Title: 1.5rem/600/#111827
13✓ Subtitle: 0.9375rem/400/#6B7280
14✗ FINDING #1 (High): 'Not for me' button font-size
15 Spec: 13px = 0.8125rem
16 Actual: 14px = 0.875rem (DevTools Computed)
17 Fix: .rec-dismiss { font-size: 0.8125rem; }
18
19INTERACTIVE STATES
20✓ Dismiss animation: correct (opacity 0 + scale, 200ms)
21✓ Card keyboard accessible (Tab navigation through scroll)
22✓ Focus ring on dismiss button: correct 2px blue
23✗ FINDING #2 (Critical): Missing aria-label on dismiss button
24 Expected: aria-label='Dismiss [course title] recommendation'
25 Actual: no aria-label (button shows only icon to AT)
26 Fix: add aria-label to each dismiss button in React
27✓ Empty state shows correctly when 0 cards
28✓ Error state shows toast correctly
29
30RESPONSIVE
31✓ 375px: single card visible, scroll for more
32✓ 768px: 2.5 cards visible (indicates more)
33✓ 1440px: 3.5 cards visible
34
35QA RESULT: FAIL (1 Critical, 1 High)
36Developer action: fix #2 (Critical) same day, #1 (High) before mergeComponent Documentation (Storybook MDX excerpt):
1# Recommendation Section
2
3Displays personalized course recommendations after course completion.
4Powered by the recommendations API.
5
6## When to Use
7
8- Course completion page only (not dashboard or homepage)
9- Requires user authentication
10- Gracefully degrades to empty state if API returns no recommendations
11
12## States
13
14- Loading: 3 skeleton cards during API fetch
15- Filled: scrollable card grid with dismiss per card
16- Empty: message + 'Browse all courses' CTA
17- Error: error message + retry button
18
19## Accessibility
20
21- Dismiss buttons include `aria-label` with course title
22- Section uses `aria-live='polite'` for dynamic content
23- Skeleton: `aria-busy='true'` on container
24- Keyboard: Tab navigates through dismiss buttons in reading orderImpact measurement setup:
1Pre-launch baseline (measured week before launch):
2 30-day post-completion return rate: 40% (measured from last 90 days)
3 Note: actual churn is 60% — 40% DO return within 30 days
4 Target: improve to 55%+ return rate
5
6Analytics events to track:
7 - recommendations_section_viewed (impression)
8 - recommendation_card_clicked (engagement)
9 - recommendation_dismissed (negative signal)
10 - enrollment_from_recommendation (conversion)
11
12Measurement window: 6 weeks post-launch
13Expected evaluation date: [Sprint 4 + 6 weeks]All collaboration artifacts for the Course Recommendation feature — from brief to impact report — demonstrating the complete design collaboration pipeline.
1/* COMPLETE ARTIFACT SET: Course Recommendation Feature
2 Sprint 4 | DevBootstrap
3
4=== 1. DESIGN BRIEF (pre-design) ===
5
6Problem: 60% post-completion churn
7User: Learner who just finished a course
8Target: 30-day return rate: 40% → 55%
9Constraints: Existing recommendation API, existing card component
10Timeline: Sprint 4
11
12=== 2. FIGMA ARTIFACTS ===
13
14Branch: feat/sprint-4/recommendations
15Named version: 'Sprint 4 / Course Recommendations — Final v1.0'
16Artboards: Desktop + Mobile + All States (loading, filled, empty, error)
17Annotations: scroll behavior, animation timings, dismiss ARIA
18
19=== 3. HANDOFF PACKAGE ===
20
21Slack message: posted Monday Sprint 4 Day 1
22Loom walkthrough: 7 min, covers all states and interactions
23New tokens documented: --color-rec-bg, --color-rec-border
24Component spec doc: behavior, ARIA, dismiss API
25Open questions: 0 at time of handoff
26
27=== 4. IMPLEMENTATION ARTIFACTS ===
28
29New files:
30 src/components/course/RecommendationSection.tsx
31 src/components/course/RecommendationCard.tsx
32 src/components/course/RecommendationSkeleton.tsx
33 src/styles/recommendations.css
34
35New tokens added to tokens.css:
36 --color-rec-bg: var(--prim-blue-50, #eff6ff)
37 --color-rec-border: var(--prim-blue-200, #bfdbfe)
38
39Storybook stories:
40 RecommendationSection/Loading
41 RecommendationSection/Filled (3 cards)
42 RecommendationSection/Empty
43 RecommendationSection/Error
44 RecommendationSection/AfterDismiss (2 cards remaining)
45 RecommendationSection/AllStates (overview)
46
47Chromatic: 6 new stories, all approved on first run
48
49Self-QA results:
50 All states tested: ✓
51 Keyboard navigation: ✓
52 Focus management: ✓
53 Mobile (375px): ✓
54 Found: dismiss button missing aria-label (fixed before QA session)
55
56=== 5. DESIGN QA RESULTS ===
57
58Designer QA date: Sprint 4 Day 12
59Findings:
60 Critical (1): Missing aria-label on dismiss — FIXED
61 High (1): Wrong dismiss button font-size — FIXED
62 Low (0): None
63
64QA sign-off: Sprint 4 Day 12 (same day as QA session)
65
66=== 6. DOCUMENTATION ===
67
68Storybook MDX: Complete (states, usage, accessibility, tokens)
69Figma annotations: motion specs, ARIA, responsive behavior
70Notion component page: created, linked from Storybook
71Changelog: v3.4.0 entry added
72
73=== 7. DEPLOYMENT ===
74
75Deployed: Sprint 4 Day 14 (last day of sprint)
76Feature flag: recommendation_section_v1 (rolled out to 100%)
77Monitoring: Mixpanel funnel set up
78
79=== 8. IMPACT MEASUREMENT (6 weeks post-launch) ===
80
8130-day post-completion return rate:
82 Before: 40% (90-day baseline)
83 After: 48% (+8 percentage points)
84 Status: Partial success (target was 55%, achieved 48%)
85
86Recommendation metrics:
87 Impression to click: 18% (target was >15%) ✓
88 Click to enrollment: 6.2% (target was >5%) ✓
89 Average dismissals per session: 1.2 (healthy — some dismissals expected)
90
91Business impact:
92 Additional monthly returning users: ~320
93 Additional enrollments from recommendations: ~64/month
94 Revenue from recommendation-driven enrollments: ~$3,136/month
95 Annual revenue impact: ~$37,600
96
97 Investment: 40 design + dev hours × $150 = $6,000
98 Annual ROI: $37,600 / $6,000 = 6.3:1
99
100Learnings for v2:
101 - Algorithm quality is the limiting factor (not UX)
102 - Users dismiss recommendations that do not match their track
103 - v2 hypothesis: personalized tracks will lift CTR from 18% to 30%+
104 - v2 scope: add 'Based on your CSS Mastery completion' subtitle
105 to contextualize recommendations (design only: 4 hours)
106
107Sprint 5 plan: A/B test contextualized vs uncontextualized recommendations
108*/The complete artifact set demonstrates the full collaboration pipeline: brief → design → handoff → implementation → QA → documentation → deployment → impact measurement. The impact measurement section shows honest results: the 40% → 48% return rate improvement is real progress but did not reach the 55% target. This honest reporting with learnings ('algorithm quality is the limiting factor') and a v2 hypothesis shows a mature, data-informed design practice. The v2 suggestion (4 hours of design work to add context subtitles) is minimal cost with high expected impact — a well-calibrated next step based on real data.
Congratulations on completing the Design Collaboration module. You now have the complete toolkit for professional design-development collaboration: Figma Dev Mode, design token implementation, version control, QA processes, documentation, cross-functional communication, and impact measurement. Apply these skills to your next project.
Your progress is saved in this browser, on this device only.