Process Nov 28, 2025 13 min read

Technical Analysis of Villa Stuart Healthcare Website

Enterprise search engineering and cross-platform design alignment for a prestigious Italian healthcare facility.

Lushano Perera
Lushano Perera
Author

Executive Summary

Comprehensive modernization of Villa Stuart’s digital presence across two platforms: a complete enterprise search system overhaul for the Italian WordPress site, and a frontend design alignment for the Russian CodeIgniter site. The project involved architecting a sophisticated medical search system with 49 curated configurations, implementing multilingual support, and creating a unified design language across both properties.

Key Achievements

  • 151 commits over 4 months of active development
  • 96/100 code quality score (Gemini AI review)
  • 23 PHP classes in modern PSR-4 architecture
  • 49 curated search configurations for medical queries
  • 400+ medical terminology synonyms
  • Zero breaking changes during 5-week architectural refactor

Project 1: Villa Stuart Italy (villastuart.it)

Technology Stack

LayerTechnologyPurpose
CMSWordPressContent management
SearchRelevanssi PREMIUMEnterprise search engine
MultilingualWPML 4.8.4Italian/English support
Page BuilderElementor ProVisual page construction
Custom FieldsACF ProStructured medical data
CacheRedis 7Object caching
DatabaseMariaDB 10.11Data persistence
RuntimePHP 8.3Server-side processing
ContainerDockerDevelopment environment
AutoloadingComposer PSR-4Modern PHP architecture

The Challenge

Villa Stuart needed a search system that could:

  1. Surface relevant doctors and services for medical queries
  2. Handle complex Italian medical terminology
  3. Support bilingual content (Italian/English)
  4. Prioritize VIP doctors in search results
  5. Prevent content cross-contamination between medical specialties
  6. Maintain fast response times with ~800 indexed posts

Architecture Solution

PSR-4 MU-Plugin Bundle

Consolidated three legacy plugins into a modern, maintainable structure:

villa-stuart/
├── src/
│ ├── Bootstrap/
│ │ └── MuPlugin.php # Singleton bootstrapper
│ ├── Support/
│ │ ├── Logger.php # Centralized logging
│ │ ├── Strings.php # UTF-8 text normalization
│ │ └── Cache.php # Two-tier caching wrapper
│ ├── Search/
│ │ ├── Config.php # 49 curated configurations
│ │ ├── ResultOrderer.php # Main ordering orchestrator
│ │ ├── WpmlHandler.php # WPML SQL-level filtering
│ │ ├── DoctorHandler.php # Doctor prioritization
│ │ ├── ServiceHandler.php # Service matching
│ │ ├── Synonyms.php # 400+ medical terms
│ │ └── SettingsValidator.php # Runtime config validation
│ ├── RelationalTags/
│ │ └── Generator.php # Auto-generated taxonomy tags
│ └── Presentation/
│ └── ShortcodeController.php
├── config/
│ └── relational-tags.json # 150+ medical terminology
└── composer.json

Key Principles Applied:

  • Service Provider pattern for modular initialization
  • Singleton bootstrap ensures single initialization
  • Dependency injection promotes testability
  • Static methods minimize instantiation overhead

Search System Implementation

12-Tier Result Categorization

/**
* Priority buckets for search result ordering
* Higher tier = appears first in results
*/
const PRIORITY_TIERS = [
1 => 'mariani_services', // VIP automatic pinning
2 => 'featured_doctors', // menu_order = 0
3 => 'ordered_doctors', // ACF equipe_doctor_order
4 => 'other_doctors',
5 => 'manager_doctors', // Extracted from services
6 => 'featured_services',
7 => 'ordered_services',
8 => 'other_services',
9 => 'taxonomy_terms', // service_cat archives
10 => 'blog_posts',
11 => 'insurance_partners',
12 => 'other_content',
];

Weight Configuration

