26 KiB
Cabo Pickleball Club Adaptation - Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Adapt SmashPoint from a Spanish-language padel club system to an English-language pickleball club system branded for Cabo Pickleball Club.
Architecture: Direct string replacement across ~30 files. No structural changes to components, API routes, or database schema. Hide unused features (Tournaments, POS) by removing sidebar links. Update color palette and seed data.
Tech Stack: Next.js 14, TailwindCSS, Prisma, TypeScript (all unchanged)
Task 1: Update Color Palette
Files:
- Modify:
apps/web/tailwind.config.ts
Step 1: Replace primary color scale
Change primary from dark navy (#1E3A5F) to Cabo blue (#2990EA). Change accent from green (#22C55E) to amber (#F59E0B).
Replace the entire colors object in tailwind.config.ts with:
primary: {
50: "#E8F4FD",
100: "#C5E3FA",
200: "#9DCEF6",
300: "#75B9F2",
400: "#4DA4EE",
500: "#2990EA",
600: "#2177C8",
700: "#195DA6",
800: "#124484",
900: "#0B2B62",
DEFAULT: "#2990EA",
},
accent: {
50: "#FEF7EC",
100: "#FDEACC",
200: "#FBD89D",
300: "#F9C66E",
400: "#F7B43F",
500: "#F59E0B",
600: "#D48509",
700: "#A36807",
800: "#724A05",
900: "#412B03",
DEFAULT: "#F59E0B",
},
Step 2: Build to verify colors compile
Run: cd /root/Padel && pnpm build 2>&1 | tail -5
Expected: Build succeeds
Step 3: Commit
git add apps/web/tailwind.config.ts
git commit -m "feat: update color palette to Cabo blue (#2990EA) and amber accent"
Task 2: Update Branding (Landing, Login, Sidebar, Metadata)
Files:
- Modify:
apps/web/app/layout.tsx - Modify:
apps/web/app/page.tsx - Modify:
apps/web/app/(auth)/login/page.tsx - Modify:
apps/web/components/layout/sidebar.tsx - Modify:
apps/web/app/icon.svg
Step 1: Update root layout metadata
In apps/web/app/layout.tsx:
- title:
"Cabo Pickleball Club | SmashPoint" - description:
"Court Management System for Cabo Pickleball Club" - keywords:
["pickleball", "cabo", "courts", "bookings", "club"] - authors:
[{ name: "SmashPoint" }] - Change
<html lang="es">to<html lang="en">
Step 2: Update landing page
In apps/web/app/page.tsx:
- Logo container: change
bg-amber-500tobg-primary - h1:
"Cabo Pickleball Club"(instead of "SmashPoint") - Add subtitle:
<p className="text-sm text-primary-400">Powered by SmashPoint</p> - Tagline:
"Court Management System"(replacing Spanish) - Change "Reservas" button text to
"Book a Court"and href to/bookings
Step 3: Update login page
In apps/web/app/(auth)/login/page.tsx:
- Logo containers: change
bg-amber-500/20andborder-amber-400/30tobg-primary/20andborder-primary-300/30 - SVG fill colors: change
#FBBF24tocurrentColorand addclassName="text-white" - Desktop h1:
"Cabo Pickleball Club" - Add after h1:
<p className="text-sm text-primary-300 mb-2">Powered by SmashPoint</p> - Desktop tagline:
"Court Management System" - Feature 1:
"Court Bookings"/"Manage your courts and schedules" - Feature 2:
"Player Management"/"Memberships and player profiles" - Feature 3:
"Reports & Analytics"/"Analyze your club's performance" - Mobile h1:
"Cabo Pickleball Club" - Mobile tagline:
"Court Management System" - Footer:
"© {year} SmashPoint. All rights reserved."
Step 4: Update sidebar
In apps/web/components/layout/sidebar.tsx:
- Logo container: change
bg-amber-500tobg-primary - Brand text:
"Cabo Pickleball"(instead of "SmashPoint") - Remove Tournaments entry:
{ label: 'Torneos', href: '/tournaments', icon: Trophy } - Remove POS entry:
{ label: 'Ventas', href: '/pos', icon: ShoppingCart } - Remove Trophy and ShoppingCart imports from lucide-react
- Translate remaining labels:
'Reservas'→'Bookings''Clientes'→'Players''Membresías'→'Memberships''Reportes'→'Reports''Configuración'→'Settings'
Step 5: Update favicon
In apps/web/app/icon.svg:
- Change
fill="#F59E0B"tofill="#2990EA"(rect background)
Step 6: Commit
git add apps/web/app/layout.tsx apps/web/app/page.tsx apps/web/app/\(auth\)/login/page.tsx apps/web/components/layout/sidebar.tsx apps/web/app/icon.svg
git commit -m "feat: rebrand to Cabo Pickleball Club with English UI"
Task 3: Translate Auth & Layout Components
Files:
- Modify:
apps/web/components/auth/login-form.tsx - Modify:
apps/web/components/layout/header.tsx
Step 1: Translate login-form.tsx
All Spanish strings → English:
'El correo electrónico es requerido'→'Email is required''Ingresa un correo electrónico válido'→'Enter a valid email address''La contraseña es requerida'→'Password is required''La contraseña debe tener al menos 6 caracteres'→'Password must be at least 6 characters''Credenciales inválidas...'→'Invalid credentials. Please check your email and password.''Ocurrió un error al iniciar sesión...'→'An error occurred while signing in. Please try again.'Iniciar Sesión(heading) →Sign InIngresa tus credenciales para acceder al sistema→Enter your credentials to access the systemCorreo Electrónico→Email"correo@ejemplo.com"→"email@example.com"Contraseña→PasswordRecordarme→Remember me¿Olvidaste tu contraseña?→Forgot your password?Iniciando sesión...→Signing in...- Button:
'Iniciar Sesión'→'Sign In'
Step 2: Translate header.tsx
'Usuario'→'User'"Cerrar sesión"→"Log out"
Step 3: Commit
git add apps/web/components/auth/login-form.tsx apps/web/components/layout/header.tsx
git commit -m "feat: translate auth and layout components to English"
Task 4: Translate Dashboard Page & Components
Files:
- Modify:
apps/web/app/(admin)/dashboard/page.tsx - Modify:
apps/web/components/dashboard/quick-actions.tsx - Modify:
apps/web/components/dashboard/occupancy-chart.tsx - Modify:
apps/web/components/dashboard/recent-bookings.tsx - Modify:
apps/web/components/dashboard/stat-card.tsx
Step 1: Translate dashboard/page.tsx
"Error al cargar los datos del dashboard"→"Error loading dashboard data""Error desconocido"→"Unknown error""Usuario"→"User"`Bienvenido, ${userName}`→`Welcome, ${userName}`Panel de administracion→Admin panel`Mostrando: ${selectedSite.name}`→`Showing: ${selectedSite.name}`"Reservas Hoy"→"Today's Bookings""Ingresos Hoy"→"Today's Revenue""Ocupacion"→"Occupancy""Miembros Activos"→"Active Members""Reservas Pendientes"→"Pending Bookings""Torneos Proximos"→"Upcoming Events"(generic since tournaments hidden)
Step 2: Translate quick-actions.tsx
"Nueva Reserva"→"New Booking""Crear una nueva reserva de cancha"→"Create a new court booking""Abrir Caja"→"Open Register""Iniciar turno de caja registradora"→"Start cash register shift""Nueva Venta"→"New Sale""Registrar venta en el punto de venta"→"Record a point of sale transaction""Registrar Cliente"→"Register Player""Agregar un nuevo cliente al sistema"→"Add a new player to the system"Acciones Rapidas→Quick Actions
Step 3: Translate occupancy-chart.tsx
Ocupacion de Canchas→Court Occupancy(appears twice)No hay canchas configuradas→No courts configured{court.occupancyPercent}% ocupado→{court.occupancyPercent}% bookeddisponible→availableOcupado→BookedDisponible→Available
Step 4: Translate recent-bookings.tsx
"Pendiente"→"Pending""Confirmada"→"Confirmed""Completada"→"Completed""Cancelada"→"Cancelled""No asistio"→"No Show"Reservas de Hoy→Today's BookingsVer todas→View allNo hay reservas para hoy→No bookings for today"Sin cliente"→"Walk-in"
Step 5: Translate stat-card.tsx
vs ayer→vs yesterday
Step 6: Commit
git add apps/web/app/\(admin\)/dashboard/page.tsx apps/web/components/dashboard/
git commit -m "feat: translate dashboard page and components to English"
Task 5: Translate Bookings Page & Components
Files:
- Modify:
apps/web/app/(admin)/bookings/page.tsx - Modify:
apps/web/components/bookings/booking-calendar.tsx - Modify:
apps/web/components/bookings/booking-dialog.tsx
Step 1: Translate bookings/page.tsx
Reservas→BookingsGestiona las reservas de canchas...→Manage court bookings. Select a time slot to create or view a booking.
Step 2: Translate booking-calendar.tsx
All Spanish strings → English (12 strings):
- Error messages:
"Error al cargar..."→"Error loading..." Reintentar→RetryCalendario→CalendarHoy→TodayCargando disponibilidad...→Loading availability...No hay canchas disponibles.→No courts available."Interior"→"Indoor","Exterior"→"Outdoor"No disponible→Not availableNo hay horarios disponibles para este día.→No time slots available for this day.
Step 3: Translate booking-dialog.tsx
All Spanish strings → English (35 strings):
- Form labels:
Buscar Cliente→Search Player,Cliente seleccionado:→Selected player: - Status labels:
"Confirmada"→"Confirmed","Pendiente"→"Pending", etc. - Payment types:
"Efectivo"→"Cash","Tarjeta"→"Card","Transferencia"→"Transfer","Membresia"→"Membership","Gratuito"→"Free" - Field labels:
Cancha:→Court:,Fecha:→Date:,Hora:→Time:,Precio:→Price: - Buttons:
"Crear Reserva"→"Create Booking","Cancelar Reserva"→"Cancel Booking" - Error messages: all
"Error al..."→"Error..." - Placeholders:
"Nombre, email o telefono..."→"Name, email or phone..." - Note: Change all instances of "Cliente" to "Player" in this file
Step 4: Commit
git add apps/web/app/\(admin\)/bookings/page.tsx apps/web/components/bookings/
git commit -m "feat: translate bookings page and components to English"
Task 6: Translate Clients Page (rename to Players)
Files:
- Modify:
apps/web/app/(admin)/clients/page.tsx
Step 1: Translate all strings
17 Spanish strings → English. Key translations:
Clientes→PlayersGestiona los clientes de tu centro→Manage your club's playersNuevo Cliente→New Player"Total Clientes"→"Total Players""Con Membresia"→"With Membership""Nuevos Este Mes"→"New This Month""Buscar por nombre, email o telefono..."→"Search by name, email or phone...""Todos"→"All","Con membresia"→"With membership","Sin membresia"→"Without membership"- All error messages: translate from Spanish to English
- Confirmation dialog: translate to English
Step 2: Commit
git add apps/web/app/\(admin\)/clients/page.tsx
git commit -m "feat: translate clients/players page to English"
Task 7: Translate Memberships Page & Components
Files:
- Modify:
apps/web/app/(admin)/memberships/page.tsx - Modify:
apps/web/components/memberships/plan-card.tsx - Modify:
apps/web/components/memberships/plan-form.tsx
Step 1: Translate memberships/page.tsx (30 strings)
Membresias→MembershipsGestiona planes y membresias de tus clientes→Manage plans and memberships for your players- Status filters:
"Todos"→"All","Activas"→"Active","Expiradas"→"Expired","Canceladas"→"Cancelled" - Stats:
Membresias Activas→Active Memberships,Por Expirar→Expiring Soon,Planes Activos→Active Plans,Total Suscriptores→Total Subscribers Planes de Membresia→Membership PlansNuevo Plan→New PlanCargando planes...→Loading plans...No hay planes→No plans,Crea tu primer plan de membresia→Create your first membership planCrear Plan→Create PlanAsignar Membresia→Assign Membership"Buscar por nombre de cliente..."→"Search by player name...""Todos los planes"→"All plans"- All error messages and confirmation dialogs → English
Step 2: Translate plan-card.tsx (11 strings)
suscriptor/suscriptores→subscriber/subscribersmes/meses→month/monthshoras gratis→free hoursde cancha al mes→of court time per monthdescuento→discounten reservas adicionales→on additional bookingsen tienda→in storeBeneficios adicionales:→Additional benefits:Editar→Edit,Eliminar→Delete
Step 3: Translate plan-form.tsx (25 strings)
- Duration labels:
"1 mes"→"1 month","3 meses"→"3 months", etc. - Validation: all Spanish error messages → English
- Form title:
"Nuevo Plan de Membresia"→"New Membership Plan","Editar Plan"→"Edit Plan" - Labels:
Nombre del Plan *→Plan Name *,Descripcion→Description,Precio *→Price *,Duracion→Duration - Section headers:
Beneficios→Benefits,Horas Gratis de Cancha (por mes)→Free Court Hours (per month),Descuento en Reservas (%)→Booking Discount (%),Descuento en Tienda (%)→Store Discount (%) - Buttons:
Cancelar→Cancel,Guardando...→Saving...,"Crear Plan"→"Create Plan","Guardar Cambios"→"Save Changes" - Placeholders: translate to English equivalents
Step 4: Commit
git add apps/web/app/\(admin\)/memberships/page.tsx apps/web/components/memberships/
git commit -m "feat: translate memberships page and components to English"
Task 8: Translate Reports Page
Files:
- Modify:
apps/web/app/(admin)/reports/page.tsx
Step 1: Translate all strings (28 strings)
Reportes→ReportsAnálisis y estadísticas del negocio→Business analysis and statistics- Period filters:
"Última semana"→"Last week","Último mes"→"Last month","Último trimestre"→"Last quarter","Último año"→"Last year" Exportar→Export- KPIs:
"Ingresos Totales"→"Total Revenue","Reservas"→"Bookings","Clientes Activos"→"Active Players","Ocupación Promedio"→"Average Occupancy" - Charts:
Ingresos por Día→Revenue by Day,Reservas→Bookings,Ventas→Sales Productos Más Vendidos→Top Selling Productsunidades→unitsRendimiento por Cancha→Court Performance- Table headers:
Cancha→Court,Sede→Site,Reservas→Bookings,Ingresos→Revenue,Ocupación→Occupancy - Day names:
"Lun"→"Mon","Mar"→"Tue","Mié"→"Wed","Jue"→"Thu","Vie"→"Fri","Sáb"→"Sat","Dom"→"Sun" - Insights:
Mejor Día→Best Day,Sábado→Saturday,en ingresos promedio→in average revenue,Hora Pico→Peak Hour,Ticket Promedio→Average Ticket vs período anterior→vs previous period- Rename "Cancha" to "Court" in mock data court names (lines 110-115)
- Rename "Raqueta alquiler" to "Paddle Rental" in mock products (line 106)
- Rename "Pelotas HEAD" to "Pickleballs" in mock products (line 105)
Step 2: Commit
git add apps/web/app/\(admin\)/reports/page.tsx
git commit -m "feat: translate reports page to English"
Task 9: Translate Settings Page
Files:
- Modify:
apps/web/app/(admin)/settings/page.tsx
Step 1: Translate all Spanish strings
Key translations (the file has ~60 Spanish strings):
Configuración→SettingsAdministra la configuración del sistema→Manage system settingsConfiguración guardada correctamente→Settings saved successfully- Tab labels:
Organización→Organization,Sedes→Sites,Canchas→Courts,Usuarios→Users - Organization form:
Nombre de la organización→Organization name,Email de contacto→Contact email,Teléfono→Phone,Moneda→Currency,Zona horaria→Timezone - Currency options:
"MXN - Peso Mexicano","USD - Dólar","EUR - Euro"→"MXN - Mexican Peso","USD - US Dollar","EUR - Euro" - Timezone options:
"Ciudad de México"→"Mexico City", etc. - Booking config:
Duración por defecto (minutos)→Default duration (minutes),Anticipación mínima (horas)→Minimum notice (hours),Anticipación máxima (días)→Maximum advance (days),Horas para cancelar→Cancellation window (hours) - Buttons:
Guardar cambios→Save changes,Guardando...→Saving... - Sites section:
Sedes→Sites,Nueva Sede→New Site,Activa/Inactiva→Active/Inactive - Courts section:
Canchas→Courts,Nueva Cancha→New Court,Cancha→Court,Sede→Site,Tipo→Type,Precio/hora→Price/hour,Estado→Status,Acciones→Actions - Court types:
Indoorstays,Outdoorstays,"Techada"→"Covered" - Court status:
"Activa"→"Active","Mantenimiento"→"Maintenance","Inactiva"→"Inactive" - Users section:
Usuarios→Users,Nuevo Usuario→New User,Usuario→User,Rol→Role,"Super Admin"stays,"Admin Sede"→"Site Admin","Staff"stays - Messages:
"Cancha actualizada"→"Court updated","Cancha creada"→"Court created","Cancha eliminada"→"Court deleted", etc. - Site form:
"Editar Sede"→"Edit Site","Nueva Sede"→"New Site",Nombre→Name,Dirección→Address,Teléfono→Phone,Hora apertura→Opening time,Hora cierre→Closing time,Sede activa→Site active - Court form:
"Editar Cancha"→"Edit Court","Nueva Cancha"→"New Court",Precio hora pico→Peak hour price - All
Cancelar→Cancel,Guardar→Save,Guardando...→Saving... - Error/success:
"Sede actualizada"→"Site updated","Sede creada"→"Site created","Error al guardar..."→"Error saving...","Error de conexión"→"Connection error" - Confirmation:
"¿Estás seguro de eliminar esta cancha?"→"Are you sure you want to delete this court?" "Todas"→"All"(for site assignment)"Activo"/"Inactivo"→"Active"/"Inactive"(user status)
Step 2: Commit
git add apps/web/app/\(admin\)/settings/page.tsx
git commit -m "feat: translate settings page to English"
Task 10: Translate API Error Messages
Files:
- Modify:
apps/web/app/api/bookings/route.ts - Modify:
apps/web/app/api/clients/route.ts - Check and modify any other API routes with Spanish strings
Step 1: Translate bookings/route.ts
'No autorizado'→'Unauthorized''Error al obtener las reservas'→'Error fetching bookings''Datos de reserva inválidos'→'Invalid booking data''Cancha no encontrada o no pertenece a su organización'→'Court not found or does not belong to your organization''La cancha no está disponible para reservas'→'The court is not available for bookings''Cliente no encontrado o no pertenece a su organización'→'Client not found or does not belong to your organization''Ya existe una reserva en ese horario...'→'A booking already exists for that time slot. Please select another time.''Error al crear la reserva'→'Error creating booking'
Step 2: Scan and translate all other API routes
Search for Spanish strings in all files under apps/web/app/api/ and translate them.
Run: grep -rn "'" apps/web/app/api/ | grep -i "[áéíóúñ]\|Error al\|No autorizado\|no encontrad" to find remaining Spanish.
Step 3: Commit
git add apps/web/app/api/
git commit -m "feat: translate API error messages to English"
Task 11: Update Seed Data for Cabo Pickleball
Files:
- Modify:
apps/web/prisma/seed.ts
Step 1: Update organization
name: 'Cabo Pickleball Club',
slug: 'cabo-pickleball-club',
settings: {
currency: 'MXN',
timezone: 'America/Mazatlan',
language: 'en',
},
Step 2: Update site (single site instead of 3)
Replace the 3 sites with 1:
const sitesData = [
{
name: 'Corridor Courts',
slug: 'corridor-courts',
address: 'Corridor area, Cabo San Lucas, BCS',
phone: '+52-624-151-5455',
email: 'topdogcabo@yahoo.com',
timezone: 'America/Mazatlan',
openTime: '07:00',
closeTime: '22:00',
},
];
Step 3: Update courts (6 outdoor courts)
Replace the 2-per-site pattern with 6 courts for the single site:
const courtData = [
{ name: 'Court 1', type: CourtType.OUTDOOR, status: CourtStatus.AVAILABLE, pricePerHour: 300, description: 'Outdoor court with night lighting', features: ['Night lighting', 'Court dividers'], displayOrder: 1 },
{ name: 'Court 2', type: CourtType.OUTDOOR, status: CourtStatus.AVAILABLE, pricePerHour: 300, description: 'Outdoor court with night lighting', features: ['Night lighting', 'Court dividers'], displayOrder: 2 },
{ name: 'Court 3', type: CourtType.OUTDOOR, status: CourtStatus.AVAILABLE, pricePerHour: 300, description: 'Outdoor court with night lighting', features: ['Night lighting', 'Court dividers'], displayOrder: 3 },
{ name: 'Court 4', type: CourtType.OUTDOOR, status: CourtStatus.AVAILABLE, pricePerHour: 300, description: 'Outdoor court with night lighting', features: ['Night lighting', 'Court dividers'], displayOrder: 4 },
{ name: 'Court 5', type: CourtType.OUTDOOR, status: CourtStatus.AVAILABLE, pricePerHour: 300, description: 'Outdoor court with night lighting', features: ['Night lighting', 'Court dividers'], displayOrder: 5 },
{ name: 'Court 6', type: CourtType.OUTDOOR, status: CourtStatus.AVAILABLE, pricePerHour: 300, description: 'Outdoor court with night lighting', features: ['Night lighting', 'Court dividers'], displayOrder: 6 },
];
Step 4: Update admin user
email: 'ivan@horuxfin.com',
password: await bcrypt.hash('Aasi940812', 10),
Remove the site admin users (single-site operation).
Step 5: Update product categories and products
Change to pickleball-relevant items:
- Category:
'Equipment'→'Pickleball equipment and accessories' - Products:
'Pickleballs'(Franklin X-40),'Paddle Rental','Paddle Grip' - Category:
'Drinks'stays but translate names to English - Remove
'Alquiler'category (merge rental into Equipment)
Step 6: Update membership plans
const membershipPlansData = [
{
name: 'Day Pass',
description: 'Single day access to all courts',
price: 300,
durationMonths: 1,
courtHours: 0,
discountPercent: 0,
benefits: ['Full day access', 'All courts', 'Night play included'],
},
{
name: '10-Day Pass',
description: '10 visits, any time of day',
price: 2500,
durationMonths: 3,
courtHours: 10,
discountPercent: 15,
benefits: ['10 day passes', 'Valid any time', 'Save vs single day pass'],
},
{
name: '10-Morning Pass',
description: '10 morning sessions (7am-12pm)',
price: 2000,
durationMonths: 3,
courtHours: 10,
discountPercent: 10,
benefits: ['10 morning passes', '7:00 AM - 12:00 PM only', 'Best value for morning players'],
},
{
name: 'Monthly Individual',
description: 'Unlimited monthly access for one player',
price: 4000,
durationMonths: 1,
courtHours: 30,
discountPercent: 25,
benefits: ['Unlimited court access', 'Priority booking', 'All time slots'],
},
{
name: 'Monthly Family',
description: 'Unlimited monthly access for up to 4 family members',
price: 6500,
durationMonths: 1,
courtHours: 60,
discountPercent: 30,
benefits: ['Up to 4 family members', 'Unlimited court access', 'Priority booking', 'All time slots'],
},
];
Step 7: Update seed summary output
Change all console.log messages to English and update credential display:
Login credentials:
Admin: ivan@horuxfin.com / Aasi940812
Step 8: Commit
git add apps/web/prisma/seed.ts
git commit -m "feat: update seed data for Cabo Pickleball Club"
Task 12: Sport Terminology Sweep
Files:
- All
.tsx,.tsfiles containing "padel", "pádel", "cancha", "raqueta", "pelota"
Step 1: Global search and replace
Run targeted searches and replace remaining sport terms:
grep -rn "padel\|pádel\|Padel\|Pádel" apps/web/ --include="*.tsx" --include="*.ts"— replace with "pickleball"grep -rn "cancha" apps/web/ --include="*.tsx" --include="*.ts"— replace with "court" (should already be done in earlier tasks)grep -rn "raqueta\|Raqueta" apps/web/ --include="*.tsx" --include="*.ts"— replace with "paddle"grep -rn "pelota\|Pelota" apps/web/ --include="*.tsx" --include="*.ts"— replace with "pickleball ball" or "pickleballs"
Step 2: Verify no Spanish sport terms remain
Run: grep -rni "padel\|cancha\|raqueta\|pelota" apps/web/ --include="*.tsx" --include="*.ts"
Expected: No matches (or only in comments/prisma generated code)
Step 3: Commit if any changes
git add -A
git commit -m "feat: replace all padel terminology with pickleball"
Task 13: Build, Verify & Final Commit
Step 1: Clean build
rm -rf apps/web/.next .turbo
pnpm build
Expected: Build succeeds with 0 errors.
Step 2: Verify no Spanish remains in user-facing code
Run: grep -rni "[áéíóúñ]" apps/web/app/ apps/web/components/ --include="*.tsx" --include="*.ts" | grep -v node_modules | grep -v ".next"
Review any remaining Spanish strings and translate.
Step 3: Restart server and verify
fuser -k 3000/tcp 2>/dev/null
sleep 2
cd apps/web && npx next start --port 3000 &
Step 4: Push
git push origin main