premium-experience
Premium app generation that creates WOW-factor experiences. Multi-page apps with smooth animations, zero TypeScript errors, and production-ready quality. Lovable-style experience: one prompt, complete app, instant delight. MUST be used alongside vibe-orchestrator for new projects.
$ Instalar
git clone https://github.com/wasintoh/toh-framework /tmp/toh-framework && cp -r /tmp/toh-framework/src/skills/premium-experience ~/.claude/skills/toh-framework// tip: Run this command in your terminal to install the skill
name: premium-experience version: 1.0.0 description: > Premium app generation that creates WOW-factor experiences. Multi-page apps with smooth animations, zero TypeScript errors, and production-ready quality. Lovable-style experience: one prompt, complete app, instant delight. MUST be used alongside vibe-orchestrator for new projects. triggers:
- /toh-vibe (new projects)
- /toh (complex app requests)
- Any "create app" request
Premium Experience Skill
"One prompt. Complete app. Instant WOW."
Transform any idea into a premium, production-ready application with multiple pages, smooth animations, and zero errors - all in a single prompt.
🎯 Core Philosophy
PREMIUM = COMPLETE + POLISHED + DELIGHTFUL
User says: "Create expense tracker"
❌ Basic output:
- 1 page
- No animations
- Basic styling
- "Add more pages later"
✅ Premium output:
- 5+ pages (Dashboard, Transactions, Reports, Settings, Auth)
- Smooth page transitions
- Micro-interactions everywhere
- Loading skeletons
- Empty states designed
- Ready to use immediately
📱 Multi-Page Generation (MANDATORY!)
Minimum Page Set by App Type
Every new project MUST generate these pages based on app type:
saas-app:
required_pages:
- "/" (Landing/Marketing page)
- "/dashboard" (Main dashboard)
- "/[feature]" (Core feature page)
- "/settings" (User settings)
- "/auth/login" (Authentication)
optional_pages:
- "/auth/register"
- "/auth/forgot-password"
- "/profile"
- "/pricing"
- "/help"
ecommerce:
required_pages:
- "/" (Homepage with hero + featured)
- "/products" (Product listing)
- "/products/[id]" (Product detail)
- "/cart" (Shopping cart)
- "/checkout" (Checkout flow)
optional_pages:
- "/auth/login"
- "/orders"
- "/wishlist"
- "/search"
ai-chatbot:
required_pages:
- "/" (Landing page)
- "/chat" (Main chat interface)
- "/chat/[id]" (Chat history)
- "/settings" (Preferences)
- "/auth/login"
optional_pages:
- "/prompts" (Saved prompts)
- "/history"
food-restaurant:
required_pages:
- "/" (Homepage with hero)
- "/menu" (Full menu)
- "/menu/[category]" (Category view)
- "/cart" (Order cart)
- "/checkout" (Order placement)
optional_pages:
- "/orders" (Order tracking)
- "/locations"
- "/about"
education:
required_pages:
- "/" (Landing page)
- "/courses" (Course listing)
- "/courses/[id]" (Course detail)
- "/learn/[id]" (Learning interface)
- "/dashboard" (Progress dashboard)
optional_pages:
- "/certificates"
- "/profile"
- "/leaderboard"
generic:
required_pages:
- "/" (Landing/Home)
- "/dashboard" (Main interface)
- "/[main-feature]" (Primary feature)
- "/settings" (Settings)
- "/auth/login" (Authentication)
Page Generation Order
1. LAYOUT FIRST
└── app/layout.tsx (with providers, fonts, metadata)
└── components/layout/Navbar.tsx
└── components/layout/Sidebar.tsx (if dashboard-style)
└── components/layout/Footer.tsx (if marketing pages)
2. SHARED COMPONENTS
└── components/ui/ (shadcn components)
└── components/shared/ (app-specific shared)
3. FEATURE COMPONENTS
└── components/features/[feature]/ (feature-specific)
4. PAGES (parallel if possible)
└── app/page.tsx
└── app/dashboard/page.tsx
└── app/[feature]/page.tsx
└── ...etc
5. AUTH PAGES (last)
└── app/auth/login/page.tsx
└── app/auth/register/page.tsx
✨ Animation System (MANDATORY!)
Required Animations
Every premium app MUST have these animations:
// 1. PAGE TRANSITIONS
// Every page should fade in smoothly
// components/motion/PageTransition.tsx
"use client";
import { motion } from "framer-motion";
import { ReactNode } from "react";
const pageVariants = {
initial: { opacity: 0, y: 20 },
animate: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -20 },
};
export function PageTransition({ children }: { children: ReactNode }) {
return (
<motion.div
variants={pageVariants}
initial="initial"
animate="animate"
exit="exit"
transition={{ duration: 0.3, ease: "easeOut" }}
>
{children}
</motion.div>
);
}
// 2. STAGGERED LIST ANIMATIONS
// Lists should animate in one by one
// components/motion/StaggerContainer.tsx
"use client";
import { motion } from "framer-motion";
import { ReactNode } from "react";
const containerVariants = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: {
staggerChildren: 0.1,
},
},
};
const itemVariants = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0 },
};
export function StaggerContainer({ children }: { children: ReactNode }) {
return (
<motion.div
variants={containerVariants}
initial="hidden"
animate="show"
>
{children}
</motion.div>
);
}
export function StaggerItem({ children }: { children: ReactNode }) {
return <motion.div variants={itemVariants}>{children}</motion.div>;
}
// 3. CARD HOVER EFFECTS
// Cards should lift on hover
// Usage in any card component
<motion.div
whileHover={{ y: -4, boxShadow: "0 10px 40px -10px rgba(0,0,0,0.2)" }}
transition={{ duration: 0.2 }}
className="..."
>
{/* Card content */}
</motion.div>
// 4. BUTTON PRESS EFFECTS
// Buttons should feel tactile
// Usage on buttons
<motion.button
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
className="..."
>
{children}
</motion.button>
// 5. NUMBER COUNTING ANIMATION
// Stats should count up
// components/motion/CountUp.tsx
"use client";
import { useEffect, useRef, useState } from "react";
import { useInView } from "framer-motion";
interface CountUpProps {
end: number;
duration?: number;
prefix?: string;
suffix?: string;
}
export function CountUp({ end, duration = 2, prefix = "", suffix = "" }: CountUpProps) {
const [count, setCount] = useState(0);
const ref = useRef(null);
const isInView = useInView(ref, { once: true });
useEffect(() => {
if (!isInView) return;
let startTime: number;
const animate = (timestamp: number) => {
if (!startTime) startTime = timestamp;
const progress = Math.min((timestamp - startTime) / (duration * 1000), 1);
setCount(Math.floor(progress * end));
if (progress < 1) requestAnimationFrame(animate);
};
requestAnimationFrame(animate);
}, [isInView, end, duration]);
return <span ref={ref}>{prefix}{count.toLocaleString()}{suffix}</span>;
}
Animation Timing Guidelines
/* Standard timings */
--duration-fast: 150ms; /* Micro-interactions */
--duration-normal: 200ms; /* Button/hover states */
--duration-slow: 300ms; /* Page transitions */
--duration-slower: 500ms; /* Complex animations */
/* Easing functions */
--ease-out: cubic-bezier(0.33, 1, 0.68, 1); /* Most animations */
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); /* Symmetric motion */
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* Playful bounce */
Animation Rules
DO:
✅ Use subtle animations (y: 20 max, scale: 1.02 max)
✅ Keep durations short (150-300ms)
✅ Use ease-out for most animations
✅ Animate on scroll (useInView)
✅ Stagger lists (100ms between items)
DON'T:
❌ Bounce animations (too playful)
❌ Long durations (>500ms feels slow)
❌ Large movements (y: 100+ is jarring)
❌ Animate everything (be selective)
❌ Block interaction during animation
🎨 Premium UI Components
Required Shared Components
Every premium app MUST have these components:
components/
├── layout/
│ ├── Navbar.tsx # Responsive navigation
│ ├── Sidebar.tsx # Dashboard sidebar (if applicable)
│ ├── Footer.tsx # Marketing footer (if applicable)
│ └── MobileMenu.tsx # Mobile navigation drawer
│
├── motion/
│ ├── PageTransition.tsx # Page fade-in
│ ├── StaggerContainer.tsx # List animations
│ ├── FadeIn.tsx # Simple fade-in wrapper
│ └── CountUp.tsx # Number animation
│
├── feedback/
│ ├── LoadingSpinner.tsx # Generic loading
│ ├── Skeleton.tsx # Content skeleton
│ ├── EmptyState.tsx # Empty state with illustration
│ └── ErrorBoundary.tsx # Error fallback
│
├── shared/
│ ├── Logo.tsx # Brand logo
│ ├── Avatar.tsx # User avatar with fallback
│ ├── Badge.tsx # Status badges
│ └── SearchInput.tsx # Global search (if applicable)
│
└── ui/ # shadcn/ui components
└── (generated by shadcn)
Loading State Pattern
// EVERY page should have loading state
// app/dashboard/loading.tsx
import { Skeleton } from "@/components/ui/skeleton";
export default function DashboardLoading() {
return (
<div className="space-y-6 p-6">
{/* Stats skeleton */}
<div className="grid grid-cols-4 gap-4">
{[...Array(4)].map((_, i) => (
<Skeleton key={i} className="h-32 rounded-xl" />
))}
</div>
{/* Chart skeleton */}
<Skeleton className="h-64 rounded-xl" />
{/* Table skeleton */}
<div className="space-y-2">
{[...Array(5)].map((_, i) => (
<Skeleton key={i} className="h-12 rounded-lg" />
))}
</div>
</div>
);
}
Empty State Pattern
// components/feedback/EmptyState.tsx
import { LucideIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
interface EmptyStateProps {
icon: LucideIcon;
title: string;
description: string;
actionLabel?: string;
onAction?: () => void;
}
export function EmptyState({
icon: Icon,
title,
description,
actionLabel,
onAction,
}: EmptyStateProps) {
return (
<div className="flex flex-col items-center justify-center py-12 text-center">
<div className="rounded-full bg-muted p-4 mb-4">
<Icon className="h-8 w-8 text-muted-foreground" />
</div>
<h3 className="text-lg font-semibold mb-2">{title}</h3>
<p className="text-muted-foreground mb-4 max-w-sm">{description}</p>
{actionLabel && onAction && (
<Button onClick={onAction}>{actionLabel}</Button>
)}
</div>
);
}
🛡️ Zero Error Guarantee
TypeScript Strict Rules
// tsconfig.json MUST have these
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true
}
}
Pre-Generation Checklist
Before generating ANY code, verify:
□ All imports are valid (no typos)
□ All types are defined
□ All props have types
□ No `any` type used
□ All async functions have error handling
□ All optional chaining where needed (?.)
□ All nullish coalescing where needed (??)
□ All arrays initialized before use
□ All state has initial values
Common Error Prevention Patterns
// ❌ BAD: Will error if data is undefined
{data.items.map(item => ...)}
// ✅ GOOD: Safe with fallback
{(data?.items ?? []).map(item => ...)}
// ❌ BAD: Type error on undefined
function UserCard({ user }) { ... }
// ✅ GOOD: Proper typing
interface UserCardProps {
user: User;
}
function UserCard({ user }: UserCardProps) { ... }
// ❌ BAD: Unhandled async
const data = await fetch(...);
// ✅ GOOD: With error handling
try {
const data = await fetch(...);
if (!data.ok) throw new Error('Failed to fetch');
return data.json();
} catch (error) {
console.error('Fetch error:', error);
return null;
}
Required Type Definitions
Every project MUST have:
// types/index.ts
export interface User {
id: string;
name: string;
email: string;
avatar?: string;
createdAt: Date;
}
// types/[feature].ts
export interface [Feature] {
id: string;
// ... feature-specific fields
createdAt: Date;
updatedAt: Date;
}
// types/api.ts
export interface ApiResponse<T> {
data: T;
error?: string;
message?: string;
}
export interface PaginatedResponse<T> {
data: T[];
total: number;
page: number;
pageSize: number;
hasMore: boolean;
}
🎁 WOW Factor Elements
Must-Have WOW Features
hero_section:
- Gradient text on heading (subtle)
- Animated background elements (floating shapes)
- CTA button with hover glow
- Stats with count-up animation
dashboard:
- Animated stat cards (stagger in)
- Charts with loading animation
- Real-time indicators (pulsing dot)
- Smooth tab transitions
lists:
- Staggered item appearance
- Hover lift effect on cards
- Smooth reorder animation (drag/drop)
- Pull-to-refresh indicator (mobile)
forms:
- Input focus animations
- Real-time validation feedback
- Submit button loading state
- Success confetti (optional)
navigation:
- Active state indicator animation
- Mobile menu slide-in
- Breadcrumb transitions
- Search expand animation
Premium Design Details
shadows:
cards: "shadow-sm hover:shadow-lg transition-shadow"
modals: "shadow-2xl"
dropdowns: "shadow-lg"
borders:
cards: "border border-border/50"
inputs: "border border-input focus:ring-2 focus:ring-primary/20"
backgrounds:
page: "bg-background"
card: "bg-card"
muted: "bg-muted/50"
gradient: "bg-gradient-to-br from-primary/10 via-background to-secondary/10"
hover_states:
cards: "hover:border-primary/50 transition-colors"
buttons: "hover:brightness-110 transition-all"
links: "hover:text-primary transition-colors"
📋 Pre-Delivery Verification
Final Checklist (MANDATORY!)
Before delivering to user, verify ALL:
BUILD CHECK:
□ `npm run build` passes with 0 errors
□ `npm run lint` passes with 0 warnings
□ All pages render without errors
PAGES CHECK (minimum 5):
□ Homepage/Landing created
□ Main feature page created
□ Dashboard/Detail page created
□ Settings page created
□ Auth page created (at least login)
ANIMATION CHECK:
□ Page transitions working
□ List animations working
□ Card hover effects working
□ Button press feedback working
□ Loading states animated
RESPONSIVE CHECK:
□ Mobile layout works (320px+)
□ Tablet layout works (768px+)
□ Desktop layout works (1024px+)
□ No horizontal scroll
QUALITY CHECK:
□ No TypeScript errors
□ No console errors
□ No missing images (use placeholders)
□ No broken links
□ Loading states present
□ Empty states designed
🚀 Quick Start Template
When starting a new project, use this structure:
project/
├── app/
│ ├── layout.tsx # Root layout with providers
│ ├── page.tsx # Landing/Home
│ ├── loading.tsx # Global loading
│ ├── error.tsx # Global error
│ ├── not-found.tsx # 404 page
│ │
│ ├── dashboard/
│ │ ├── page.tsx # Dashboard
│ │ └── loading.tsx # Dashboard skeleton
│ │
│ ├── [feature]/
│ │ ├── page.tsx # Feature list
│ │ ├── [id]/page.tsx # Feature detail
│ │ └── loading.tsx # Feature skeleton
│ │
│ ├── settings/
│ │ └── page.tsx # Settings
│ │
│ └── auth/
│ ├── login/page.tsx # Login
│ └── register/page.tsx # Register
│
├── components/
│ ├── layout/ # Layout components
│ ├── motion/ # Animation components
│ ├── feedback/ # Loading, empty, error states
│ ├── features/ # Feature-specific components
│ ├── shared/ # Shared components
│ └── ui/ # shadcn/ui
│
├── lib/
│ ├── utils.ts # Utility functions
│ └── mock-data.ts # Realistic mock data
│
├── stores/
│ └── use-[feature].ts # Zustand stores
│
├── types/
│ ├── index.ts # Shared types
│ └── [feature].ts # Feature types
│
└── providers/
└── providers.tsx # All providers wrapped
🌐 Internationalization Note
All code, comments, and documentation should be in English.
Only user-facing content (mock data, UI text) should match the user's language:
// Code: Always English
interface ProductCardProps {
product: Product;
}
// Mock data: Match user language
const mockProducts = [
// Thai user
{ name: "กาแฟลาเต้", price: 65 },
// English user
{ name: "Caffe Latte", price: 65 },
];
Premium Experience Skill v1.0.0 - One Prompt, Complete App, Instant WOW
Repository