class Config {
/**
* Search result weights by post type and category
* Higher weight = appears first in results
*/
const WEIGHTS = [
'featured_page' => 5.0, // Pages mentioning VIP doctors
'priority_doctor' => 4.0, // Doctors with menu_order = 0
'equipment' => 3.0, // Diagnostic equipment
'service' => 3.0, // Healthcare offerings
'page' => 2.0, // Regular pages
'service_cat_archive' => 1.5, // Service category terms
'regular_doctor' => 1.5, // Standard doctors
'post' => 1.0, // Blog posts
'insurance' => 0.8, // Insurance partners
'default' => 0.5, // Unknown post types
];

/**
* Secondary weight boosts for ACF field matches
*/
const FIELD_BOOSTS = [
'doctor_specialty' => 2.0, // Ortopedia, Cardiologia
'doctor_role' => 2.0, // Chirurgo, Medico
'service_description' => 1.0, // 80/20 title weighting
'service_type' => 1.0,
];
}

Curated Rankings System

For specific medical queries, deterministic result ordering overrides relevance scoring:

/**
* Example: "risonanza" (MRI) search configuration
* Ensures diagnostic equipment appears before generic pages
*/
'risonanza' => [
'exact_match' => true,
'tokens' => ['risonanza', 'magnetica', 'rm', 'mri', '3t', '3 tesla'],
'results' => [
['type' => 'service', 'id' => 2847, 'title' => 'Risonanza Magnetica Ingenia 3.0T'],
['type' => 'service', 'id' => 1456, 'title' => 'Radiologia e diagnostica'],
['type' => 'service', 'id' => 3021, 'title' => 'Ritiro Referti Radiologia'],
['type' => 'term', 'taxonomy' => 'service_cat', 'slug' => 'ortopedia'],
],
],

/**
* Example: Doctor name search with VIP positioning
*/
'mariani' => [
'exact_match' => true,
'tokens' => ['mariani', 'pier paolo', 'pier paolo mariani'],
'results' => [
['type' => 'doctor', 'id' => 1358, 'wpml_en' => 6049], // Always first
['type' => 'service', 'id' => 2156], // Ortopedia
['type' => 'service', 'id' => 2847], // Related services
],
],

Total Configurations: 49 curated rankings covering:

  • Medical equipment (risonanza, TAC, robot GPS Excelsius)
  • Anatomy (ginocchio, anca, spalla, piede, caviglia, colonna)
  • Procedures (protesi, artroscopia, allungamento arti)
  • Specialties (neurochirurgia, ortopedia, cardiologia)
  • Doctor surnames (22 VIP doctor configurations)

WPML Multilingual Integration

SQL-level language filtering with prepared statements:

class WpmlHandler {
/**
* Modify Relevanssi SQL query for language filtering
* Uses prepared statements to prevent SQL injection
*/
public static function filter_query_for_language($query, $language = null) {
global $wpdb;

$lang = $language ?: self::get_current_language();

// Join with WPML translations table
$query = str_replace(
"FROM {$wpdb->posts}",
"FROM {$wpdb->posts}
INNER JOIN {$wpdb->prefix}icl_translations t
ON {$wpdb->posts}.ID = t.element_id
AND t.element_type LIKE 'post_%'",
$query
);

// Add language condition with prepared statement
$query = $wpdb->prepare(
str_replace("WHERE 1=1", "WHERE 1=1 AND t.language_code = %s", $query),
$lang
);

return $query;
}

/**
* Normalize post ID to current language translation
* With graceful fallback to original if no translation exists
*/
public static function normalize_id($post_id, $target_language = null) {
if (!function_exists('icl_object_id')) {
return $post_id;
}

$lang = $target_language ?: self::get_current_language();
$translated_id = icl_object_id($post_id, get_post_type($post_id), true, $lang);

return $translated_id ?: $post_id;
}
}

Hybrid Équipe Filtering

Prevents content cross-contamination while preserving discoverability:

