Ship Check Guidelines
Comprehensive quality standards for shipping category-defining features at Juniro.
Last Updated: January 27, 2026
Overview
The @ship-check agent uses these guidelines to evaluate whether code is ready to ship. This document serves as both:
- Reference for the AI agent - Consistent evaluation criteria
- Guide for developers - What to check before requesting review
Severity Definitions
🚫 Blocker (must be fixed before release)
A blocker is an issue that:
- Breaks or degrades a core user flow
- Violates brand foundations
- Creates significant future rework if shipped
- Introduces patterns that will spread incorrectly
- Blocks users from accomplishing their goal
Examples:
- Custom
<button>when<Button>component exists - Hardcoded
#3B82F6instead oftext-primary - Missing loading state on data fetch
- Keyboard navigation completely broken
- No value visible before signup
⚠️ Warning (acceptable short-term, but risky)
A warning is an issue that:
- Is contained and won't spread
- Has limited user impact
- Represents conscious, documented tech debt
- Can be addressed in a follow-up
Examples:
- Minor color inconsistency in one component
- Performance issue on non-critical path
- Missing ARIA label on decorative element
- Mobile UX slightly awkward but functional
✨ Polish (non-blocking improvements)
Polish items are:
- Visual refinements
- Nice-to-have UX improvements
- Code cleanup
- Enhancements that don't affect users materially
Examples:
- Smoother animation
- Better empty state illustration
- More descriptive error message
- Code comment improvements
Design System Compliance
Components
Always use design system components from:
@/components/design-system/(in web repos)@/components/ui/shared-core/(in juniro-design)
| Instead of | Use |
|---|---|
<button> | <Button> |
<input> | <Input> |
<select> | <Select> |
| Custom dropdown | <Menu> |
| Custom modal | <Modal> |
| Custom tabs | <Tabs> |
| Custom toggle | <Switch> or <Toggle> |
How to Check
# Find violations
grep -r "<button\|<input\|<select" src/ --include="*.tsx" | grep -v "design-system"
Brand Foundations
Colors
Never hardcode colors. Use Tailwind classes that reference design tokens.
| ❌ Don't | ✅ Do |
|---|---|
#3B82F6 | text-primary |
#EF4444 | text-error |
#10B981 | text-success |
rgb(59, 130, 246) | bg-primary |
style={{ color: '#333' }} | text-foreground |
How to Check
# Find hardcoded colors
grep -rE "#[0-9a-fA-F]{3,6}|rgb\(|rgba\(" src/ --include="*.tsx"
Typography
Use Tailwind typography classes:
text-xs,text-sm,text-base,text-lg,text-xl,text-2xlfont-normal,font-medium,font-semibold,font-bold- Don't hardcode
font-familyorfontSizein pixels
Spacing
Use Tailwind spacing scale:
p-1throughp-12(padding)m-1throughm-12(margin)gap-1throughgap-12(flex/grid gap)- Don't hardcode pixel values
UX Quality Standards
Required States
Every data-fetching component MUST have:
| State | Required | Implementation |
|---|---|---|
| Loading | 🚫 Blocker if missing | Skeleton or spinner |
| Error | 🚫 Blocker if missing | Error message + retry |
| Empty | ⚠️ Warning if missing | Helpful message + CTA |
| Success | ✅ Default | Normal content |
Example Pattern
function ActivityList() {
const { data, isLoading, error } = useActivities();
if (isLoading) return <ActivityListSkeleton />;
if (error) return <ErrorState error={error} onRetry={refetch} />;
if (!data?.length) return <EmptyState message="No activities found" />;
return <ul>{data.map(item => <ActivityCard key={item.id} {...item} />)}</ul>;
}
Dark Mode
All components MUST support dark mode:
- Use
dark:Tailwind variants - Test in both modes before shipping
// ✅ Good
<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
// ❌ Bad
<div className="bg-white text-gray-900">
Mobile Responsiveness
- Design mobile-first
- Test at 375px viewport width
- Use responsive Tailwind prefixes:
sm:,md:,lg:,xl: - Touch targets minimum 44x44px
Accessibility (WCAG 2.1 AA)
Keyboard Navigation
| Requirement | Standard |
|---|---|
| All interactive elements focusable | Tab to navigate |
| Logical focus order | Left-to-right, top-to-bottom |
| Focus indicator visible | 2px outline minimum |
| Escape closes modals/dropdowns | Standard behavior |
| Enter/Space activates buttons | Standard behavior |
ARIA Labels
// ✅ Good
<button aria-label="Close modal">
<XIcon />
</button>
// ❌ Bad (icon button with no label)
<button>
<XIcon />
</button>
Color Contrast
| Element | Minimum Ratio |
|---|---|
| Normal text | 4.5:1 |
| Large text (18px+ or 14px+ bold) | 3:1 |
| UI components | 3:1 |
Semantic HTML
// ✅ Good
<nav aria-label="Main navigation">
<ul>
<li><a href="/home">Home</a></li>
</ul>
</nav>
// ❌ Bad
<div className="nav">
<div className="nav-item" onClick={...}>Home</div>
</div>
Industry Best Practices
Marketplace Patterns (Airbnb, Booking.com)
| Pattern | Why | Implementation |
|---|---|---|
| Trust signals | Reduces booking anxiety | Reviews, verification badges, ratings |
| Social proof | Encourages action | "X parents booked this week" |
| Urgency/scarcity | Drives conversion | "Only 3 spots left" |
| Clear pricing | Builds trust | No hidden fees, total upfront |
| Safety info | Critical for kids activities | Age requirements, supervision, certifications |
PLG Patterns (Slack, Notion, Figma)
| Pattern | Why | Implementation |
|---|---|---|
| Value before signup | Reduces friction | Browse/search without account |
| Progressive disclosure | Prevents overwhelm | Show basics first, details on demand |
| Aha moment optimization | Drives retention | Clear path to first successful booking |
| Viral loops | Organic growth | Share activity, invite friends, referral rewards |
| Self-serve | Scalable | FAQs, help center, chatbot before human support |
Performance Standards
| Metric | Target | Blocker If |
|---|---|---|
| LCP (Largest Contentful Paint) | < 2.5s | > 4s |
| FID (First Input Delay) | < 100ms | > 300ms |
| CLS (Cumulative Layout Shift) | < 0.1 | > 0.25 |
| Time to Interactive | < 3s | > 5s |
Category-Defining Checklist
These are the patterns that differentiate great products:
Trust & Safety
- Provider verification status visible
- Review count and average rating prominent
- Cancellation policy clearly stated
- Support contact easily accessible
- Safety certifications displayed (CPR, background check)
- Age-appropriate content warnings
Discovery & Search
- Search works without login
- Filters are intuitive and instant
- Results show key decision factors (price, rating, distance, availability)
- Easy comparison between options
- Relevant recommendations based on context
Booking Flow
- Availability is accurate and real-time
- Booking completes in ≤ 3 steps
- Confirmation is immediate and clear
- Calendar integration offered (Google, Apple)
- Automatic reminders scheduled
- Easy modification/cancellation
Provider Experience
- Onboarding completes in < 10 minutes
- Dashboard shows actionable insights
- Common actions are one-click
- Analytics help providers improve
- Support is accessible when stuck
Growth Mechanics
- Share buttons on activities
- Referral program visible and easy
- Invite flow for parents to invite parents
- Provider referral for provider-to-provider
- Testimonials/success stories featured
Ship Check Process
Before Requesting Review
- Self-check against this document
- Run build -
bun run buildmust pass - Test mobile - Check at 375px viewport
- Test dark mode - Toggle and verify
- Keyboard test - Navigate with Tab, Enter, Escape
- Check states - Loading, error, empty all present
During Review
- Invoke
@ship-checkwith context about what you're shipping - Review findings by severity
- Fix all 🚫 Blockers
- Acknowledge ⚠️ Warnings (fix or document as tech debt)
- Consider ✨ Polish items for follow-up
After Shipping
- Monitor for errors (Sentry, Vercel logs)
- Check analytics for user behavior
- Create tickets for accepted warnings
- Celebrate shipping! 🎉
Quick Reference Card
Must Have (🚫 Blocker if missing)
- Design system components used
- Brand colors via tokens
- Loading state
- Error state
- Keyboard navigation
- Mobile responsive
- Dark mode support
Should Have (⚠️ Warning if missing)
- Empty state
- ARIA labels
- Performance optimized
- Trust signals (where applicable)
- Analytics tracking
Nice to Have (✨ Polish)
- Micro-interactions
- Advanced animations
- Additional social proof
- Copy refinements
This document is the source of truth for ship-check evaluations. Update when standards evolve.