Process Dec 24, 2020 6 min read

Le CLAPE (formerly APEC) — Course Enrollment Platform

A custom e-commerce platform for the French international school community in Rome. Built a WordPress/WooCommerce solution enabling parents to register, manage children profiles, and enroll in after-school activities with real-time availability tracking. Delivered bilingual French/Italian support and handled high-concurrency enrollment periods over 5+ years of active development.

Lushano Perera
Lushano Perera
Author

Project Overview

Client: APEC – Association des Parents d’Élèves du Lycée Chateaubriand (Rome, Italy)

Website: www.atelierschateau.it

Project Duration: January 2014 – September 2019 (5+ years of active development and maintenance)

My Role: Frontend Developer

Team:

  • Lushano Perera – Frontend Development (512 commits)
  • Carlo Cifarelli – Backend Development (414 commits)

The Challenge

The Association des Parents d’Élèves du Lycée Chateaubriand, a parents’ association connected to the prestigious French international school Lycée Chateaubriand in Rome, needed a comprehensive digital platform to manage:

  • Parent registration and authentication
  • Children profile management
  • After-school activities enrollment
  • Course booking with limited availability
  • Online payments
  • Bilingual support (French and Italian)

The platform had to handle high-concurrency scenarios during enrollment periods, where hundreds of parents compete for limited course spots simultaneously.


The Solution

We developed a fully custom WordPress-based platform with WooCommerce integration, featuring a real-time stock management system for course enrollment and a sophisticated user management system.

Key Features Delivered

  1. User Registration & Authentication System
    • Custom login flow with session management
    • Automatic parent profile creation upon registration
    • Login status tracking to prevent concurrent sessions
  2. Child Management Interface
    • Parents can add, edit, and manage multiple children profiles
    • Custom fields for school information, medical notes, emergency contacts
  3. Real-time Course Enrollment System
    • Live availability tracking
    • Cart reservation with 20-minute expiration timer
    • Prevention of double-booking through slot validation
  4. E-commerce Integration
    • WooCommerce-powered checkout
    • Multiple payment methods (PayPal, bank transfer, check)
    • Order status tracking and notifications
  5. Admin Control Panel
    • Toggle switches for registration, validation, shop, and profile access
    • Real-time control without code deployment
    • Comprehensive reporting system
  6. Multilingual Support
    • Full French/Italian translation via WPML
    • Language switcher with flag indicators

Technology Stack

Frontend (My Focus)

TechnologyPurpose
HTML5/CSS3Semantic markup, responsive styling
jQuery 1.10DOM manipulation, AJAX interactions
Cycle2Homepage slider and activity carousels
FancyboxImage galleries and modal windows
SwitcheryiOS-style toggle switches for admin controls
SuperfishAccessible dropdown navigation menus
jsPDFClient-side PDF generation for reports
Font AwesomeIcon library
ModernizrFeature detection for progressive enhancement

Backend (Developed by Carlo Cifarelli)

TechnologyPurpose
WordPressContent management system
PHP 5.6Server-side logic
MySQLDatabase
RedisObject caching for performance
WooCommerceE-commerce engine
WPMLMultilingual content management
Toolset TypesCustom post types and fields

DevOps & Infrastructure

TechnologyPurpose
DockerLocal development environment
GitLab CI/CDAutomated deployment pipeline
NginxWeb server
LFTPFTP-based deployment

Frontend Development Highlights

Custom Theme Architecture

I built a completely custom WordPress theme from scratch, based on HTML5 Boilerplate/Initializr best practices. The theme follows a modular structure with separated concerns:

apec-theme/
├── css/
│ ├── main.css # Primary stylesheet (~4000 lines)
│ ├── normalize.css # CSS reset
│ └── print.css # Print-optimized styles
├── js/
│ ├── main.js # Core functionality
│ ├── init.js # Initialization scripts
│ └── vendor/ # Third-party libraries
├── fonts/ # Custom Museo Slab webfonts
└── inc/ # PHP includes (modular functions)

Responsive Navigation System

Implemented a multi-level navigation system with Superfish for accessibility:

jQuery(document).ready(function() {
jQuery('ul.menu .sub-menu').hide();

// Show relevant submenu based on current page
jQuery('.current-menu-item .sub-menu, ' +
'.current-page-ancestor .sub-menu, ' +
'.current-menu-parent .sub-menu').show();
});

Real-time Admin Controls

Created an intuitive admin control panel using Switchery toggles that communicate with the backend via AJAX:

var input_controllo_vendita = document.querySelector('#input_controllo_vendita');
var controllo_vendita_switchery = new Switchery(input_controllo_vendita, {
color: '#00bf12',
secondaryColor: '#fb2a2a'
});

input_controllo_vendita.onchange = function() {
jQuery(".overlay").show();
jQuery.post(ajaxurl, {
'action': 'abilita_acquisti',
'checked': input_controllo_vendita.checked
}, function(response) {
jQuery(".overlay").hide();
alert(response);
location.reload();
});
};

Loading Overlay System

Implemented a loading overlay to improve UX during AJAX operations:

<div class="overlay" style="display: none;">
<div>Chargement...</div>
</div>
jQuery(".cred-form").submit(function(event) {
jQuery(".overlay").show();
jQuery(".js-wpt-field-items .wpt-form-error:visible").onAvailable(function() {
jQuery(".overlay").hide();
});
});

Built dynamic gallery functionality that automatically groups images and pulls captions:

jQuery('section.gallery figure a').each(function() {
var title = jQuery(this).parent('figure').find('.caption').text();
jQuery(this).attr('title', title);
});