/**
* Problem: Services appeared in unrelated searches due to équipe indexing
* Example: "Protesi d'Anca" appeared in "gomito" (elbow) searches because
* Prof. Santucci treats elbows AND manages hip replacement service
*
* Solution: Service-linked doctor preservation
*/
public static function apply_hybrid_equipe_filter($results, $context) {
// Build hash map of services in primary results
$service_ids = [];
foreach ($context['primary_results'] as $result) {
if ($result->post_type === 'service') {
$service_ids[$result->ID] = true;
}
}

// Build hash map of doctors managing/staffing those services
$service_linked_doctors = [];
foreach ($service_ids as $service_id => $_) {
// Get manager
$manager_id = get_field('service_manager', $service_id);
if ($manager_id) {
$service_linked_doctors[$manager_id] = true;
}

// Get équipe staff
$equipe = get_field('equipe_doctors', $service_id);
if (is_array($equipe)) {
foreach ($equipe as $doctor) {
$service_linked_doctors[$doctor['doctor_id']] = true;
}
}
}

// Filter fallback results - O(1) lookup
return array_filter($results, function($result) use ($service_linked_doctors, $context) {
// Always keep non-doctors
if ($result->post_type !== 'doctor') {
return true;
}

// EXCEPTION 1: Direct content match
if (self::has_direct_content_match($result, $context['query'])) {
return true;
}

// EXCEPTION 2: Service-linked doctor
if (isset($service_linked_doctors[$result->ID])) {
return true;
}

// Filter out équipe-only matches
return false;
});
}

Medical Synonym System

class Synonyms {
/**
* 400+ medical term mappings for Italian healthcare
*/
const SYNONYM_GROUPS = [
// Anatomy
'ginocchio' => ['ginocchio', 'knee', 'articolazione ginocchio'],
'anca' => ['anca', 'hip', 'bacino', 'coxartrosi'],
'spalla' => ['spalla', 'shoulder', 'cuffia rotatori'],
'caviglia' => ['caviglia', 'ankle', 'tibiotarsica'],

// Equipment
'risonanza' => ['risonanza', 'rm', 'mri', 'magnetica', '3t', '3 tesla', 'ingenia'],
'tac' => ['tac', 'tc', 'ct', 'tomografia'],
'robot' => ['robot', 'gps', 'excelsius', 'robotica', 'navigazione'],

// Procedures
'protesi' => ['protesi', 'prosthesis', 'impianto', 'sostituzione'],
'artroscopia' => ['artroscopia', 'arthroscopy', 'mini invasiva'],
'allungamento' => ['allungamento', 'lengthening', 'ilizarov', 'arti'],

// Specialties (14 groups x 6 terms each)
'andrologia' => ['andrologia', 'andrology', 'urologo', 'andrologist'],
'cardiologia' => ['cardiologia', 'cardiology', 'cuore', 'cardiologo'],
'dermatologia' => ['dermatologia', 'dermatology', 'pelle', 'dermatologo'],
'neurochirurgia' => ['neurochirurgia', 'neurosurgery', 'colonna', 'spinale'],
// ... 10 more specialty groups

// Visit patterns (for "visita X" searches)
'visita_dermatologica' => ['visita dermatologica', 'dermatologia visita'],
'visita_cardiologica' => ['visita cardiologica', 'cardiologia visita'],
'visita_oculistica' => ['visita oculistica', 'oculistica visita'],
];

/**
* Register synonyms with Relevanssi PREMIUM
*/
public static function register() {
if (!function_exists('relevanssi_register_synonym')) {
return; // Fallback to query expansion for FREE version
}

foreach (self::SYNONYM_GROUPS as $primary => $synonyms) {
foreach ($synonyms as $synonym) {
if ($synonym !== $primary) {
relevanssi_register_synonym($primary, $synonym);
}
}
}
}
}

Performance Optimizations

Two-Tier Caching Strategy

class Cache {
const DEFAULT_TTL = 3600; // Object cache: 1 hour
const SHORT_TTL = 300; // Transients: 5 minutes

/**
* Get or compute pattern with graceful fallback
*/
public static function remember($key, callable $callback, $ttl = self::DEFAULT_TTL) {
// Try object cache first (Redis)
$cached = wp_cache_get($key, 'villa_stuart');
if ($cached !== false) {
return $cached;
}

// Compute value
$value = $callback();

// Store in object cache
wp_cache_set($key, $value, 'villa_stuart', $ttl);

return $value;
}
}

Hash Map Deduplication

/**
* O(1) lookups instead of O(N) array_search
*/
$seen_doctors = []; // Hash map: doctor_id => true

