GameCraftGameCraft

Demo Mode

Try ProductReady without login - explore features with sample data

Demo Mode

ProductReady includes a Demo Mode that lets you explore all features without creating an account or setting up a database. Perfect for:

  • ๐ŸŽฏ Quick exploration - See features in action immediately
  • ๐Ÿ‘ฅ Demonstrations - Show your app to stakeholders
  • ๐Ÿงช Testing - Try the UI and workflows without real data
  • ๐Ÿ“š Learning - Understand how features work before implementation

No setup required! Demo mode works with mock data - no database, no authentication needed.


How to Use Demo Mode

Activate Demo Mode

Add ?demo=1 to any URL:

http://localhost:3000/dashboard?demo=1
http://localhost:3000/agent?demo=1

Or use the Demo User Login on the sign-in page (see below).


What's Included in Demo Mode

When demo mode is active, you'll see:

โœ… Sample Data

  • 5 demo agent tasks (various statuses: pending, in progress, completed, failed)
  • 8 example blog posts (published and draft)
  • 3 demo users

โœ… Full UI Access

  • Dashboard with metrics
  • Agent task management
  • Blog post listing
  • All navigation and layouts

โœ… Read-Only Operations

  • View all demo content
  • Browse and filter
  • See UI interactions

โš ๏ธ Limitations

  • Cannot create/edit/delete real data
  • Changes show alerts but don't persist
  • Database operations return mock data

Demo User Login

The sign-in page includes a "Try Demo Mode" button for instant access without credentials.

Go to Sign-In Page

Visit /sign-in or click "Sign In" from the landing page.

Click "Try Demo Mode"

Look for the blue button below the login form:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Sign in to ProductReady     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Email: _______________  โ”‚
โ”‚ Password: ___________   โ”‚
โ”‚ [Sign In]               โ”‚
โ”‚                         โ”‚
โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€ OR โ”€โ”€โ”€โ”€โ”€โ”€โ”€      โ”‚
โ”‚                         โ”‚
โ”‚ [Try Demo Mode]  โ† Here โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Explore Features

You'll be redirected to /dashboard?demo=1 with full access to demo content.

  • Create agent tasks (alerts instead of saving)
  • View sample blog posts
  • Navigate all dashboard sections
  • See how tRPC queries work

Demo Data Examples

Demo Agent Tasks

Demo mode includes 5 sample agent tasks:

// Sample demo agent tasks
[
  {
    title: "Create landing page with pricing section",
    status: "completed",
    priority: "high",
    result: "Successfully generated landing page..."
  },
  {
    title: "Generate blog post about Next.js 16",
    status: "in_progress",
    priority: "high"
  },
  {
    title: "Create dashboard component with charts",
    status: "pending",
    priority: "medium"
  },
  // ... more tasks
]

Demo Blog Posts (Example Feature)

8 example posts covering various topics:

  • "Getting Started with ProductReady"
  • "Understanding tRPC Type Safety"
  • "Drizzle ORM Best Practices"
  • "Building a Design System with CSS Variables"
  • And more...

Note: Blog posts are an example feature to demonstrate CRUD operations. You can remove this feature or replace it with your own business logic.

Demo Users

3 demo users for testing:

  • Alice Johnson (alice@example.com)
  • Bob Smith (bob@example.com)
  • Carol Williams (carol@example.com)

Using Demo Mode in Your Code

Detect Demo Mode

import { isDemoMode } from '~/lib/demo';

export function MyComponent() {
  const searchParams = useSearchParams();
  const isDemo = isDemoMode(searchParams);
  
  if (isDemo) {
    return <DemoBanner />;
  }
  
  // Normal component
}

tRPC with Demo Mode

All tRPC routers automatically detect demo mode from the context:

// Query automatically handles demo mode based on URL/headers
const { data } = trpc.agentTasks.list.useQuery({
  limit: 20,
});

// Create with demo mode check
const createTask = trpc.agentTasks.create.useMutation({
  onMutate: () => {
    if (isDemo) {
      alert('Demo mode: Sign in to create real agent tasks');
      return;
    }
  }
});

Server-Side Demo Detection

// In tRPC router
export const myRouter = createTRPCRouter({
  list: publicProcedure
    .input(z.object({
      // No demo param needed in input
    }))
    .query(async ({ ctx, input }) => {
      // Return mock data if context indicates demo mode
      if (ctx.isDemo) {
        return getDemoData();
      }
      
      // Real database query
      return ctx.db.select().from(myTable);
    }),
});

Demo Banner Component

Demo mode shows a blue banner to indicate sample data:

{isDemo && (
  <div className="rounded-lg border border-blue-200 bg-blue-50 p-4">
    <div className="flex items-center gap-2">
      <Bot className="h-5 w-5 text-blue-600" />
      <div>
        <p className="text-sm font-medium text-blue-900">
          Demo Mode Active
        </p>
        <p className="text-sm text-blue-700">
          Viewing sample data. Sign in to create real content.
        </p>
      </div>
    </div>
  </div>
)}

Creating Your Own Demo Data

Add demo data in src/lib/demo.ts:

// Define your demo data
export const DEMO_PRODUCTS: Product[] = [
  {
    id: 1,
    name: "Starter Plan",
    price: 9.99,
    features: ["Feature 1", "Feature 2"],
  },
  // ... more items
];

// Export getter function
export function getDemoProducts(): Product[] {
  return DEMO_PRODUCTS;
}

Use in tRPC router:

import { getDemoProducts } from '~/lib/demo';

export const productsRouter = createTRPCRouter({
  list: publicProcedure
    .input(z.object({ /* ... */ }))
    .query(async ({ ctx, input }) => {
      if (ctx.isDemo) {
        return getDemoProducts();
      }
      return ctx.db.select().from(products);
    }),
});

Disabling Demo Mode

To disable demo mode in production:

// src/middleware.ts
export function middleware(request: NextRequest) {
  const { searchParams } = request.nextUrl;
  
  // Disable demo mode in production
  if (process.env.NODE_ENV === 'production' && searchParams.get('demo')) {
    const url = request.nextUrl.clone();
    url.searchParams.delete('demo');
    return NextResponse.redirect(url);
  }
  
  return NextResponse.next();
}

Or hide the demo button:

{process.env.NODE_ENV !== 'production' && (
  <Button onClick={goToDemo}>Try Demo Mode</Button>
)}

Best Practices

โœ… Do

  • Show demo banners - Make it clear when viewing sample data
  • Disable mutations - Alert users instead of showing errors
  • Use realistic data - Make demos convincing
  • Match real schema - Keep demo types in sync with database
  • Test demo mode - Ensure it works without database

โŒ Don't

  • Don't mix demo and real data - Keep them separate
  • Don't skip the banner - Users must know it's demo mode
  • Don't allow partial saves - All or nothing in demo
  • Don't expose sensitive data - Use generic demo content
  • Don't forget to document - Explain what's mocked

Troubleshooting

Demo mode not working

Check:

  1. URL has ?demo=1 parameter
  2. isDemoMode() function imported correctly
  3. Demo data exists in src/lib/demo.ts

Demo banner not showing

Check:

const searchParams = useSearchParams(); // โ† Client component
const isDemo = isDemoMode(searchParams);

Make sure component is marked "use client".

tRPC returns empty data

Check router:

.query(async ({ ctx, input }) => {
  if (ctx.isDemo) {  // โ† Check context
    return getDemoAgentTasks(); // โ† Check function exists
  }
  // ...
})

Next Steps


Demo mode is perfect for exploring ProductReady risk-free. When ready, follow the Quick Start guide to set up your own app!

On this page