← back to ClawCoder

src/app/page.tsx

213 lines

'use client'

import { useEffect, useState } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/navigation'

interface ProfileSummary {
  slug: string
  ageGroup: string
  skillLevel: string
  displayName: string
  persona: string
  ui: { fontSize: number }
  skillCount: number
  mcpCount: number
  subagentCount: number
}

const ageGroupLabels: Record<string, string> = {
  teen: 'Teen (13-17)',
  young_adult: 'Young Adult (18-30)',
  professional: 'Professional (31-50)',
  pre_senior: 'Pre-Senior (51-65)',
  senior: 'Senior (65+)',
}

const ageGroupOrder = ['teen', 'young_adult', 'professional', 'pre_senior', 'senior']
const skillLevelOrder = ['beginner', 'intermediate', 'expert']
const skillLevelLabels: Record<string, string> = {
  beginner: 'Beginner',
  intermediate: 'Intermediate',
  expert: 'Expert',
}

export default function HomePage() {
  const [profiles, setProfiles] = useState<ProfileSummary[]>([])
  const [loading, setLoading] = useState(true)
  const router = useRouter()

  useEffect(() => {
    fetch('/api/profiles')
      .then((r) => r.json())
      .then((data) => {
        setProfiles(data)
        setLoading(false)
      })
      .catch(() => setLoading(false))
  }, [])

  function getProfile(age: string, skill: string) {
    return profiles.find(
      (p) => p.ageGroup === age && p.skillLevel === skill
    )
  }

  return (
    <div className="flex flex-col">
      {/* Hero Section */}
      <section className="flex flex-col items-center justify-center px-4 py-20 text-center sm:py-28">
        <h1 className="max-w-2xl text-4xl font-bold tracking-tight text-slate-900 sm:text-5xl">
          Build your perfect CLAUDE.md
        </h1>
        <p className="mt-6 max-w-xl text-lg leading-8 text-slate-600">
          15 profiles tailored to your age and experience level. Or upload
          your existing config for instant analysis.
        </p>
        <div className="mt-10 flex flex-col gap-4 sm:flex-row">
          <Link
            href="/onboarding"
            className="inline-flex min-h-[48px] items-center justify-center rounded-xl bg-blue-600 px-8 py-3 text-base font-medium text-white transition-colors hover:bg-blue-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500"
          >
            Start Guided Setup
          </Link>
          <a
            href="#profiles"
            className="inline-flex min-h-[48px] items-center justify-center rounded-xl border border-slate-300 px-8 py-3 text-base font-medium text-slate-700 transition-colors hover:bg-slate-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500"
          >
            Choose a Profile
          </a>
          <Link
            href="/analyzer"
            className="inline-flex min-h-[48px] items-center justify-center rounded-xl border border-slate-300 px-8 py-3 text-base font-medium text-slate-700 transition-colors hover:bg-slate-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500"
          >
            Analyze My CLAUDE.md
          </Link>
        </div>
      </section>

      {/* Profile Grid */}
      <section id="profiles" className="mx-auto w-full max-w-7xl px-4 pb-20 sm:px-6">
        <h2 className="mb-8 text-center text-2xl font-bold text-slate-900">
          Choose Your Profile
        </h2>

        {loading ? (
          <div className="flex items-center justify-center py-20">
            <div className="h-8 w-8 animate-spin rounded-full border-2 border-slate-300 border-t-blue-600" />
          </div>
        ) : (
          <>
            {/* Desktop Grid */}
            <div className="hidden lg:block">
              {/* Skill level headers */}
              <div className="mb-4 grid grid-cols-[180px_1fr_1fr_1fr] gap-4">
                <div />
                {skillLevelOrder.map((skill) => (
                  <div
                    key={skill}
                    className="text-center text-sm font-semibold uppercase tracking-wider text-slate-500"
                  >
                    {skillLevelLabels[skill]}
                  </div>
                ))}
              </div>

              {/* Rows by age group */}
              {ageGroupOrder.map((age) => (
                <div
                  key={age}
                  className="mb-4 grid grid-cols-[180px_1fr_1fr_1fr] gap-4"
                >
                  <div className="flex items-center text-sm font-semibold text-slate-700">
                    {ageGroupLabels[age]}
                  </div>
                  {skillLevelOrder.map((skill) => {
                    const profile = getProfile(age, skill)
                    if (!profile) {
                      return (
                        <div
                          key={skill}
                          className="rounded-xl border border-dashed border-slate-200 p-4 text-center text-sm text-slate-400"
                        >
                          Coming soon
                        </div>
                      )
                    }
                    return (
                      <button
                        key={skill}
                        type="button"
                        onClick={() =>
                          router.push(`/builder?profile=${profile.slug}`)
                        }
                        className="group cursor-pointer rounded-xl border border-slate-200 bg-white p-5 text-left shadow-sm transition-all hover:-translate-y-0.5 hover:border-blue-300 hover:shadow-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 motion-reduce:transform-none"
                      >
                        <h3 className="text-sm font-semibold text-slate-900 group-hover:text-blue-600">
                          {profile.displayName}
                        </h3>
                        <p className="mt-1 line-clamp-2 text-xs text-slate-500">
                          {profile.persona}
                        </p>
                        <div className="mt-3 flex gap-3 text-xs text-slate-400">
                          <span>Font {profile.ui.fontSize}px</span>
                          <span>{profile.skillCount} skills</span>
                          <span>{profile.mcpCount} MCP</span>
                        </div>
                      </button>
                    )
                  })}
                </div>
              ))}
            </div>

            {/* Mobile List */}
            <div className="space-y-6 lg:hidden">
              {ageGroupOrder.map((age) => (
                <div key={age}>
                  <h3 className="mb-3 text-sm font-semibold uppercase tracking-wider text-slate-500">
                    {ageGroupLabels[age]}
                  </h3>
                  <div className="space-y-3">
                    {skillLevelOrder.map((skill) => {
                      const profile = getProfile(age, skill)
                      if (!profile) return null
                      return (
                        <button
                          key={skill}
                          type="button"
                          onClick={() =>
                            router.push(`/builder?profile=${profile.slug}`)
                          }
                          className="w-full cursor-pointer rounded-xl border border-slate-200 bg-white p-4 text-left shadow-sm transition-all hover:border-blue-300 hover:shadow-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500"
                        >
                          <div className="flex items-center justify-between">
                            <h4 className="text-sm font-semibold text-slate-900">
                              {profile.displayName}
                            </h4>
                            <span className="rounded-full bg-slate-100 px-2 py-0.5 text-xs text-slate-500">
                              {skillLevelLabels[skill]}
                            </span>
                          </div>
                          <p className="mt-1 line-clamp-2 text-xs text-slate-500">
                            {profile.persona}
                          </p>
                          <div className="mt-2 flex gap-3 text-xs text-slate-400">
                            <span>Font {profile.ui.fontSize}px</span>
                            <span>{profile.skillCount} skills</span>
                            <span>{profile.mcpCount} MCP</span>
                          </div>
                        </button>
                      )
                    })}
                  </div>
                </div>
              ))}
            </div>
          </>
        )}
      </section>
    </div>
  )
}