foreach ($results as $result) {
if ($result->post_type === 'doctor') {
// O(1) lookup
if (isset($seen_doctors[$result->ID])) {
continue; // Skip duplicate
}
$seen_doctors[$result->ID] = true;
}
$deduplicated[] = $result;
}

Batch Query Optimization

/**
* Single query for all doctor metadata instead of N+1
*/
$doctor_ids = wp_list_pluck($doctors, 'ID');

// Batch ACF field loading
$menu_orders = [];
$specialties = [];

$meta_query = $wpdb->prepare(
"SELECT post_id, meta_key, meta_value
FROM {$wpdb->postmeta}
WHERE post_id IN (" . implode(',', array_fill(0, count($doctor_ids), '%d')) . ")
AND meta_key IN ('menu_order', 'doctor_specialty')",
...$doctor_ids
);

foreach ($wpdb->get_results($meta_query) as $row) {
if ($row->meta_key === 'menu_order') {
$menu_orders[$row->post_id] = (int) $row->meta_value;
} else {
$specialties[$row->post_id] = $row->meta_value;
}
}

WP-CLI Diagnostic Suite

# Validate critical Relevanssi configuration
wp vs-search validate-settings

# Test Premium-specific features
wp vs-search premium-smoke

# Compare DB synonyms with code defaults
wp vs-search diff-synonyms

# Merge code defaults into DB (non-destructive)
wp vs-search diff-synonyms --apply-merge

# Find taxonomy terms missing search_keywords
wp vs-search term-keywords-report

# Auto-populate missing keywords from synonym sets
wp vs-search populate-term-keywords --apply --rebuild-index

Testing Infrastructure

tests/
├── integration/
│ ├── test-mariani-pinning.php # VIP doctor positioning
│ ├── test-hybrid-filter.php # Équipe filtering
│ └── test-wpml-integration.php # Language switching
├── phpunit/
│ ├── ResultOrdererComparisonTest.php # New vs legacy parity
│ ├── SearchPremiumParityTest.php # Premium features
│ └── ConfigTest.php # Configuration validation
└── bin/
└── run-relevanssi-validation.php # CLI test runner

Project 2: Villa Stuart Russia (villastuart.ru)

Technology Stack

ComponentTechnology
FrameworkCodeIgniter 3.x
Grid SystemBootstrap 4
CarouselOwl Carousel
DevelopmentDocker
DatabaseMySQL

The Challenge

Align the Russian website frontend with the Italian site’s modern design, creating a consistent brand experience across both properties while working within CodeIgniter’s MVC architecture.

Design System Implementation

Color Palette (Figma-Based)

:root {
/* Primary Brand Colors */
--color-primary: #003E38; /* Deep teal green */
--color-secondary: #213535; /* Darker gray-green */
--color-white: #FCFCFC; /* Off-white */

/* Accent Colors */
--accent-gold: #F6C744; /* Gold for borders/highlights */
--border-light: #B6D5D4; /* Light teal for subtle borders */
--background-light: #EDF5F4; /* Very light teal background */

/* Text Colors */
--text-primary: #213535;
--text-secondary: #666666;
--text-light: #FCFCFC;
}

Typography System

/* Primary Font: UI Elements & Body */
@import url('https://fonts.googleapis.com/css2?family=Mulish:wght@400;600;700;800&display=swap');

/* Secondary Font: Headings & Titles */
@font-face {
font-family: 'Trajan Pro 3';
src: url('../fonts/TrajanPro3-Regular.woff2') format('woff2');
font-weight: normal;
}

body {
font-family: 'Mulish', sans-serif;
font-size: 16px;
line-height: 1.6;
color: var(--text-primary);
}

h1, h2, h3, .section-title {
font-family: 'Trajan Pro 3', serif;
text-transform: uppercase;
letter-spacing: 0.05em;
}

Header Redesign

/* Pre-navigation bar with language selector */
.pre-nav-new {
background-color: var(--color-primary);
padding: 8px 0;
}

.pre-nav-new .language-selector {
display: flex;
gap: 12px;
}

.pre-nav-new .language-selector a {
color: var(--color-white);
opacity: 0.7;
transition: opacity 0.3s ease;
}