jQuery('section.gallery').each(function() {
var gallery_id = jQuery(this).attr('id');
jQuery(this).children('div').children('figure').each(function() {
jQuery(this).find('a').attr('rel', gallery_id);
});
});

jQuery('section.gallery a').fancybox();

Form Validation & UX Enhancements

Implemented real-time form field formatting:

// Auto-uppercase surnames
jQuery("input[name='wpcf-cognome']").keyup(function() {
jQuery(this).val(jQuery(this).val().toUpperCase());
});

// Capitalize first letters of names
jQuery("input[name='wpcf-nome']").keyup(function() {
jQuery(this).val(jQuery(this).val().capitalise());
});

// Lowercase emails
jQuery("input[name='wpcf-email']").keyup(function() {
jQuery(this).val(jQuery(this).val().toLowerCase());
});

Custom String Capitalization Prototype

String.prototype.capitalise = function() {
var text = this,
split = text.split(" "),
res = [],
i, len, component;

for (i = 0, len = split.length; i < len; i++) {
component = split[i];
res.push(component.substring(0, 1).toUpperCase());
res.push(component.substring(1));
if (len > 1 && i < len - 1) {
res.push(" ");
}
}
return res.join("");
};

CSS Architecture

Custom Typography with Web Fonts

@font-face {
font-family: 'museo-slab-500';
src: url('../fonts/museo_slab_700-webfont.eot');
src: url('../fonts/museo_slab_700-webfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/museo_slab_700-webfont.woff') format('woff'),
url('../fonts/museo_slab_700-webfont.ttf') format('truetype'),
url('../fonts/museo_slab_700-webfont.svg#museo_slab700') format('svg');
font-weight: normal;
font-style: normal;
}

Header Bar with Admin Controls

#top {
width: 100%;
float: left;
height: 34px;
background: #2b2b2b;
color: #ffffff;
border-bottom: 3px solid #fcb040;
font-size: 1.2em;
}

#top .flex {
display: flex;
align-items: center;
justify-content: space-between;
}

Language Switcher with Flag Icons

#top ul#langs li.fr.active a {
background: url(../img/flag_fr_active.png) no-repeat;
}

#top ul#langs li.fr a {
background: url(../img/flag_fr.png) no-repeat;
}

#top ul#langs li a {
display: block;
width: 22px;
height: 14px;
float: left;
text-indent: -999em;
}

Timer/Notification Banner

#timer {
width: 100%;
float: left;
background: #7DBE74;
color: #ffffff;
}

#timer p {
margin: 0 35px;
padding: 10px 0;
font-weight: bold;
font-size: 2em;
text-align: center;
}

#timer p span {
color: #fcb040;
}

Performance Optimizations

CDN with Fallback Pattern

Implemented smart resource loading with local fallback:

function load_theme_scripts() {
wp_deregister_script('jquery');
$url = 'https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js';

if (urlOK($url)) {
wp_register_script('jquery',
'//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js',
false, '1.10.1', true);
} else {
wp_register_script('jquery',
get_template_directory_uri() . '/js/vendor/jquery-1.10.1.min.js',
__FILE__, '1.10.1', true);
}
wp_enqueue_script('jquery');
}

DNS Prefetching

<link rel="dns-prefetch" href="//ajax.googleapis.com" />
<link rel="dns-prefetch" href="//fonts.googleapis.com" />
<link rel="dns-prefetch" href="//fonts.gstatic.com" />
<link rel="dns-prefetch" href="//www.google-analytics.com" />

Asset Versioning for Cache Busting

wp_register_style('main',
get_template_directory_uri() . '/css/main.css',
array('normalize'),
'1.91', // Version number for cache busting
'screen'
);

Challenges & Solutions

Challenge 1: High-Concurrency Course Enrollment

Problem: During enrollment periods, hundreds of parents tried to book limited course spots simultaneously, causing race conditions.

Solution: Implemented a cart reservation system with a 20-minute timer. Items are temporarily “locked” in a user’s cart, preventing double-booking while giving users time to complete checkout.

Challenge 2: Bilingual Content Management

Problem: All content needed to be available in both French and Italian, with seamless language switching.

Solution: Integrated WPML for full multilingual support, with custom language switcher in the header using flag icons.

Challenge 3: Complex User Roles

Problem: Different user types (parents, teachers, administrators) needed different access levels and features.

Solution: Custom role-based access control with WordPress capabilities system, plus special username whitelist for administrative features.


Results & Impact

  • 5+ years of continuous operation serving the school community
  • 900+ commits representing ongoing improvements and feature additions
  • Successfully handled seasonal enrollment rushes with high concurrent users
  • Zero downtime during critical enrollment periods
  • Smooth rebranding transition from APEC to Le CLAPE in 2019

Lessons Learned

  1. WordPress can scale: With proper caching (Redis) and optimized queries, WordPress handles high-traffic scenarios effectively.
  2. User experience matters: Small UX touches like loading overlays, real-time field formatting, and clear error messages significantly improve user satisfaction.
  3. Plan for concurrency: Any booking/reservation system needs to handle race conditions from the start.
  4. Modular code pays off: Separating frontend logic into focused files (init.js, main.js, validation.js) made maintenance much easier over 5+ years.

Technologies Used (Summary)

Frontend: HTML5, CSS3, jQuery, Cycle2, Fancybox, Superfish, Switchery, jsPDF, Modernizr, Font Awesome

Backend: WordPress, PHP, MySQL, Redis, WooCommerce, WPML, Toolset Types

DevOps: Docker, GitLab CI/CD, Nginx

Written by Lushano Perera

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