+ {dashboardConfig.sections.backlog.acceptanceLabel}{" "} + {problem.acceptanceRate !== null + ? `${Math.round(problem.acceptanceRate * 100)}%` + : "—"} +
++ {layout.headline} +
+{layout.tagline}
+diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..97f0e81 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "prisma.pinToPrisma6": true +} diff --git a/AGENTS.md b/AGENTS.md index 650701c..8029dc9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -✅ OPEN SOLVE — MASTER REDESIGN & IMPLEMENTATION PROMPT +# OPENSOLVE — DESIGN SYSTEM & IMPLEMENTATION GUIDE (Cursor Agent Spec) You are the **principal product/UI engineer for OpenSolve**, an open-source LeetCode alternative. @@ -8,444 +8,617 @@ Your job is to **completely redesign** the given page(s) and all of their nested - **Tailwind CSS** - **Customized shadcn/ui components** - **TanStack Table** -- **hugeicons-react** for all icons (see Section 4.4) +- **hugeicons-react** for all icons This is NOT a tweak or refinement. -This is a **full visual + UX rebuild** while keeping the existing data structures, hooks, and behavior intact. +This is a **full visual + UX rebuild** while keeping the **existing data structures, hooks, and behavior intact**. --- -## 0. Project Context (OpenSolve) +## [00] ROLE & PRIORITIES + +**Role:** +You are responsible for the **UI/UX layer** only. You may reorganize components, JSX, and Tailwind classes, but: + +1. **Do NOT break logic** + - Keep existing hooks, tRPC calls, React Query usage, and business rules. + - Keep prop names and types unless explicitly told otherwise. + +2. **Absolute MUSTs (never violate):** + - `font-mono` for **all** text (headings, labels, body, buttons). + - **No rounded corners** anywhere → always `rounded-none`. + - **Semantic Tailwind tokens only** (`bg-background`, `text-foreground`, etc.). + - **hugeicons-react only** for icons (via `@/components/icons` or direct imports). + - Designs must work in **both light and dark mode**. + - All marketing/UX copy should be configurable (via `config/*.ts`), not hard-coded in components. + +3. **When redesigning a page, output in this structure:** + 1. **Brief UX Plan** (4–6 bullets). + 2. **Main Page Component** (full TSX with imports). + 3. **Nested Components** (any additional components you introduce). + 4. **Config File** (if applicable; put strings/copy here). + 5. **Notes** (integration points, assumptions, domain considerations). + +--- + +## [01] PROJECT CONTEXT (OPENSOLVE) OpenSolve is: -- A competitive programming / algorithmic practice platform -- Built with **Next.js**, **PostgreSQL/Prisma**, **tRPC**, **React Query**, **Tailwind**, and **shadcn/ui** -- Uses a **RabbitMQ + Docker judge** for submissions -- Has rich domain entities: +- A **competitive programming / algorithmic practice platform**. +- Built with **Next.js**, **PostgreSQL/Prisma**, **tRPC**, **React Query**, **Tailwind**, and **shadcn/ui**. +- Uses a **RabbitMQ + Docker judge** (plus an inline simulator fallback) for submissions. +- Includes rich domain entities like: - `User`, `Problem`, `ProblemVersion`, `Tag`, `Difficulty`, `Company` - `Submission`, `Language`, `Verdict`, `TestCase` - `Contest`, `ContestProblem`, `ContestRegistration`, `ContestSnapshot`, `ContestClarification` - `Discussion`, `TrailInsight`, `Badge`, `Leaderboard*`, `SystemSetting`, `Incident`, etc. -Everything you design must feel **native to this domain**: -coding, problems, submissions, contests, leaderboards, discussions, admin tooling. +Everything you design must feel **native** to this domain: + +> Coding, problems, submissions, contests, leaderboards, discussions, staff tools, admin consoles. --- -## 1. Goal: Complete Redesign (Not Modification) +## [02] DESIGN LANGUAGE — “BRUTALIST TERMINAL” -**Do NOT**: +### 2.1 Core Aesthetic -- Do not preserve or slightly improve the current layout. -- Do not keep the same structure and just reskin. -- Do not keep “placeholder” structures from the old UI. +OpenSolve uses a **brutalist, terminal-inspired** design. It should feel like a **serious developer tool**, not a generic SaaS. -**Instead**: +**Key principles:** -- **Replace the entire page UI and all nested components** with a new, intentional, premium OpenSolve design. -- Create a layout and visual hierarchy that looks handcrafted and product-grade—**not** like a generic AI/Tailwind template. +- **No rounded corners** + - Always use `rounded-none` (buttons, cards, chips, panels, inputs). +- **Sharp borders** + - Emphasis: `border-2 border-border` or `border-2 border-primary`. + - Dividers: `border border-border`. +- **Monospace typography** + - `font-mono` for **all** text, including headings and buttons. +- **Numbered sections** + - Use bracket notation: `[01]`, `[02]`, `[03]` for major sections. +- **Functional minimalism** + - No decorative flourishes for their own sake. + - Let grid, spacing, typography, and subtle gradients carry the visual weight. +- **Magazine-style layouts** + - Asymmetric grids, bold headings, strong hierarchy. -The new UI must make people think: +--- -> “There’s no way AI built this. This looks like a serious, professionally designed product.” +## [03] COLOR SYSTEM — SEMANTIC ONLY ---- +### 3.1 Semantic Tokens -## 2. Global Layout & Information Architecture (Enforce These Patterns) +**Never** use raw hex colors or Tailwind’s gray/blue palettes (`text-gray-900`, `bg-white`, etc.). +Only use semantic tokens (which are mapped in CSS for light/dark modes): -OpenSolve uses a **unified app shell**: +- `bg-background` / `text-foreground` — page background and primary text. +- `text-muted-foreground` — secondary text. +- `bg-card` / `text-card-foreground` — card surfaces. +- `bg-primary` / `text-primary-foreground` — primary actions and CTAs. +- `text-primary` — emphasis text. +- `bg-accent` — subtle backgrounds & hovers. +- `border-border` — all default borders. +- State colors (if defined): + - `bg-success`, `text-success`, `bg-success/10`, `border-success/30` + - `bg-warning`, `text-warning`, `bg-warning/10`, `border-warning/30` + - `bg-destructive`, `text-destructive`, `bg-destructive/10`, `border-destructive/30` + - `bg-info`, `text-info`, `bg-info/10`, `border-info/30` -- **Left Sidebar** → main navigation (Problems, Submissions, Contests, Discussions, Trails, Profile, Admin, etc.) -- **Topbar** → page context and actions +### 3.2 Gradients & Shadows (Subtle) -For any **authenticated/internal page** you redesign: +Use Tailwind’s gradient utilities (or equivalent custom ones) **sparingly**, mostly for headings and hero sections: -1. **Sidebar (persistent)** - - Implement a clean, slim left sidebar for primary navigation. - - Include: - - Product logo/name - - Main nav items (Problems, Contests, Submissions, Leaderboard, Discussions, Trails) - - Admin/Staff area (only if roles permit) - - Use **icon + label** patterns (icons from `hugeicons-react`). - - Support collapse/minify on smaller screens (`md:` up). +- **Text gradients (headlines):** -2. **Topbar (always present above content)** - Use the top bar to convey: - - Page **title** and **subtitle** or short context. - - **Breadcrumbs** (e.g., Problems → Two Sum → Submissions). - - Primary **page-level actions**: “New Contest”, “Create Problem”, “Edit”, “Upsolve”, etc. - - User identity: avatar + small dropdown. - - Optional environment/light indicators (e.g., `Dev`, `Staging` badge), if reasonable. +```tsx +className = + "bg-gradient-to-br from-foreground via-foreground to-foreground/70 bg-clip-text text-transparent"; +``` + +- **Primary accent text:** + + `className="bg-gradient-to-r from-primary via-primary to-primary/70 bg-clip-text text-transparent"` + +- **Subtle background gradient:** -3. **Content Area** - - Below the topbar, design a **clear main content layout**: - - For simple detail pages: single column + side rail. - - For complex pages (problem solving, contest dashboards): **split panes**, sticky headers, and clear sections. + `className="bg-gradient-to-br from-primary/5 via-background to-background"` -4. **Responsiveness** - - On small screens: - - Sidebar collapses into a top menu or overlay. - - Topbar remains, but simplified. - - Content stacks vertically, no horizontal scroll. +- **Hover gradient overlay (e.g. cards):** -Use these patterns **consistently** across all redesigns unless a page is explicitly public/standalone (e.g., landing page, auth screens). + `
` + +- **Shadows:** + - Use `shadow-sm shadow-primary/10`, `shadow-md shadow-primary/20`, etc. + - Keep them subtle; this is not a neumorphic UI. --- -## 3. Visual Direction & Design System +## [04] TYPOGRAPHY & SPACING -### 3.1 Color System — Modern Bright SaaS (Blue Primary) +### 4.1 Typography Scale (all `font-mono`) -Use a **Modern Bright SaaS** style: +- **Hero display:** -- **Primary**: Blue (mid-saturated, not neon, not dull). - Think something in the range of Tailwind `blue-500` / `blue-600` for primary actions, with lighter tints for backgrounds/badges. -- **Neutrals**: A refined gray scale (e.g., slate/stone) for backgrounds, borders, and typography. -- **Accents** (used sparingly): - - Green for success (AC, RESOLVED, ACTIVE) - - Amber/orange for warnings (RETRYING, OFFSET, PENDING, FREEZE) - - Red/pink for errors/critical (FAILED, REJECTED, SEV1/SEV2) - - Purple or cyan for “special” or “featured” states (editorials, Trails, badges) + `className="font-mono text-6xl sm:text-7xl lg:text-8xl font-black leading-[1.05] tracking-tighter"` -Support **both light and dark mode**: +- **Section headlines:** -- Use Tailwind `dark:` variants and/or CSS variables. -- Avoid hard-coded colors like `#000`, `#fff`; instead rely on semantic tokens and classes (e.g. `bg-background`, `text-foreground`, `border-border` if using shadcn theme). + `className="font-mono text-4xl sm:text-5xl lg:text-6xl font-black leading-tight tracking-tight"` -### 3.2 Typography +- **Subsection titles:** -- Use a clean, modern sans-serif. -- Establish a clear hierarchy: - - Page title: `text-2xl` / `text-3xl`, `font-semibold` - - Section headings: `text-lg` / `text-xl`, `font-semibold` - - Body: `text-sm` / `text/base`, comfortable line-height - - Meta text: `text-xs` / `text-[13px]`, muted -- Use consistent letter spacing and alignment. No random mix of weights. + `className="font-mono text-xl font-bold"` -### 3.3 Spacing & Layout Rhythm +- **Body text:** -- Use an **8-point spacing system**: 4, 8, 12, 16, 20, 24, etc. -- Prefer Tailwind spacing tokens (`p-4`, `px-6`, `gap-4`, `gap-6`) over arbitrary pixels. -- Use `max-w-*` and `mx-auto` for constrained layouts where it makes sense (e.g. auth pages, simple forms). + `className="font-mono text-base leading-relaxed"` -### 3.4 Surfaces & Depth +- **Small / labels:** -- Cards and panels should be: - - Subtly rounded (`rounded-xl`, `rounded-2xl` for primary surfaces). - - Light shadows (`shadow-sm`, `shadow-md`), not heavy, with subtle contrast between layers. -- Use separators and soft borders (`border-border`) to structure dense information (tables, timelines, details). + `className="font-mono text-sm"` ---- +- **Meta / micro text:** -## 4. Components, Icons & Libraries (OpenSolve Constraints) + `className="font-mono text-xs text-muted-foreground"` -### 4.1 Tech Stack +- **Section markers:** -- **Next.js + TypeScript** -- **Tailwind CSS** -- **shadcn/ui components (customized)** -- **TanStack Query (React Query) over tRPC** -- **TanStack Table** for data tables -- **hugeicons-react** for all icons (see below) + `className="font-mono text-xs font-bold text-primary/80"` -Do NOT introduce: +### 4.2 Spacing System (8px base) -- New UI libraries (no MUI, Chakra, DaisyUI, etc.). -- New motion libraries (no Framer Motion, no GSAP). -- Heavy CSS frameworks beyond Tailwind. +Use Tailwind spacing aligned with 8px increments: -### 4.2 shadcn/ui +- `gap-2` (8px), `gap-3` (12px), `gap-4` (16px), `gap-6` (24px), `gap-8` (32px), `gap-12` (48px). +- `p-4`, `p-6`, `p-8`, `p-12` for padding. +- Section vertical spacing: `py-24 lg:py-32` for major sections. -- Use shadcn components as your base: `Button`, `Card`, `Tabs`, `Dialog`, `DropdownMenu`, `Badge`, `Tooltip`, `Skeleton`, `Alert`, `Toast`, `Form`, `Input`, `Textarea`, `Select`, `Checkbox`, `Switch`, `Tabs`, `ScrollArea`, etc. -- **Customize them** to match the OpenSolve design system, instead of using vanilla shadcn styles: - - Adjust radii, colors, typography via classNames/tokens. - - Ensure consistency across all redesigned pages. +--- -### 4.3 Data Tables — Use TanStack Table +## [05] CORE COMPONENT PATTERNS -For any list-heavy / admin / analytics page: +### 5.1 Buttons (shadcn/ui-based) -- Use the **existing TanStack Table abstraction** (e.g. a `DataTable` component already in the codebase). -- Do NOT hand-roll random HTML tables when a proper data table is needed. -- Enhance table UX with: - - Sticky headers - - Row hover states - - Clear sorting indicators - - Optional column visibility toggles - - Search & filters integrated into a table toolbar - - Pagination controls that feel native to the design +**Primary CTA:** -### 4.4 Icon System — Migrate to `hugeicons-react` (No `lucide-react`) +```jsx + +``` -OpenSolve is moving from `lucide-react` to **`hugeicons-react`**. -You must: +**Secondary / Outline:** -1. **Never import from `lucide-react`.** - - Remove all existing lucide imports. - - Do not introduce new ones. - - Replace every lucide icon with a `hugeicons-react` icon. +```jsx + +``` -2. **Use `hugeicons-react` for every icon**: - - Navigation icons (sidebar, topbar) - - Action icons (buttons, fab, menus) - - Status icons (success, error, warning, info) - - Domain icons (problems, contests, submissions, discussions, leaderboard, admin, incidents, settings, feature flags, judge, queues, etc.) +**Ghost / text button:** -3. **If you don’t know which `hugeicons-react` icon to use or how to import it**, you MUST: - - Perform an internet search to look up: - - The `hugeicons-react` package, - - Its icon list and naming conventions, - - The appropriate icon component name and import syntax. - - Then choose the most semantically appropriate icon (e.g. problem→code/algorithm icon, contests→trophy/flag, submissions→checklist or code-run icon, incidents→alert, etc.). +```jsx + +``` -4. **Consistency**: - - Use a consistent size (e.g. `className="h-4 w-4"` or `h-5 w-5`) for icons in a given context. - - Use consistent stroke/fill style (outlined vs filled) for icons in the same UI area. - - Use Tailwind utility classes to align icons (`inline-flex`, `items-center`, `gap-2`). +**Icon button:** -Example (illustrative, not exact): +```jsx + +``` -```tsx -import { CodeCircle01Icon, Trophy01Icon } from "hugeicons-react"; +### 5.2 Cards / Panels + +**Default card:** -; +```jsx +{config.hero.description}
{" "} +Helper text
++ {magicLink.loading.description} +
+Validating magic link...
++ We're verifying your magic link token and establishing a secure session. This may + take a few seconds. +
++ {magicLink.success.description} +
+Redirecting to dashboard...
++ {magicLink.error.description} +
+• Link has already been used (single-use only)
+• Link expired (15 minute validity)
+• Token was tampered with or corrupted
+• Network error during validation
++ {resetPassword.invalid.description} +
++ {resetPassword.description} +
++ {verifyEmail.loading.description} +
+Validating token...
++ {verifyEmail.success.description} +
++ {verifyEmail.error.description} +
+1. Sign in to your account
+2. Navigate to Settings → Account
+3. Request a new verification email
+- Join a community of engineers solving problems, competing in contests, and sharpening - their craft every day. -
-{layout.tagline}
+Sign in to continue your learning journey
+Start solving problems and competing today
+{siteConfig.description}
-+ {landingConfig.hero.description} +
+ ++ {landingConfig.features.subtitle} +
++ {feature.description} +
++ {landingConfig.techStack.footer} +
++ {landingConfig.cta.subtitle} +
+ +- Mission Control -
-- Monitor your submissions, upcoming contests, and proposals without leaving this - cockpit. -
-{action.label}
-{action.description}
- - ))} -- Last submission -
-- {submissionSummary.lastSubmissionAt - ? formatDistanceToNow(submissionSummary.lastSubmissionAt, { addSuffix: true }) - : "No history yet"} +
+ {dashboardConfig.hero.marker}
-- Keep the streak alive by solving any problem today. -
-{dashboardConfig.hero.description}
++ Operator: {operatorName} +
++ {dashboardConfig.hero.summaryLabel} +
++ {submissionSummary.lastSubmissionAt + ? formatDistanceToNow(submissionSummary.lastSubmissionAt, { addSuffix: true }) + : dashboardConfig.hero.historyFallback} +
+{dashboardConfig.hero.summaryHelper}
+{metric.label}
-{metric.value}
-{metric.meta}
++ {dashboardConfig.sections.telemetry.chart.title} +
++ {dashboardConfig.sections.telemetry.chart.description} +
++ {dashboardConfig.sections.backlog.title} +
++ {dashboardConfig.sections.backlog.description} +
+ {dashboardConfig.sections.backlog.acceptanceLabel}{" "} + {problem.acceptanceRate !== null + ? `${Math.round(problem.acceptanceRate * 100)}%` + : "—"} +
++ {dashboardConfig.sections.activity.table.title} +
++ {dashboardConfig.sections.activity.table.description} +
{status.value}
-{status.label}
++ {dashboardConfig.sections.activity.proposals.title} +
++ {dashboardConfig.sections.activity.proposals.description} +
+{proposalStats[stat.key]}
+{stat.label}
- Intended difficulty: {proposal.intendedDifficulty} + {dashboardConfig.sections.activity.proposals.intendedDifficultyLabel}:{" "} + {proposal.intendedDifficulty}
-+ {dashboardConfig.sections.contests.featuredLabel} +
+Featured contest
-{nextContest.description}
-{contest.name}
-- {formatDistanceToNow(new Date(contest.startsAt), { addSuffix: true })} -
-{dashboardConfig.sections.contests.upcomingLabel}
+ {contestOverview.upcoming.length} events +{contest.name}
++ {formatDistanceToNow(new Date(contest.startsAt), { addSuffix: true })} +
+- Acceptance{" "} - {problem.acceptanceRate !== null - ? `${Math.round(problem.acceptanceRate * 100)}%` - : "—"} -
-{marker}
+{description}
+ ) : null} +{description}
+{label}
+{value}
+{meta}
+{label}
-{value}
- {muted ?{muted}
: null} +{value}
+{meta}
++ {dashboardConfig.sections.contests.featuredLabel} +
+{contest.description}
+{label}
+{value}
+ {meta ?{meta}
: null}{title}
-{description}
-{title}
+{description}
+Problem
-+ {submissionsConfig.problem.marker} +
++ {submissionsConfig.problem.description} +
+Problem
+{problem.title}
+- Manage your account details and security preferences -
-Your core account details
+ return ( ++ {settingsConfig.account.description} +
+{stat.label}
+{stat.value}
+{session.user.email}
+{session.user.email}
{session.user.emailVerified ? ( -+ {settingsConfig.account.info.emailFootnote} +
@{session.user.handle}
+@{session.user.handle}
+{settingsConfig.account.info.title}
- {session.user.twoFactorEnabled ? "Enabled" : "Disabled"} +
+ {session.user.twoFactorEnabled + ? settingsConfig.account.info.twoFactorEnabled + : settingsConfig.account.info.twoFactorDisabled}
- Devices where you're currently signed in -
-{sess.userAgent || "Unknown Device"}
- {sess.isCurrent ? ( -+ {sess.userAgent || settingsConfig.account.sessions.deviceUnknown} +
+ {sess.isCurrent ? ( ++ {sess.ipAddress} · {settingsConfig.account.sessions.lastActive}{" "} + {formatDistanceToNow(new Date(sess.lastUsedAt), { addSuffix: true })} +
+- {sess.ipAddress} · Last active{" "} - {formatDistanceToNow(new Date(sess.lastUsedAt), { addSuffix: true })} -
+ {!sess.isCurrent ? ( +Sign out everywhere
++ {settingsConfig.account.sessions.signOutAll.title} +
- Terminate all active sessions on all devices + {settingsConfig.account.sessions.signOutAll.description}
+ {settingsConfig.account.danger.marker} +
+- Irreversible actions. Please proceed with caution. + {settingsConfig.account.danger.description}
+ {settingsConfig.account.danger.warningTitle} +
+Warning:
-{marker}
+{description}
+ ) : null}- Manage your public profile information and avatar -
-+ {settingsConfig.profile.description} +
+{stat.label}
+{stat.value}
+- Upload a new avatar. Max 2MB. PNG or JPEG recommended. -
-{settingsConfig.profile.avatar.helper}
fileInputRef.current?.click()} disabled={uploading} - className="rounded-xl" + className="h-11 rounded-none border-2 border-border px-5 text-xs font-bold uppercase" >