# DevDash - Super Hard Debug Challenge (16-18 Errors) ## Challenge Overview This is the **super hard tier** debug challenge with 16-18 intentional errors distributed across 6 categories. Students must identify and fix all errors to make the project run successfully. --- ## CATEGORY 1: BLOCKING ERRORS (3 Errors) ### Error 1: Missing Dependency - `date-fns` **File:** `src/lib/utils.ts` **Issue:** The code imports `format` from `date-fns`: ```typescript import { format } from "date-fns"; ``` But `date-fns` is **NOT** listed in `package.json`. **Symptom:** Runtime error: "Cannot find module 'date-fns'" **Fix:** Add to `package.json` dependencies: ```json "dependencies": { "date-fns": "^2.30.0" } ``` --- ### Error 2: Wrong Import Path - `next/navigations` (with 's') **File:** `src/components/Header.tsx` **Issue:** ```typescript import { usePathname } from "next/navigations"; // WRONG - has 's' ``` Should be: ```typescript import { usePathname } from "next/navigation"; // CORRECT ``` **Symptom:** Module not found error at build time **Fix:** Remove the 's' from the import path. --- ### Error 3: Circular Dependency Crash **Files:** `src/lib/types.ts` and `src/lib/utils.ts` **Issue:** In `src/lib/utils.ts`: ```typescript import { formatDate } from "./utils"; // Value import, not type ``` In `src/lib/types.ts`: ```typescript import { formatDate } from "./utils"; export function createPost(data: Omit): Post { return { ...data, formattedDate: formatDate(data.date) }; // formatDate is undefined! } ``` **Symptom:** `TypeError: formatDate is not a function` at runtime **Fix:** Use `import type` for types to avoid the circular dependency: In `src/lib/utils.ts`: ```typescript import type { Post } from "./types"; // Change to type import ``` Alternatively, restructure to avoid circular imports altogether. --- ## CATEGORY 2: NEXT.JS SPECIFIC ERRORS (4 Errors) ### Error 4: Missing "use client" Directive **File:** `src/components/ThemeToggle.tsx` **Issue:** The component uses `useState` (a client-side hook) but **lacks** `"use client"` at the top. ```typescript // MISSING "use client" at the top! import { useState } from 'react'; export function ThemeToggle() { const [isHovered, setIsHovered] = useState(false); // ... } ``` **Symptom:** Next.js error: "You're importing a component that needs useState. It only works in Client Components." **Fix:** Add at the very top of the file: ```typescript "use client"; import { useState } from 'react'; ``` --- ### Error 5: Hooks in Server Component **File:** `src/app/dashboard/page.tsx` **Issue:** The page uses `useState` and `useEffect` directly: ```typescript // MISSING "use client" at the top! import { useState, useEffect } from 'react'; export default function DashboardPage() { const [isLoading, setIsLoading] = useState(false); // ... } ``` **Symptom:** Hydration error or "You're importing a component that needs useState" **Fix:** Add `"use client"` directive at the top: ```typescript "use client"; import { useState, useEffect } from 'react'; ``` --- ### Error 6: Wrong Middleware Matcher Pattern **File:** `middleware.ts` **Issue:** ```typescript export const config = { matcher: ['/dashboard/:path'], // WRONG - missing asterisk }; ``` This matches `/dashboard/:path` but NOT `/dashboard/page/subpage`. The sub-routes won't be protected. Also, the middleware looks for `'auth-token'` cookie but the app doesn't set one: ```typescript const authToken = request.cookies.get('auth-token')?.value; ``` **Symptom:** Sub-routes of dashboard bypass middleware; authentication doesn't work **Fix:** ```typescript export const config = { matcher: ['/dashboard/:path*'], // Add asterisk for all sub-routes }; ``` And update cookie name to match what's actually used or create a mock auth mechanism. --- ### Error 7: `metadata` Export in Client Component **File:** `src/app/blog/[slug]/page.tsx` **Issue:** ```typescript 'use client'; // This is a CLIENT component export const metadata = { // Can't export metadata from client! title: 'Blog Post', description: 'Read the full article', }; import { useParams } from 'next/navigation'; ``` **Symptom:** Build error: "Metadata exports must be in a Server Component" **Fix (Option 1):** Remove `'use client'` and use function parameters instead of `useParams()`: ```typescript // Remove "use client" import { generateMetadata } from 'next'; import type { Metadata } from 'next'; export async function generateMetadata({ params }): Promise { const post = getPostBySlug(params.slug); return { title: post?.title || 'Blog Post', description: post?.content.substring(0, 100) || '', }; } export default function BlogPostPage({ params }: { params: { slug: string } }) { const post = getPostBySlug(params.slug); // ... } ``` **Fix (Option 2):** Keep as client component and remove metadata export: ```typescript 'use client'; // Remove metadata export import { useParams } from 'next/navigation'; // ... rest of component ``` --- ## CATEGORY 3: LOGIC ERRORS (3 Errors) ### Error 8: Wrong Filter Condition **File:** `src/data/posts.ts` **Issue:** ```typescript export function getPublishedPosts(): Post[] { return posts.filter(p => p.draft); // WRONG - returns DRAFTS! } ``` Should check for `!p.draft` (NOT drafted): ```typescript export function getPublishedPosts(): Post[] { return posts.filter(p => !p.draft); // CORRECT } ``` **Symptom:** Blog page shows only draft posts (only 1 post visible instead of 2 published ones) **Fix:** Change condition to `!p.draft`. --- ### Error 9: Stale Closure in Event Handler **File:** `src/components/Testimonials.tsx` **Issue:** ```typescript useEffect(() => { const timer = setInterval(() => { setCurrentIndex(currentIndex + 1); // STALE CLOSURE! }, 4000); return () => clearInterval(timer); }, []); // Empty dependency array captures initial value ``` The `currentIndex` is captured from the initial render (0). The interval always increments from 0 to 1, causing the carousel to jump back repeatedly. **Symptom:** Testimonial carousel doesn't advance smoothly; always jumps to position 1 **Fix:** Use the functional update form of `setState`: ```typescript useEffect(() => { const timer = setInterval(() => { setCurrentIndex(prev => (prev + 1) % testimonials.length); // Use prev! }, 4000); return () => clearInterval(timer); }, []); ``` --- ### Error 10: Using Index as Key **File:** `src/components/Features.tsx` **Issue:** ```typescript {displayedFeatures.map((feature, index) => (
// WRONG - using index as key {/* ... */}
))} ``` Using index as key is problematic if the list reorders or filters. **Symptom:** Visual glitches when filtering features; component state gets mixed up **Fix:** Use unique identifier: ```typescript {displayedFeatures.map((feature) => (
// Use feature.id {/* ... */}
))} ``` --- ## CATEGORY 4: TYPESCRIPT ERRORS (2 Errors) ### Error 11: Wrong API Response Type **File:** `src/app/api/stats/route.ts` and `src/components/StatsGrid.tsx` **Issue:** API returns wrapped response: ```typescript // src/app/api/stats/route.ts return NextResponse.json({ data: stats }); // Wrapped in { data: ... } ``` But component expects unwrapped array: ```typescript // src/components/StatsGrid.tsx const data = await response.json(); setStats(data); // Expects data to be array, but gets { data: [...] } ``` Later: ```typescript {stats.map((stat, index) => ( // stats is an object, not array! ``` **Symptom:** TypeError: `stats.map is not a function` **Fix - Option 1:** Unwrap in component: ```typescript const data = await response.json(); setStats(data.data); // Extract the array ``` **Fix - Option 2:** Change API response: ```typescript return NextResponse.json(stats); // Return array directly ``` --- ### Error 12: Missing Optional Chaining **File:** `src/components/UserProfile.tsx` **Issue:** ```typescript {user.profile.avatar} // profile could be undefined! ``` The API might return a user without a `profile` object: ```typescript const user: User = { id: '1', name: 'John', email: 'john@example.com', // profile is undefined! }; ``` **Symptom:** TypeError: `Cannot read property 'avatar' of undefined` **Fix:** Use optional chaining: ```typescript {user.profile?.avatar} // Safe access ``` Or add a null check: ```typescript {user.profile && user.profile.avatar} ``` --- ## CATEGORY 5: REACT PATTERN ERRORS (3 Errors) ### Error 13: Missing useEffect Cleanup **File:** `src/app/dashboard/page.tsx` **Issue:** ```typescript useEffect(() => { window.addEventListener('resize', handleResize); // Missing cleanup! // Should have: return () => window.removeEventListener('resize', handleResize); }, []); ``` **Symptom:** Memory leak; listeners accumulate when component remounts; "Can't perform a React state update on an unmounted component" warnings **Fix:** Add cleanup function: ```typescript useEffect(() => { function handleResize() { setIsLoading(window.innerWidth < 768); } window.addEventListener('resize', handleResize); // Add cleanup return () => { window.removeEventListener('resize', handleResize); }; }, []); ``` --- ### Error 14: Incorrect Context Provider Wrapping **File:** `src/app/layout.tsx` **Issue:** ```typescript
{/* Header tries to use theme context but provider hasn't wrapped it yet! */}
{children}