# Prowler UI Agent Guide **Complete guide for AI agents and developers working on the Prowler UI Next.js application.** ## Mission & Scope - Ship small, high-impact UI changes with minimal risk - Align to current patterns: App Router, Server Components first, consistent styling, strict types - Avoid broad refactors, library swaps, or reorganization unless requested - Focus on safe, incremental frontend changes aligned with existing architecture --- ## Critical Architecture Rules (Non-Negotiable) ### 1. React Imports (Required) **NEVER** import React with `import * as React`. Instead, import only what you need: **❌ DON'T:** ```typescript import * as React from "react"; import React, { useState } from "react"; ``` **✅ DO:** ```typescript import { useState, useEffect } from "react"; ``` **When you need nothing from React (e.g., only using JSX):** ```typescript // No React import needed - JSX works without it in modern Next.js export function MyComponent() { return
Hello
; } ``` ### 2. TypeScript Type Patterns (Required) When defining union types for options, ALWAYS create a const object first, then extract the type: **❌ DON'T:** ```typescript type SortOption = "high-low" | "low-high" | "alphabetical"; ``` **✅ DO:** ```typescript const SORT_OPTIONS = { HIGH_LOW: "high-low", LOW_HIGH: "low-high", ALPHABETICAL: "alphabetical", } as const; type SortOption = (typeof SORT_OPTIONS)[keyof typeof SORT_OPTIONS]; ``` ### 2. Tailwind 4 Theme Variables This project uses Tailwind 4 with @theme variables. **Tailwind is mainly semantic** - prioritize using Tailwind's naming system whenever possible. #### In Template/JSX (className) - ✅ Use Tailwind utility classes: `bg-card-bg`, `text-white`, `text-slate-400`, `border-slate-700` - ✅ Use arbitrary values with classes: `h-3`, `w-3`, `min-w-[200px]`, `bg-slate-700/50` - ✅ Use Tailwind for conditional styles: `className={isActive ? "bg-blue-500" : "bg-gray-500"}` - ✅ Use style props only for truly dynamic values: `style={{ width: \`\${percentage}%\` }}` - ❌ NEVER use `var()` in className - ❌ NEVER use hex colors in className #### Constants with var() (Only for library props that don't accept className) - ✅ Use CHART_COLORS constants: `stroke={CHART_COLORS.gridLine}`, `tick={{ fill: CHART_COLORS.textSecondary }}` - These props don't accept className, so we use constants that internally reference `var()` - This is the **only** valid use case for `var()` - when the library doesn't support className #### Examples ```tsx // ✅ GOOD - Template with Tailwind classes

{title}

// ✅ GOOD - Conditional Tailwind classes // ✅ GOOD - Recharts library props with CHART_COLORS (var() only here) // ✅ GOOD - Truly dynamic values (not available in Tailwind)
// ❌ BAD - var() in className
// Don't do this! // ❌ BAD - Hex colors in className

// Use text-white instead // ❌ BAD - Using var() for colors when Tailwind classes exist const PROVIDER_COLORS = { AWS: "var(--color-orange)", // Use Tailwind classes instead! }; // ❌ BAD - Using style when className is available

// Use className="bg-blue-500" instead ``` ### 3. The `cn()` Utility Function #### What is `cn()`? The `cn()` function is a utility that combines `clsx` and `tailwind-merge`: ```typescript import { clsx } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } ``` **Components:** - **`clsx`**: Constructs conditional className strings (handles booleans, arrays, objects) - **`twMerge`**: Intelligently merges Tailwind classes, resolving conflicts (e.g., `p-4` + `p-2` → `p-2`) #### When to Use `cn()` Use `cn()` **ONLY** when you have: ##### 1. Conditional Classes ```tsx // ✅ GOOD - Conditional logic
// ✅ GOOD - Boolean conditionals