.pre-nav-new .language-selector a.active,
.pre-nav-new .language-selector a:hover {
opacity: 1;
}

/* Main header with centered navigation */
.header-new {
background-color: var(--color-white);
padding: 20px 0;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.header-new .nav-menu {
display: flex;
justify-content: center;
gap: 32px;
}

.header-new .nav-menu a {
font-family: 'Mulish', sans-serif;
font-weight: 600;
color: var(--color-primary);
text-decoration: none;
padding: 8px 0;
border-bottom: 2px solid transparent;
transition: border-color 0.3s ease;
}

.header-new .nav-menu a:hover,
.header-new .nav-menu a.active {
border-bottom-color: var(--accent-gold);
}

Homepage Sections

/* Services Grid - 4 cards with medical icons */
.services-section {
background-color: var(--color-primary);
padding: 80px 0;
}

.service-card {
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 32px;
text-align: center;
transition: transform 0.3s ease, background 0.3s ease;
}

.service-card:hover {
transform: translateY(-8px);
background: rgba(255, 255, 255, 0.15);
}

.service-card .icon {
width: 64px;
height: 64px;
margin-bottom: 24px;
}

.service-card h3 {
color: var(--color-white);
font-size: 18px;
margin-bottom: 12px;
}

/* About Section - Image + Content Columns */
.about-section {
background-color: var(--background-light);
padding: 100px 0;
}

.about-section .content-column {
padding-left: 60px;
}

.about-section .section-label {
font-family: 'Mulish', sans-serif;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--accent-gold);
font-size: 12px;
margin-bottom: 16px;
}

/* Contact Section - Coordinator Info */
.contact-section {
background-color: var(--color-secondary);
padding: 80px 0;
}

.coordinator-card {
display: flex;
align-items: center;
gap: 32px;
}

.coordinator-card .photo {
width: 180px;
height: 180px;
border-radius: 50%;
object-fit: cover;
border: 4px solid var(--accent-gold);
}

/* Accreditations - FIFA/FIMS Badges */
.accreditations-section {
padding: 60px 0;
text-align: center;
}

.accreditation-badges {
display: flex;
justify-content: center;
gap: 48px;
align-items: center;
}

.accreditation-badges img {
height: 80px;
filter: grayscale(100%);
opacity: 0.7;
transition: all 0.3s ease;
}

.accreditation-badges img:hover {
filter: grayscale(0%);
opacity: 1;
}

View Template Structure (CodeIgniter)

<!-- application/views/template/bootstrap/frontend/index.php -->
<?php $this->load->view('template/bootstrap/common/header'); ?>

<!-- Services Grid -->
<section class="services-section">
<div class="container">
<div class="row">
<?php foreach ($services as $service): ?>
<div class="col-md-3 col-sm-6">
<div class="service-card">
<img src="<?= base_url('css/images/' . $service['icon']) ?>"
alt="<?= $service['title'] ?>"
class="icon">
<h3><?= $service['title'] ?></h3>
<p><?= $service['description'] ?></p>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</section>

<!-- About Section -->
<section class="about-section">
<div class="container">
<div class="row align-items-center">
<div class="col-md-6">
<img src="<?= base_url('img/clinic-exterior.jpg') ?>"
alt="Villa Stuart"
class="img-fluid rounded">
</div>
<div class="col-md-6 content-column">
<span class="section-label">Chi Siamo</span>
<h2><?= $about_title ?></h2>
<p><?= $about_content ?></p>
<a href="<?= site_url('about') ?>" class="btn btn-primary">
Scopri di più
</a>
</div>
</div>
</div>
</section>

<!-- Russian Coordinator -->
<section class="contact-section">
<div class="container">
<div class="coordinator-card">
<img src="<?= base_url('img/coordinator.jpg') ?>"
alt="Максим Долгий"
class="photo">
<div class="info">
<h3>Максим Долгий</h3>
<p class="role">Координатор для русскоязычных пациентов</p>
<p class="phone">+39 XXX XXX XXXX</p>
<p class="email">russia@villastuart.it</p>
</div>
</div>
</div>
</section>

<?php $this->load->view('template/bootstrap/common/footer'); ?>

Design Alignment Results

