https://www.lesarconsults.org/
1. High-Level System Overview
The website code is hosted on GitHub in the repository below. Kindly email [email protected] for access to this repository.
1.1 What the Website Does
Lesar Consults is a professional consultancy firm website serving two primary purposes:
Public-facing platform: Showcases services, team, projects, and resources for potential clients and partners
Admin dashboard: Enables content management, lead tracking, and resource publishing
1.2 Core Features
Seven specialized consultancy services with detailed pages
Individual team member profiles with education, expertise, and project history
Featured and archived projects with metrics and achievements
Gated and ungated downloadable resources (reports, tools, case studies)
Multi-step form with file uploads and email notifications
Lead management, resource editing, analytics overview
Public Users:
Admin Users:
1.4 Architecture Diagram
2. Technology Stack
2.1 Frontend Framework
Build tool and dev server
Why React + Vite: Fast development iteration with HMR, excellent TypeScript support, and optimised production builds.
2.2 Styling System
Pre-built component library
Design System Colors (from index.css):
--navy: 227 57% 19% (#162356) - Primary brand color
--cream: 37 65% 91% (#FAEED4) - Secondary background
--dark-red: 0 50% 33% (#8B1E1E) - Accent color
Routes are defined in App.tsx with protected routes using ProtectedRoute component.
2.4 Backend Services (Supabase)
Leads, resources, profiles tables
File uploads (leads-uploads, resources buckets)
Signed URLs, email forwarding
2.5 Email System
Edge function send-lead-email forwards lead data to an external webhook (n8n on Railway)
Non-blocking: Email failures don't prevent form submission
Frontend hosting with analytics
Configuration files: vercel.json, public/_redirects
3. Frontend Architecture
3.1 Folder Structure
3.2 Component Categories
Page Components (src/pages/):
Full-page layouts with SEO metadata
Compose multiple UI components
Layout Components:
Navbar.tsx: Responsive navigation with dropdown menus
Footer.tsx: Site footer with newsletter signup
AdminLayout.tsx: Admin sidebar and header
Feature Components:
ContactWizard.tsx: Multi-step form orchestrator
ResourceEditor/index.tsx: Rich text editor for resources
UI Primitives (src/components/ui/):
Button, Card, Dialog, Input, etc.
Built on Radix UI primitives
3.3 Styling Conventions
4. Page-by-Page Breakdown
4.1 Home Page (/)
File: src/pages/Index.tsx
Components:
Hero: Full-width hero with CTA buttons
PartnersMarquee: Animated logo carousel
ServicesStrip: Service overview cards
Counters: Animated impact statistics
FeaturedCase: Highlighted project
ResourcesGrid: Latest resources preview
WhyChoose: Value propositions
Data Source: Static imports, Supabase for resources
4.2 About Page (/about)
File: src/pages/About.tsx
Components:
AboutHero: Hero with headline from JSON
ValuesGrid: Company values cards
ApproachTimeline: Methodology steps
Image3DCarousel: Work showcase
QASection: Quality assurance points
PartnersMarquee: Client logos
Data Source: src/data/about.json
4.3 Services Page (/services)
File: src/pages/Services.tsx
Features:
Service grid with alternating layouts
Icon mapping for each service type
Links to individual service detail pages
Data Source: src/data/services.json
4.4 Team Page (/team)
File: src/pages/Team.tsx
Components:
TeamGrid: Grid of team member cards
Timeline: Company milestones
Links to individual member profiles
Data Source: src/data/team.json, src/data/milestones.json
4.5 Projects Page (/projects)
File: src/pages/Projects.tsx
Features:
Featured projects with full details
Additional projects in card grid
Metrics and achievements display
Download button for certain projects
Data Source: src/data/projects.json
4.6 Resources Page (/resources)
File: src/pages/Resources.tsx
Features:
Search and filter functionality
Resource cards with thumbnails
Data Source: Supabase resources table
4.7 Contact Page (/contact)
File: src/pages/Contact.tsx
Contains ContactWizard component (detailed in Section 5).
4.8 Admin Dashboard (/admin/dashboard)
File: src/pages/admin/AdminDashboard.tsx
Features:
Statistics cards (resources, leads, downloads)
Data Source: Supabase queries on mount
4.9 Admin Leads (/admin/leads)
File: src/pages/admin/AdminLeads.tsx
Features:
Lead table with search/filter
Export to PDF, CSV, Excel
Lead detail modal with file attachments
Delete with cascade (files + records)
5.1 Wizard Structure
Main Component: src/components/contact/ContactWizard.tsx
Step Components (src/components/contact/steps/):
Email and phone with country code
Service selection and project description
Budget, timeframe, file uploads
5.2 State and Validation
Form State Shape (TypeScript interface):
Validation Rules (isStepValid() function):
Valid email regex + phone length > 0
At least one service + description filled
Submission Guards:
isSubmitting state prevents double-submission
isSubmitted flag disables button after success
5.3 Submission Flow (End-to-End)
Submit Request: create lead record
User clicks "Submit Request".
Generate client-side UUID for lead_id.
INSERT into leads table (lead record stored).
Upload files (for each file)
Request signed upload URL from Edge Function (create-signed-url).
PUT file directly to the signed upload URL.
Request signed download URL from Edge Function (get-signed-download-url).
INSERT a record into leads_uploads with file_path (and store signed URL as file_url if needed).
Post-submit notifications and UX
Invoke send-lead-email Edge Function (non-blocking).
Show success toast to user.
Navigate to SuccessOptions component.
Error Handling:
File upload failures are logged but don't block submission.
Email failures are caught and logged silently.
Database errors show a user-friendly toast.
6. Supabase Database Schema
leads - Contact form submissions
leads_uploads - File attachments
Storage path for deletion
resources - Content items
article/case_study/report/tool/download
profiles - Admin users
UUID (PK, FK to auth.users)
6.2 Relationships
7. Supabase Storage and Signed URLs
7.1 Why Signed URLs
Security: Prevent direct bucket access
Expiration: URLs expire after 1 hour
Audit Trail: Track who requested access
RLS Bypass: Service role generates URLs server-side
7.2 Upload Flow
Request signed upload URL
Client: POST /functions/v1/create-signed-url
Body: { bucket: "leads-uploads", filename: "doc.pdf" }
Edge Function generates upload URL
Edge Function: createSignedUploadUrl(object_path, 3600) (service role). Response: { upload_url: "...", object_path: "leads/12345_doc.pdf" }
Client uploads file
Client: PUT file directly to upload_url.
Storage: File saved to bucket at returned object_path.
7.3 Download Flow
Request signed download URL
Client: POST /functions/v1/get-signed-download-url
Body: { bucket: "leads-uploads", object_path: "leads/12345_doc.pdf" }
Edge Function returns signed URL
Edge Function: createSignedUrl(object_path, 3600)
Response: { signed_download_url: "..." }
Client uses signed URL
Client: Open signed_download_url in new tab (or link for admin).
7.4 File Path Generation
8. Supabase Edge Functions
8.1 create-signed-url
Purpose: Generate pre-signed upload URL
Location: supabase/functions/create-signed-url/index.ts
Input:
Output:
Called: During ContactWizard file upload step
8.2 get-signed-download-url
Purpose: Generate pre-signed download URL
Location: supabase/functions/get-signed-download-url/index.ts
Input:
Output:
Called: During file upload (for record) and admin file viewing
8.3 send-lead-email
Purpose: Forward lead data to email notification service
Location: supabase/functions/send-lead-email/index.tsx
Flow:
Receive lead payload from client.
Forward to RAILWAY_WEBHOOK_URL (n8n) for processing.
n8n sends email via configured provider.
Called: After successful lead insert (non-blocking)
9. Email System
9.1 Architecture
9.2 Template Mapping
The lead data object passed to the webhook contains:
name, email, organization, role
interested_in, other_service
message, budget, timeframe
n8n transforms this into email templates.
9.3 Error Handling
9.4 Non-Blocking Design
Email failures are logged and follow best-effort, they don't prevent:
Lead database record creation
10. Admin Dashboard
10.1 Route Protection
File: src/components/admin/ProtectedRoute.tsx
Logic (stepper):
Check AuthContext loading state.
If loading > 200ms, show skeleton/loading UI.
If not loading and no user, redirect to /admin/login.
If requireAdmin prop is true and !isAdmin, show "Access Denied".
Otherwise, render children.
10.2 Authentication Flow
File: src/contexts/AuthContext.tsx
Flow (stepper):
On mount: supabase.auth.getSession() to initialize session.
Listen to onAuthStateChange() for auth updates.
On user change: call checkAdminStatus(userId) which queries profiles table for is_admin flag.
Expose context values: user, session, isAdmin, signIn, signOut.
10.3 Lead Data Access
AdminLeads.tsx:
File Attachment Access:
10.4 Export Features
11. JSON-Driven Content
File: src/data/team.json
Structure:
Rendering:
11.2 Services Page
File: src/data/services.json
Structure:
11.3 Projects Page
File: src/data/projects.json
Rendering:
11.4 About Page
File: src/data/about.json
Contains: hero content, whoWeAre paragraphs, values, approach steps, qualityAssurance, carousel slides.
11.5 Benefits of JSON-Driven Content
No database dependency for static content
Version controlled content changes
Easy content updates without code changes
Type-safe with TypeScript interfaces
12. Routing and Access Control
12.1 Route Definitions
File: src/App.tsx
12.2 Authentication Checks
ProtectedRoute wraps admin pages
requireAdmin prop enforces is_admin flag check
Unauthenticated users redirect to /admin/login
Non-admin authenticated users see "Access Denied"
12.3 Redirect Behavior
Unauthenticated + admin route
Authenticated + /admin/login
Redirect to /admin/dashboard
Not admin + requireAdmin route
13. Environment Configuration
13.1 Frontend Variables (Vite)
VITE_SUPABASE_FUNCTIONS_URL
Usage: import.meta.env.VITE_SUPABASE_URL
13.2 Backend Secrets (Edge Functions)
Auto-injected Supabase URL
SUPABASE_SERVICE_ROLE_KEY
Auto-injected service role key
n8n email webhook endpoint
Usage: Deno.env.get("RAILWAY_WEBHOOK_URL")
13.3 Client Configuration
File: src/integrations/supabase/client.ts
14. Error Handling and UX Safeguards
14.1 Client-Side Validation
Per-step validation in ContactWizard
14.2 Backend Error Handling
14.3 Graceful Failure Strategies
File upload failures don't block form submission
Email failures are logged but silent to user
Network errors show retry-friendly messages
404 pages for missing resources/team members
14.4 User Feedback Mechanisms
"No results found" messages
15. Maintenance and Extensibility
15.1 Adding New Pages
Create page component in src/pages/
Add to navigation in Navbar.tsx and Footer.tsx
Include SEO metadata with react-helmet-async
15.2 Adding New Services
Add entry to src/data/services.json
ServiceDetail page auto-renders based on slug
Update Navbar dropdown if needed
Create new step component in src/components/contact/steps/
Add to step renderer in ContactWizard
Update totalSteps constant
Add validation logic to isStepValid()
Update FormData interface
15.4 Updating JSON Content
Edit relevant JSON file in src/data/
TypeScript will catch schema mismatches
Changes take effect on next build/deploy
15.5 Adding Database Tables
Create migration in supabase/migrations/
Update TypeScript types in src/integrations/supabase/types.ts
Add RLS policies for security
Test locally before deploying
15.6 Code Quality Guidelines
Run npm run lint before committing
Run npm run typecheck for type safety
Follow existing component patterns
Use shadcn/ui components when possible
Keep components under 300 lines
Appendix A: Key File Reference
Route definitions and provider setup
Authentication state management
src/contexts/AuthContext.tsx
Supabase client configuration
src/integrations/supabase/client.ts
Database TypeScript types
src/integrations/supabase/types.ts
src/components/contact/ContactWizard.tsx
src/components/admin/ProtectedRoute.tsx
Design system and global styles