Profile Overview
Your lawyer profile is accessed through /lawyer/profile and managed via the ProfilePage.tsx component. It consists of several key sections that clients see when browsing lawyers.
Basic Details
interface ProfileFormData {
first_name : string
last_name : string
bio : string
phone : string
location : string
website : string
avatar_url ?: string
}
Profile Photo
Upload a professional photo using the ProfileAvatarUpload component:
Maximum size: 5MB
Formats: JPG, PNG, WebP
Stored in Supabase Storage bucket: avatars
Auto-resized to square aspect ratio
< ProfileAvatarUpload
avatarUrl = {formData. avatar_url }
onUpload = { async ( url ) => {
await updateProfile ({ avatar_url : url })
}}
disabled = {! isEditing }
/>
Professional Bio
Write a compelling bio (recommended 150-500 characters): “Cuéntanos sobre tu experiencia, especialidades y forma de trabajo. Esta información ayuda a los usuarios a conocerte mejor y tomar una decisión informada al agendar.”
The bio is displayed prominently on your public profile at /abogado/{slug}-{id}.
Contact Information
Phone : Chilean format +56 9 1234 5678
Location : City, Region (e.g., “Santiago, Región Metropolitana”)
Website : Your professional website (optional)
Specializations
Select one or more areas of legal practice from 18 available specializations:
const availableSpecializations = [
'Derecho Laboral' ,
'Derecho Civil' ,
'Derecho de Familia' ,
'Derecho Penal' ,
'Derecho Comercial' ,
'Derecho Tributario' ,
'Derecho Inmobiliario' ,
'Derecho de Propiedad Intelectual' ,
'Derecho Ambiental' ,
'Derecho Bancario' ,
'Derecho de Consumidor' ,
'Derecho Migratorio' ,
'Derecho Internacional' ,
'Derecho Constitucional' ,
'Derecho Administrativo' ,
'Derecho de Salud' ,
'Derecho de Tecnología' ,
'Derecho Deportivo'
]
Specializations are stored as an array in profiles.specialties and used for:
Client search filtering
Lawyer recommendations
Service categorization
Education & Credentials
Education Fields
University Options
{
education : string // e.g., "Abogado", "Licenciado en Derecho"
university : string // Selected from Chilean universities list
study_start_year : number // e.g., 2010
study_end_year : number // e.g., 2015
certifications ?: string // Additional certifications
bar_association_number : string // Colegio de Abogados number
}
Professional Document Upload
Upload your professional title or certificate:
< DocumentUpload
bucket = "documents"
userId = {user?. id }
onUpload = { async ( url , fileName ) => {
await supabase . auth . updateUser ({
data : {
professional_document : url ,
document_file_name : fileName
}
})
}}
description = "Sube tu título profesional o certificado"
/>
Accepted formats: PDF, JPG, PNG
Max size: 10MB
Stored in documents bucket
Reviewed by admin for verification
Rates & Pricing
Hourly Rate
Set your consultation rate in Chilean Pesos (CLP):
hourly_rate_clp : number // e.g., 50000 ($50,000 CLP)
The hourly rate is displayed on your profile and used for appointment booking calculations.
Configure a fee for direct client contact (second contact onwards):
contact_fee_clp : number // e.g., 10000 ($10,000 CLP)
“Esta tarifa se cobrará a los clientes al realizar el segundo ‘Contactar’ contigo.” The first contact is free; subsequent contacts are charged to prevent spam.
RUT & PJUD Verification
The Chilean RUT is formatted and validated using this algorithm:
const formatRUT = ( rut : string ) : string => {
// Remove non-digit and non-k/K characters
let cleanRut = rut . replace ( / [ ^ \dkK ] / g , '' )
// Extract verification digit
const dv = cleanRut . slice ( - 1 ). toUpperCase ()
let number = cleanRut . slice ( 0 , - 1 )
// Add dots as thousand separators
let formatted = ''
let counter = 0
for ( let i = number . length - 1 ; i >= 0 ; i -- ) {
formatted = number [ i ] + formatted
counter ++
if ( counter === 3 && i > 0 ) {
formatted = '.' + formatted
counter = 0
}
}
return ` ${ formatted } - ${ dv } ` // e.g., "12.345.678-9"
}
PJUD Verification Process
Enter RUT
Input your RUT in the profile form. Format is automatically applied as you type.
Click Verify
Click the “Verificar” button to initiate verification: const handleVerifyRUT = async () => {
const result = await verifyWithPJUD (
formData . rut ,
` ${ formData . first_name } ${ formData . last_name } `
)
if ( result ?. verified ) {
setFormData ( prev => ({
... prev ,
pjud_verified: true
}))
}
}
API Validation
System calls the PJUD scraper: // lib/pjudScraper.ts
const searchUrl = 'https://www.pjud.cl/ajax/Lawyers/search'
const formData = new URLSearchParams ()
formData . append ( 'dni' , rutBody ) // e.g., "12345678"
formData . append ( 'digit' , rutVerifier ) // e.g., "9"
const response = await fetch ( searchUrl , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/x-www-form-urlencoded' ,
},
body: formData . toString ()
})
Result Display
Verification status is shown inline:
✅ Success : Green checkmark with “Verificado con el Poder Judicial de Chile”
❌ Error : Red X with error message
⏳ Verifying : Loading spinner
If the RUT is modified after verification, the pjud_verified flag is reset to false and re-verification is required.
Verification States
type VerificationStatus = 'idle' | 'verifying' | 'success' | 'error'
// Stored in database
interface Profile {
rut : string
pjud_verified : boolean
}
Profile Completion Tracking
The system calculates completion percentage based on filled fields:
// Displayed in ProfileCompletion component
const completionPercentage = calculateProfileCompletion ( profile )
// Breakdown:
// - Basic info (20%): name, email, phone, location
// - Bio (10%): professional description
// - Photo (10%): avatar uploaded
// - Experience (15%): years + specializations
// - Education (15%): degree + university + years
// - Verification (15%): PJUD verified
// - Rates (10%): hourly_rate_clp set
// - Document (5%): professional document uploaded
Aim for 100% completion to maximize visibility in client searches.
Saving Profile Changes
Profile updates are saved to both profiles table and auth.users.user_metadata:
const handleSave = async () => {
const updateData = {
first_name: formData . first_name ?. trim (),
last_name: formData . last_name ?. trim (),
bio: formData . bio ?. trim (),
specialties: selectedSpecializations ,
experience_years: Number ( formData . experience_years ),
hourly_rate_clp: Number ( formData . hourly_rate_clp ),
// ... all other fields
}
await updateProfile ( updateData )
// Auto-save when profile reaches 100%
if ( completionPercentage === 100 && hasChanges ) {
await handleSave ()
}
}
Public Profile View
Clients see your profile at /abogado/{slug}-{id} with:
Profile photo and name
Specializations (as badges)
Bio and experience
Hourly rate
Education details
Verification badge (if PJUD verified)
Available services
Booking button
Preview Your Profile Click “Ver perfil” in the profile page header to view your public-facing profile as clients see it.