AspectBeforeAfter
Color SchemeGeneric template colorsBrand-aligned teal palette
TypographySingle sans-serif fontMulish + Trajan Pro hierarchy
HeaderBasic navigationPre-nav + centered menu
FooterStandard templateHorizontal sections with social
CardsFlat designRounded corners, shadows, hover effects
ResponsiveBasic BootstrapMobile-first with custom breakpoints

Development Workflow

Git Commit Distribution

TypeCountPercentage
feat (features)4026.5%
fix (bug fixes)2818.5%
docs (documentation)2113.9%
refactor42.6%
chore32.0%

Major Development Phases

  1. Foundation (July 2025): Initial setup, shortcodes, service management
  2. Infrastructure (October 2025): Docker environment, database optimization
  3. Search Overhaul (November 2025): Relevanssi integration, curated rankings
  4. Refactor (November 14, 2025): 5-week PSR-4 migration completed
  5. Refinement (November 18-24, 2025): Hybrid filtering, synonym expansion

Quality Assurance

  • Gemini AI Code Review: 96/100 score after bug fixes
  • Code Quality Score: 10/10
  • Production Readiness: 9.5/10
  • Test Coverage: Search, WPML, Elementor, security

Documentation System

docs/
├── SEARCH_SYSTEM.md # Complete search reference
├── RELEVANSSI_SETTINGS.md # Critical configuration
├── HYBRID_EQUIPE_FILTERING_DESIGN.md
├── MU_PLUGINS_REFACTOR_PLAN.md
├── MU_PLUGINS_REFACTOR_FIXES.md
├── MARIANI_PINNING_IMPLEMENTATION.md
├── DOCKER_ENVIRONMENT.md
├── DEPLOYMENT_GUIDE.md
└── INDEX.md # Master documentation index

.claude/reports/
├── SEARCH_CHANGELOG.md # Change history
├── SEARCH_GUARDRAILS_2025-11-21.md
├── DEPLOYMENT_PRODUCTION_*.md
└── SECURITY_AUDIT_*.md

Technical Achievements

Search System Metrics

  • 49 curated search configurations
  • 400+ medical terminology synonyms
  • 12 priority tiers for result categorization
  • 6 weight levels for post type scoring
  • 0 breaking changes during architectural refactor

Code Quality Metrics

  • 23 PHP classes in PSR-4 architecture
  • 9,480+ lines of organized, documented code
  • 3,272 lines in ResultOrderer (main orchestrator)
  • 1,751 lines in Config (curated rankings)
  • 151 commits with conventional commit messages

Performance Metrics

  • O(1) hash map lookups for deduplication
  • Two-tier caching (Redis + transients)
  • Batch queries instead of N+1 patterns
  • Lazy evaluation with early returns

Skills Demonstrated

Backend Development

  • PHP 8.3 with modern syntax and type hints
  • WordPress plugin architecture (MU-plugins)
  • PSR-4 autoloading with Composer
  • Service Provider pattern
  • WPML multilingual integration
  • ACF Pro custom field management
  • Redis object caching

Search Engineering

  • Relevanssi PREMIUM configuration
  • Custom weighting algorithms
  • Synonym management systems
  • Medical terminology indexing
  • Multilingual search optimization

Frontend Development

  • CodeIgniter MVC architecture
  • Bootstrap 4 responsive design
  • CSS custom properties
  • Figma-to-code implementation
  • Cross-browser compatibility

DevOps

  • Docker containerization
  • MariaDB/MySQL database management
  • WP-CLI automation
  • Git version control (conventional commits)
  • rsync deployment workflows

Quality Assurance

  • PHPUnit testing
  • Integration test suites
  • AI-assisted code review (Gemini)
  • Configuration validation
  • Performance profiling

Conclusion

The Villa Stuart project demonstrates comprehensive full-stack development capabilities, from architecting a sophisticated search system with 49 curated configurations to implementing a cohesive design language across multiple platforms. The 5-week architectural refactor achieved zero breaking changes while modernizing the codebase to PSR-4 standards, and the final 96/100 quality score validates the production-ready nature of the implementation.


Written by Lushano Perera

Digital craftsman exploring the intersection of design, technology, and human experience.