Consolidation
This page tracks concrete issues where the codebase uses duplicate implementations, bypasses the shared component library, or uses hardcoded values instead of design tokens. Each item includes the recommended fix.
Priority 1 — Duplicate Components
1. ShaderGradientBackground
Status: Duplicated across apps
| File | App |
|---|---|
apps/landing/src/app/components/shader-gradient-background.tsx | Landing |
apps/admin/src/app/components/ShaderGradientBackground.tsx | Admin |
Both files contain identical implementations: a ShaderErrorBoundary class component wrapping ShaderGradientCanvas with the same parameters and CSS fallback.
Fix: Move to packages/shared/components/shader-gradient-background.tsx and import from @prosper/shared in both apps.
Priority 2 — Shared Components Not Used
2. ApplicationForm uses raw HTML elements
File: apps/landing/src/app/components/ApplicationForm.tsx
This 700+ line form uses raw HTML elements with inline Tailwind classes throughout:
| Raw Element | Shared Replacement |
|---|---|
<input> | Input |
<select> | Select + SelectTrigger + SelectContent + SelectItem |
<textarea> | Textarea |
<label> | Label |
<input type="radio"> | RadioGroup + RadioGroupItem |
<button> | Button |
Impact: Inconsistent focus rings, missing error styling patterns, visual discrepancies between the application form and the contact form (which correctly uses shared components).
Fix: Replace all raw elements with their shared counterparts. The ContactPage (contact-page.tsx) serves as a reference for the correct import pattern.
3. CandidateInfoPage minimal shared UI usage
File: apps/admin/src/app/components/CandidateInfoPage.tsx
Uses mostly raw HTML + Tailwind for layout. Local helper components FilePill and SectionHeading are defined inline.
Fix:
- Use
Cardfor the main content area - Use
Badgefor status indicators (work auth, sponsorship, etc.) - Use
Separatorbetween sections - Extract
FilePillandSectionHeadingif reused elsewhere, or at minimum adopt shared styling patterns
4. ProsperChatPanel fully custom UI
File: apps/admin/src/app/components/ProsperChatPanel.tsx
A 700+ line component with entirely custom button, input, and card styling.
Fix: Adopt Button, Input, Card, and ScrollArea from shared where applicable, particularly for the input bar and action buttons.
Priority 3 — Token / Style Issues
5. SearchInput debug logging
File: packages/shared/components/ui/search-input.tsx
Contains #region agent log blocks with fetch() calls to 127.0.0.1:7242 in useEffect, onFocus, and onChange handlers. This is leftover debug instrumentation.
Fix: Remove all code between // #region agent log and // #endregion comments.
6. OpportunityCard hardcoded shadows
File: apps/landing/src/app/components/job-card.tsx
Uses inline shadow-[...] with raw CSS var references instead of the shadow-card token:
shadow-[0px_0px_0px_1px_var(--color-gray-200),0px_1px_3px_0px_rgba(0,0,0,0.1),0px_1px_2px_-1px_rgba(0,0,0,0.1)]Fix: Use the shared Card component, or at minimum apply the shadow-card token which provides the same visual effect.
7. LoadingSpinner / ErrorState hardcoded colors
File: packages/shared/components/ui/loading-spinner.tsx
Uses border-gray-300, border-t-gray-900, text-gray-600, text-red-600, text-gray-700, and bg-gray-900 instead of semantic tokens.
Fix: Replace with border-muted, border-foreground, text-muted-foreground, text-destructive, text-foreground, and bg-foreground respectively. Also use shared Button in ErrorState instead of a raw <button>.
8. FilterDropdown custom implementation
File: apps/landing/src/app/components/filter-dropdown.tsx
A fully custom dropdown with manual click-outside handling, no keyboard navigation, and no ARIA attributes.
Fix: Rebuild using Popover + a simple list (or Command for search support). This would gain:
- Keyboard navigation (arrow keys, Escape, Enter)
- Proper ARIA roles and focus management
- Consistent animation and styling
- Reduced code (~100 lines vs ~50)
Summary
| # | Issue | Severity | Effort |
|---|---|---|---|
| 1 | ShaderGradientBackground duplicate | High | Low — move file, update imports |
| 2 | ApplicationForm raw HTML | High | Medium — replace ~20 elements |
| 3 | CandidateInfoPage minimal shared UI | Medium | Low — swap containers and labels |
| 4 | ProsperChatPanel custom UI | Low | Medium — incremental adoption |
| 5 | SearchInput debug logging | High | Trivial — delete code |
| 6 | OpportunityCard hardcoded shadows | Low | Low — swap to Card or token |
| 7 | LoadingSpinner hardcoded colors | Medium | Low — swap class names |
| 8 | FilterDropdown accessibility | Medium | Medium — rebuild with Popover |