Lumera Learning Group (lumera-spa)
A high-performance, modern, and SEO-optimized Single Page Application (SPA) with Server-Side Rendering (SSR) built for Lumera Learning Group. The platform offers interactive Spanish and English language learning classes for children and teenagers (ages 4β18) led by native teachers.
π Project Overview
This web application serves as the main portal for Lumera Learning Group. It is built to offer a seamless, fast user experience across multiple devices, featuring:
- Dynamic Class Scheduling: Real-time integration with the Calendly API to fetch, cache, and display available class categories.
- Fully Translated Experience (i18n): Native support for English (
en) and Spanish (es) using compiled Angular localization, complete with SEO-optimized language routing. - Direct Contact Forms: Client-side integration with EmailJS to securely capture parental inquiries and child age brackets.
- Highly Optimized Performance: Leveraging viewport-based lazy loading (
@defer) and Angular hydration to maximize Core Web Vitals.
π οΈ Tech Stack & Integration Ecosystem
The project utilizes a modern frontend and server architecture:
1. Core Framework & Runtime
- Angular 21 (v21.2.0): Leverages the latest framework innovations, including standalone components, Signals, computed properties,
DestroyRef, and the new@defertemplating syntax. - Angular Hydration & SSR: Server-Side Rendering powered by
@angular/ssrand Express to pre-render routes and serve fast, crawler-friendly HTML.
2. Styling & Design System
- Tailwind CSS v4 (
@tailwindcss/postcss&tailwindcssv4.1.12): Built using the new Tailwind CSS v4@themecompiler and CSS custom properties insidesrc/styles.cssfor a custom pastel palette, smooth micro-animations, and responsive layouts. - Typography: Google Fonts integration (
Nunito) configured globally for kid-friendly and readable interface aesthetics.
3. Third-Party API Integrations
- Calendly API: Fetches active class events dynamically. Includes an automated warm-up cache in the services layer and launches the Calendly Booking Widget on click.
- EmailJS (
@emailjs/browser): Processes contact form submissions on the client side without needing a custom database backend, keeping operational overhead low.
4. Quality & Build Tooling
- Vitest: Replaces Karma/Jasmine as the test runner, delivering faster execution times during unit testing.
- Postcss & Prettier: Ensures clean, auto-formatted style assets.
π Project Directory Structure
Below is the layout of the source files, reflecting a highly modular design:
lumera-spa/
βββ public/ # Static public assets
β βββ assets/ # Images and brand graphics
β βββ _redirects # Netlify / CDN redirection mapping
β βββ robots.txt # Crawler directives
β βββ sitemap.xml # SEO sitemap with alternate hreflang tags
βββ src/
β βββ app/ # Main Angular application root
β β βββ components/ # Reusable UI components
β β β βββ benefits-section.component.ts/.html
β β β βββ class-gallery.component.ts/.html
β β β βββ contact-form.component.ts/.html
β β β βββ contact-section.component.ts/.html
β β β βββ footer.component.ts/.html
β β β βββ hero-section.component.ts/.html
β β β βββ navbar.component.ts/.html
β β β βββ testimonials-section.component.ts/.html
β β β βββ whatsapp-button.component.ts/.html
β β βββ models/ # TypeScript interfaces
β β β βββ calendly.model.ts
β β βββ pages/ # High-level page components (views)
β β β βββ blog/ # Individual blog post components
β β β βββ blog-hub/ # Blog listing dashboard
β β β βββ home/ # Homepage view (lazy loads sections)
β β β βββ pricing/ # Product options and course pricing lists
β β βββ services/ # API and DOM utility services
β β β βββ calendly-api.service.ts
β β β βββ external-scripts.service.ts
β β βββ app.config.ts # Main CSR/Hydration configuration providers
β β βββ app.config.server.ts # Server-specific configurations
β β βββ app.routes.ts # Navigation routing definitions
β β βββ app.ts # App root component (manages SEO tags & JSON-LD)
β β βββ app.html / app.css
β β βββ tokens.ts # Base URL injection tokens for SSR
β βββ environments/ # Environment configurations
β β βββ environment.ts # Local development values (includes local tokens)
β β βββ environment.prod.ts # Production values
β βββ locale/ # i18n XLF localization resources
β β βββ messages.xlf # Extracted base source dictionary
β β βββ messages.en.xlf # English translation file
β β βββ messages.es.xlf # Spanish translation file
β βββ main.ts # Client bootstrap entry point
β βββ main.server.ts # Server bootstrap entry point
β βββ server.ts # Express SSR server setup
β βββ styles.css # Global styles and Tailwind configuration
βββ angular.json # Angular CLI configuration file
βββ package.json # Scripts & dependencies definition
βββ tailwind.config.js # Legacy tailwind config (if backward compatibility is needed)
βββ tsconfig.json # TypeScript compiler configuration
π Data Models
Calendly Integration Model (src/app/models/calendly.model.ts)
Standardized interfaces that model the payload coming from the Calendly Event Types endpoint:
export interface CalendlyEventType {
name: string;
description_plain: string;
description_html: string;
scheduling_url: string;
duration: number;
color: string;
active: boolean;
}
export interface CalendlyResponse {
collection: CalendlyEventType[];
pagination: {
count: number;
next_page: string | null;
};
}
π Security Configuration & Performance
The codebase adheres to strict security and frontend performance best practices:
1. Security Safeguards
- Renderer2 Safe Injection: The application injects structured JSON-LD schemas inside the HTML
<head>using AngularβsRenderer2to prevent Cross-Site Scripting (XSS) vulnerabilities. - Input Sanitization: The contact form enforces size limits (
maxLengthvalidation on names, child age, email, and messages) and strict type constraints via AngularβsReactiveFormsModule. - Decoupled Server Logic: Client-side integration with EmailJS and Calendly ensures that no database credentials or session tokens are exposed to the client or stored on custom databases, removing server-side database exploit vectors.
- Platform Guarding: Services checking for DOM manipulation (such as loading Calendly scripts or tracking screen sizes) wrap executions in
isPlatformBrowserchecks, preventing crashes or data leakage on the SSR server layer.
2. Performance Engineering
- Caching Layer: The
CalendlyApiServicecaches the list of event types using RxJSshareReplay(1). When the user is on the pricing page, the service is called on initialization (ngOnInit), warming up the cache so that the widget loads instantly when requested. - Lazy Script Loading: Instead of blocking page load with scripts in the main index file,
ExternalScriptsServicedynamically mounts scripts and stylesheets (e.g. Calendly widgets) in the DOM only when the user opens the relevant section. - Viewport Deferrals (
@defer): The footer, testimonials, contact, and benefit sections are lazy-rendered only when they enter the viewport (@defer (on viewport)), dramatically improving initial page load metrics. - Change Detection Tuning: Essential components use
ChangeDetectionStrategy.OnPushto prevent unnecessary component tree re-renders, lowering CPU overhead.
π SEO & Internationalization (i18n)
SEO is a primary pillar of the applicationβs implementation:
1. Dynamic Meta Tags & Links
- Canonical Linking: On navigation, the application updates the
<link rel="canonical">element in the head, pointing to the exact current page with trailing slashes to align with sitemaps and CDNs. - Cross-Language Mapping (
hreflang): Configures<link rel="alternate" hreflang="xx">mapping Spanish, English, andx-default(pointing to the English version) to resolve redirect issues on search engines.
2. Structured Data (JSON-LD Schemas)
- Organization Schema: Implemented on the home view to identify the business, brand names, web URL, logo, description, and official social media properties.
- ItemList & Course Schema: Embedded on the pricing view to structure information about child and teenage language programs, including names, providers, and prices (USD) for Google Rich Snippets.
3. Multi-Locale Builds
Because Angular compiles separate compiled static folders per language locale (/en and /es), routing is configured via Netlify redirections (public/_redirects):
/ /en/ 301
/es/* /es/index.html 200
/en/* /en/index.html 200
This forces a hard reload when switching languages in NavbarComponent, ensuring the client downloads the correct translated JavaScript bundle.
π§ͺ Implementation Validation & Testing
During the validation audit of the implementation, we verified:
- Successful Production Compilation: The build pipeline compiles and correctly generates SSR server assets and 12 static localized paths for SSG.
- Vitest Execution: Unit tests are configured via Vitest. The initial test runs fail due to missing context in default boilerplate specs.
Known Testing Gaps & How to Fix Them
The boilerplate unit tests fail on:
Ι΅NotFound: NG0201: No provider found for ActivatedRoute: Components likeApporHomeimportRouterLink/NavbarComponentbut the test setups do not provide the routing modules.- Solution: Import
RouterModuleand provide the routing providers usingprovideRouter([])inside thebeforeEachblock of the spec files. expect(compiled.querySelector('h1')?.textContent).toContain('Hello, lumera-spa'): The test still expects the boilerplate template header, which has been removed.- Solution: Update the assertion to query for current components or text.
βοΈ Development Commands
Use the following scripts during local development and builds:
Run Local Development Server
To launch the app locally (defaults to English):
npm run dev
To run specifically in the English configuration:
npm run dev:en
Build for Production
To trigger the double compilation (en/es), pre-render static HTML views, and copy redirect/SEO rules to the public output:
npm run build
Serve Compiled SSR Build
To preview the Server-Side Rendered application on localhost (port 4000):
npm run serve
Run Vitest Unit Tests
To run Vitest specs locally:
npm run test