skills/ui-page-standards/SKILL.md
New page checklist: metadata, loading/error states, component states, form completeness, mobile-first, SEO, API routes. Use when creating or auditing Next.js pages.
npx skillsauth add adilkalam/orca ui-page-standardsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use when creating a new page.tsx, route segment, or auditing existing pages.
page.tsx MUST export metadata (static) or generateMetadata (dynamic)| Field | Requirement |
|-------|------------|
| title | Unique, descriptive. Format: "Page Title | Site Name" or per project template |
| description | 150-160 characters, compelling, includes primary keyword |
| openGraph.title | Match or extend the page title |
| openGraph.description | Match or extend the page description |
| openGraph.images | At least one image, 1200x630px (standard) or 1200x1200px (square) |
| openGraph.type | 'website', 'article', or appropriate type |
| twitter.card | 'summary_large_image' |
| twitter.title | Match the page title |
| twitter.description | Match the page description |
| twitter.images | Match the link preview image |
Every page needs a preview image for social sharing (Slack, Twitter, iMessage, LinkedIn).
/app/opengraph-image.png or similar)opengraph-image.png (static) or opengraph-image.tsx (dynamic) in the route segmentmetadata export object[slug]): use generateMetadata({ params }) functionWhen creating a new page, the builder MUST also create or verify:
| File | Purpose | When to skip |
|------|---------|-------------|
| loading.tsx | Loading skeleton matching the page layout | Static pages with no data fetching |
| error.tsx | User-friendly error boundary with retry action | Never -- every page needs error handling |
| Navigation link | Page must be reachable from existing UI | Only if page is accessed via direct URL (e.g., callback pages) |
| Metadata | Title, description, openGraph, twitter, preview image | Never |
Rules:
loading.tsx skeleton MUST mirror the page's layout structure (not a generic spinner)error.tsx MUST show a user-friendly message with a "Try Again" button that calls reset()Every data-driven component MUST handle three states:
| State | What to show | Anti-pattern | |-------|-------------|-------------| | Loading | Skeleton matching final layout, OR spinner with context | Blank screen, no indicator | | Empty | Friendly message explaining no data + action (e.g., "No posts yet. Create your first post.") | Blank screen, empty table with just headers | | Error | User-friendly message + retry action. NEVER show raw error messages or stack traces to users. | White screen, console.error only, generic "Something went wrong" with no action |
Rules:
error.tsx. The builder must ensure one exists.Every form MUST have:
| Requirement | Implementation | Anti-pattern |
|------------|----------------|-------------|
| Client-side validation | Required fields marked, format validation (email, phone, URL), min/max length. Use Zod, react-hook-form, or HTML5 validation per project conventions. | No validation, console.log errors |
| Visible error messages | Error text shown next to the field that has the error. Use aria-describedby for accessibility. | Errors only in console, alert() boxes, errors at top with no field association |
| Submit loading state | Button shows loading indicator during submission. Button text preserved (not replaced with spinner only). | No feedback during submission |
| Double-submit prevention | Disable submit button while request is in-flight. | User clicks 3 times, 3 records created |
| Success feedback | Toast notification, inline success message, or redirect. User must KNOW it worked. | Form submits, nothing visible changes |
| Unsaved changes warning | For important forms (multi-step, long forms): warn before navigation. Not needed for simple search/filter forms. | User fills 10 fields, accidentally navigates away |
Rules:
useFormStatus() for pending state, useFormState() for error handlingEvery UI change must work on mobile:
| Rule | Specifics |
|------|-----------|
| Touch targets | Minimum 44x44px for interactive elements (buttons, links, inputs) |
| No horizontal overflow | Test at 320px width minimum. No content should require horizontal scrolling. |
| Readable text | Minimum 16px for body text on mobile. No text below 14px. |
| Navigation | Must be usable on mobile (hamburger menu, bottom nav, or collapsible sidebar) |
| Forms on mobile | Inputs must be full-width or near full-width. Use appropriate input types (type="email", type="tel") for mobile keyboards. |
| Images | Must scale properly. Use sizes prop for responsive images. |
| Spacing | Reduce section spacing on mobile (see typography-spacing skill mobile column). |
Rules:
When creating pages that represent entities (articles, products, FAQs, events, organizations):
| Page Type | JSON-LD Schema | When to add |
|-----------|---------------|-------------|
| Article/Blog post | Article or BlogPosting | Always for content pages |
| Product | Product with offers | Always for e-commerce |
| FAQ | FAQPage with questions | When page has Q&A format |
| Organization/About | Organization | Homepage or about page |
| Event | Event | Event listing pages |
| Breadcrumb | BreadcrumbList | Nested pages with breadcrumb UI |
Rules:
<script type="application/ld+json"> tagmetadata export or generateMetadata to include JSON-LDmetadata.alternates.canonicalWhen creating or modifying Next.js API routes (route.ts files):
| Requirement | Implementation |
|------------|----------------|
| Input validation | Validate request body/params with Zod or similar. Return 400 with specific error messages. |
| Consistent error format | All errors return: { error: string, details?: object }. Never return raw error objects or stack traces. |
| Proper HTTP status codes | 200 success, 201 created, 400 bad request, 401 unauthorized, 403 forbidden, 404 not found, 500 internal error. |
| Error handling | Wrap handler in try/catch. Log server errors (don't swallow). Return user-safe error messages. |
| Type safety | Request and response types defined. Use Zod .parse() or .safeParse() for runtime validation. |
Rules:
Check that these exist when working on a new Next.js project:
| File | Purpose | Required? |
|------|---------|-----------|
| app/sitemap.ts or app/sitemap.xml | Search engine discovery | Yes for public sites |
| app/robots.ts or public/robots.txt | Crawler instructions | Yes for public sites |
| app/favicon.ico or app/icon.tsx | Browser tab icon | Yes always |
| app/apple-icon.png | iOS home screen icon | Recommended |
| app/manifest.ts or public/manifest.json | PWA manifest | Only if PWA |
| app/opengraph-image.tsx or default preview image | Default link preview | Yes |
Rules:
When implementing or touching theme/color-related code:
| Issue | Prevention |
|-------|-----------|
| Flash of wrong theme (FOUC) | Use <script> in <head> to set theme class BEFORE React hydrates. Or use next-themes. |
| Images that need dark variants | Use <picture> with prefers-color-scheme media query, or CSS filter: invert() for simple icons |
| Hardcoded colors | All colors must come from design tokens / CSS custom properties that change with theme |
| Third-party embeds | Some embeds don't respect dark mode. Note as known limitation. |
Rules:
next-themes or a similar battle-tested solutioncontent-media
Download YouTube video transcripts when user provides a YouTube URL or asks to download/get/fetch a transcript from YouTube. Also use when user wants to transcribe or get captions/subtitles from a YouTube video.
development
Web UI quality rules: interactions, forms, loading, animations, layout, content, performance, accessibility, design. Apply to all web UI work. Adapted from Vercel Design Guidelines.
testing
MANDATORY protocol enforcing knowledge check before EVERY response - prevents explaining systems without reading docs, claiming without verification, and ignoring auto-loaded context
testing
Typography hierarchy and spacing scale fallbacks. Yields to project design-dna when present.