Portfolio

Projects &
Achievements

A curated selection of academic, team and personal projects — full-stack platforms, real-time multiplayer apps, REST APIs and a Pygame title. Pick a project below to see the full case study: context, features, stack, my contribution, what I learned, and a gallery.

Project
Web Development · 2ACS Solo Project Full-Stack Laravel · Livewire

ARRiSE — Rehabilitation Clinic Platform

A full-stack Laravel application combining a public marketing site, an education academy, a charity shop, and three role-segregated portals (admin, therapist, patient) for a fictional sports-rehabilitation clinic.

2ACS — Web Development
2025–2026
Sole developer
Shipped

Context & Background

Personal project for the 2ACS Web Development module at Thomas More (2025–2026). The brief was to design and ship a complete real-world Laravel application individually, starting from the laravel/livewire-starter-kit. I picked a clinic platform because it forces several non-trivial concerns into one codebase: multi-role authorization, structured clinical data with PDF output, an enrolment system with deadlines, bilingual public content, and a transactional email pipeline.

Features

  • Role-aware /dashboard router and three separate portals (admin, therapist, patient), gated by a custom role middleware that also verifies a matching profile record exists.
  • Therapist clinical workflow: a Livewire form capturing mobility, stability, strength, power and functional data, auto-calculating left/right asymmetry into a JSON column, with multi-file uploads (PDF, images, video, Office docs up to 10 MB) and on-save DomPDF generation + optional email delivery to the patient.
  • Patient progress dashboard derived from historical session reports — time-series for dorsiflexion (L/R) and hip extension (L/R) — with a profile-completion flow that flips a patient from pending to active.
  • Admin back-office with KPI dashboards and CRUD for users, internal courses, speakers, external conferences, webinars, podcasts, products and shop orders.
  • Academy module with derived enrolment status (open, closing_soon, closed, full, ongoing, past), capacity and deadline checks, plus confirmation emails.
  • Charity shop: public catalog with reservation workflow (pending / collected / cancelled), and a separate shop_orders / shop_orderlines schema for admin tracking.
  • EN / NL / FR internationalization via translation dictionaries, a SetLocale middleware (session/cookie/config), and bilingual model fields surfaced through a runtime accessor.
  • Five Mailable classes with local /mail-preview/* routes for designing templates in Mailpit.

My Contribution

I was the sole developer. I designed the data model (23 custom migrations and the matching Eloquent models — users with role normalisation, patients with consent / insurance / no-show tracking, therapists, the therapist–patient pivot, session reports with the JSON objective_data column, courses, registrations, speakers, products, orders, reservations, contacts) and authored the seeders that boot a usable demo dataset.

On the authorization side I built the CheckRole middleware, the EnsurePatientProfileComplete guard, the role-aware dashboard redirector, and the PatientPolicy / SessionReportPolicy gating the report download route through Gate::authorize. I implemented the therapist session-report form, the asymmetry computation, and the SessionReportPdfService that renders a Blade-based DomPDF, caches it on the public disk and regenerates on demand if the cached file is missing.

I built every interactive page as a full-page Livewire component, designed the custom arrise layout, the transactional email templates, the PDF template, the EN/NL/FR translation layer, and the zip.cjs packaging script. The standard Fortify auth flow and the Settings screens come from the starter kit and were not authored by me.

SKIL2 · Required Team Project (7) Real Client Laravel · Livewire

Grow Kasterlee — Fitness Studio Management Platform

Production-style web application for a real fitness studio in Kasterlee, Belgium — bookings, training and nutrition coaching, member progress tracking, and credit-based payments, built across Scrum sprints with versioned releases and direct client demos.

SKIL2 — 2 ITF APPAI-ACS
2025–2026
Module owner — Plans & Progress
7 students · KLA-B

Context & Background

Team project for the SKIL2 course at Thomas More (2025–2026), built for an external client — Katrien Laenen, who runs the fitness studio Grow Kasterlee. The client needed to replace ad-hoc spreadsheets and paper agendas with a single system covering bookings, training and nutrition coaching, member progress, and credit-based payments. The course required us to deliver in Scrum sprints with versioned releases, a real backlog, and direct client demos.

Features

  • Three role-aware experiences — member, coach, admin — each with its own dashboard and layout.
  • Public site: marketing home, pricing, contact form with email confirmation, and a session-availability viewer.
  • Authentication via Laravel Fortify: registration, login, password reset, email verification, two-factor.
  • Members book individual or group sessions (invite friends), follow a personal weekly calendar, log weight, follow assigned training and nutrition plans, log per-exercise progress, manage friends via friend codes, chat live with image upload, and receive in-app + email notifications.
  • Coaches see a weekly stats dashboard, set available time slots, manage member goals, build training and nutrition plans per member, and review member progress with structured feedback and performance labels.
  • Admins manage users and roles, configure credit-based packages and promotions, manage session types and a master calendar, edit text content of public pages (lightweight CMS), and broadcast notifications.
  • Cross-cutting: queued session-reminder emails, role-based middleware, credit-based purchase system.

My Contribution

I owned the Training Plans, Goals & Progress Tracking module end-to-end. On the data layer I designed nine Eloquent models (TrainingPlan, TrainingPlanExercise, Exercise, ProgressReport, Goal, WorkoutLevelType, EquipmentType, ExerciseEquipment, Injury) and shipped roughly fourteen migrations — including iterative schema changes such as adding member_id to plans, linking progress reports directly to plan exercises, making user_session_id nullable, and introducing coach feedback and performance-label columns — plus the matching seeders.

On the coach side I built the plan builder (Coach\TrainingPlans) with member search, goal linking, dynamic exercise rows, workout-level selection, and an assign-existing-plan flow; the per-member goal CRUD (Coach\GoalsManagement); the progress-review screen with per-session feedback, overall feedback, and performance labels; and the equipment catalog used inside the builder.

On the member side I built Member\TrainingPlans and Member\SessionProgess, including the progress-logging modal (weight, reps, duration, notes) with create/edit flows, validation, and Auth::id()-scoped authorization through nested relationship constraints. Frontend: six Blade views styled with Tailwind 4 and Livewire Flux, integrated into the role-specific layouts. Routes were wired under the role:member and role:coach,admin middleware groups.

The result is a complete coach-to-member feedback loop: a coach sets a goal, builds a tailored plan, the member logs progress per exercise, and the coach reviews each entry and pushes feedback back.

Skills Integration 2 · SKIL2 Solo Project Design Phase Figma · Database Design

Household Management System — Multi-Role Family Platform

A conceptual multi-role household management system designed to organize daily tasks, scheduling, meals, receipts, and trip planning for a shared family environment. Focus on system architecture, database modeling, and interface design rather than implementation.

Skills Integration 2 (SKIL2)
2025–2026
Sole designer — UI/UX & Database
Completed (design phase)

Context & Background

Project for Skills Integration 2 (SKIL2, 2025–2026) at Thomas More. The brief was to design a structured digital system from scratch, simulating a real-world household coordination platform capable of supporting multiple user roles and complex daily workflows. The focus was on translating real-life household operations into a normalized relational database structure and a clear, scalable UI/UX system using Figma.

Features (Designed System Scope)

  • Role-based system concept with four personas: Admin, Family Member, Staff, and Chef — each with distinct permission layers and dashboard views.
  • Task scheduling and assignment module for daily household activities with status tracking and priority levels.
  • Meal planning system with structured weekly planning logic, recipe integration, and dietary preferences.
  • Trip and event planning structure for shared household coordination and scheduling.
  • Receipt and expense tracking model for shared financial management, splitting costs, and budget oversight.
  • Dashboard-based UI concept tailored to each user role, presenting relevant data and actions.
  • Structured relational data relationships between users, tasks, meals, trips, receipts, and roles.

My Contribution

I owned the complete system design phase, including both UI/UX and database architecture. I designed the full Figma prototype covering multiple dashboards and role-based interfaces, crafting distinct views for Admin (overview & management), Family Member (task/meal view), Staff (task execution), and Chef (meal planning). I created the relational database model including entities for users, roles, tasks, meals, trips, receipts, and their relationships, with proper normalization and constraint design for scalability.

I defined role-based access logic at the design level, ensuring each persona had appropriate permissions and view restrictions. I produced system workflow diagrams and interaction flows between modules, and ensured consistency between UI components and database structure to facilitate future implementation.

Capstone Social Impact Multilingual Laravel · Twilio

FarmPulse — Multilingual Agricultural Service for Tanzanian Farmers

A Laravel platform that delivers weather forecasts, market prices and crop recommendations to smallholder farmers in Tanzania through SMS, voice, and an accessible multilingual website (English, Swahili, Dutch).

Capstone — Thomas More
2025–2026
Full-stack contributor
Web · SMS · Voice

Context & Background

Capstone project at Thomas More (Geel, Belgium). The brief was to design and build a digital service for a real-world social problem: smallholder farmers in rural Tanzania often lose income to unpredictable rainfall, volatile crop prices, and limited internet access. The goal was a working prototype that could realistically reach farmers with feature phones, while serving as a credible demo for stakeholders, lecturers and external reviewers.

Features

  • 7-day weather forecasts for ten Tanzanian cities (Dar es Salaam, Arusha, Dodoma, Mbeya, Iringa, Mwanza, Morogoro, Moshi, Songea, Kigoma), pulled from OpenWeatherMap and aggregated into daily summaries with rain probability, temperature range, wind and storm warnings.
  • Daily market prices for maize, beans, rice, cassava and coffee, with up/down/stable trend indicators and recommended selling periods.
  • Rule-based crop recommendations combining weather signals (rain probability, storm warnings) and market trends into ranked planting advice with confidence scores.
  • Twilio SMS delivery: on-demand test messages, multi-day forecast SMS, and bulk market updates personalized per subscriber's selected crops and language.
  • Public demo dashboard with city selector, live data cards, an interactive USSD-style phone simulator, and a "simulate next day" tool.
  • Admin back office (session-based auth, role + active-status checks): weekly price management with idempotent upserts, and bulk SMS dispatch.
  • Multilingual UI (EN / SW / NL) with instant client-side language switching, including translation of database-driven values such as crop names, trend labels and dates.
  • Accessibility: in-browser text-to-speech via the Web Speech API on every section, light/dark theme, fully responsive layout.
  • Automated data pipeline — three Artisan commands wired to the Laravel scheduler keep weather (every 6 hours), prices (daily 00:10) and recommendations (daily 00:20) current without manual intervention.

My Contribution

I worked across the stack and took ownership of several core systems. I designed the domain schema (phone numbers, subscriptions, weather data, crop prices, recommendations, voice messages, admin users) and wrote the migrations, Eloquent models and the realistic 30-day seeder used for demos.

I built the FarmPulseAutomationService: it ingests OpenWeatherMap forecasts for ten cities, aggregates 3-hour entries into daily summaries, simulates daily price drift per crop with volatility profiles, and generates rule-based recommendations from the combined signals. I wired the Laravel scheduler to three Artisan commands so weather, prices and recommendations update on their own cadences.

I implemented the Twilio integration and three SMS flows on top of it — admin bulk send with per-subscriber language and crop personalization, on-demand test SMS, and N-day forecast SMS — along with a voice_messages outbox driven by each subscription's notification preferences. I also built the admin back office: login with role and active-status enforcement, the weekly market-price CRUD with idempotent upserts per market and effective date, and the bulk SMS dispatch screen. On the multilingual frontend I contributed the data-i18n convention, the dynamic translation layer for database values, and the in-browser TTS buttons and USSD-style phone simulator on the demo page.

Team Project Real-Time Multiplayer Vue · Express · Socket.IO Unity WebGL

Arcane-quiz — Multiplayer Quiz × Unity Arcade

A hosted multiplayer quiz in the spirit of Kahoot — but quiz answers feed in-game cash into a Unity WebGL "Space Invaders"-style mini-game running side-by-side in the same view.

Applied Computer Science
Real-time multiplayer lead
Render
spacequiz-1qak.onrender.com

Context & Background

Team project at Thomas More (Applied Computer Science). The brief was to deliver a hosted, multiplayer quiz experience in the spirit of Kahoot, but with a twist: the quiz had to drive the economy of an arcade-style mini-game. The deliverable is a deployable web app where one user hosts a quiz lobby, others join via a short code, and during play the quiz answers feed cash into a Unity WebGL game running in the same view.

Features

  • Quiz authoring: form-based editor for title, dynamic questions, variable-length choice lists, and per-question correct answers, persisted to Firebase Realtime Database under quizzes/{quizId}.
  • Catalog & hosting: a home page listing all stored quizzes and letting a host launch any of them as a new lobby.
  • Multiplayer lobbies: 6-character lobby codes generated server-side, a join screen for guests with username input, and a live waiting room with DiceBear pixel-art avatars.
  • Real-time gameplay: when the host starts, guests are routed into a split-screen view — Unity WebGL game on the left, quiz panel on the right. Correct answers grow a doubling streak (capped at 16) paid out as in-game cash; Unity reads that cash through window.getCashFromVue / window.deductCash JS bridges, and pauses/unpauses based on a per-round question quota that grows by 2 each round.
  • Live leaderboard: scores update over WebSockets while the round is running and are written through to Firebase under scores/{lobbyId}/{userId}, so the host's view stays sorted in real time and survives a refresh.
  • Lobby lifecycle: empty pre-game lobbies are deleted on the last disconnect, post-start lobbies are marked inactive, and a one-minute sweep purges inactive lobbies older than an hour.

My Contribution

I owned the real-time multiplayer layer end-to-end, across backend and frontend. On the backend (backend/server.js) I implemented the Socket.IO server, the in-memory lobbies store, and the full event protocol — createLobby, joinLobby, startGame, updateScore, endGame, getGameData, and disconnect. I wrote the lobby lifecycle rules (broadcasting playersUpdate, deleting empty pre-game lobbies, marking started ones inactive, and the 60-second cleanup sweep) and configured the origin allow-list for both Express and Socket.IO. I also built the persistence side of the leaderboard with POST /api/save-score and GET /api/scores/:lobbyId, modeled in Firebase under scores/{lobbyId}/{userId}.

On the frontend I built the four Vue views that drive the multiplayer flow — CreateLobbyPage.vue, ConnectPage.vue, LobbyPage.vue, LeaderboardPage.vue — and their Vue Router entries. That included the host/guest split via the ?host=true flag (host routes to the leaderboard on gameStarted, guests route into the Unity game with the quizId), the live roster with DiceBear avatars, the host-only Start and End Game controls, and the leaderboard view that merges an initial REST fetch with live scoreUpdate events.

Full Stack Essentials · 1ITF Team 207 Front-End + API Bootstrap · Vanilla JS

NitroDrive — Full-Stack Car Dealership Web App

A six-page Bootstrap front-end consuming a shared serverless REST API, simulating a multi-brand car dealership with maintenance, appointments and customer feedback — continuously deployed to Netlify via GitHub Actions.

Full Stack Essentials (1ITF WT)
2024–2025
Front-end (Cars / About) + back-end lead
nitrodriveee.netlify.app

Context & Background

Team project for the course Full Stack Essentials (1ITF WT, 2024–2025) at Thomas More, completed by a four-person team (Team 207). The brief was to build a multi-page website backed by a real REST API, simulating a multi-brand car dealership that also offers maintenance, appointments and customer feedback. Each team member owned a feature area; the project was version-controlled on GitHub and continuously deployed to Netlify via GitHub Actions.

Features

  • Homepage — autoplaying hero video, featured-car grid, services overview.
  • Cars — brand catalog (Mercedes-Benz, Ford, Chevrolet, Rolls-Royce, Lamborghini, Jeep), real-time search by model, live feed of customer requests, and a request-submission form.
  • About — company story, team profiles, FAQ accordion, and a preferences form (car type + features).
  • Maintenance — services and tips loaded dynamically from the API into Bootstrap cards and an accordion.
  • Contact — validated message form (regex email check, service-type selector) posting to the API, plus an embedded Google Maps location.
  • Appointments & Feedback — available time-slot loader with a simulated preloader, a testimonial feed with star ratings, and a testimonial-submission form.

My Contribution

I owned the Cars and About sections of the front end as well as the shared back-end API the entire team integrated against. I built student2page1.html (Cars) and student2page2.html (About) with a dedicated stylesheet and a single JS module (student2.js) handling all data integration. I implemented a client-side car search that fetches /cars, normalizes the API's tuple format into objects, and filters results live; a customer-requests feed backed by GET /customer-requests; and two validated submission forms posting JSON to /customer-requests and /additional-requirements. I designed the visual layout of both pages — brand grid, team profile cards, FAQ accordion — and curated the image assets used across the site.

I also designed and deployed the serverless REST API on Vercel under my account, defining the JSON contracts every teammate consumed (cars, services, tips, contact, bookings, testimonials, customer requests, additional requirements). This made me effectively the team's back-end lead.

Full Stack Essentials · 1ITF Team 207 FastAPI · PostgreSQL Serverless

Car Services & Catalog REST API — Team 207 Back-End

A shared FastAPI back-end serving the NitroDrive multi-page car-business website, deployed serverlessly on Vercel with a CI/CD pipeline through GitHub Actions.

Full Stack Essentials (1ITF)
2024–2025
Catalog & custom-orders owner · deploy lead
Vercel (@vercel/python)

Context & Background

Built for the course Full Stack Essentials (1ITF, 2024–2025) at Thomas More. Three developers collaborated on one FastAPI service deployed to Vercel, each owning the endpoints for their assigned page of the front-end (NitroDrive). The objective was to deliver a production-deployed REST API covering schema design, parameterized SQL, request validation, CORS and CI/CD — and to practise working as a team in a single shared repository.

Features

  • Services & contact — listing of services and maintenance tips, plus a contact-form endpoint with a typed ServiceType enum (Oil Change, Tire Service, Brake Service, Other).
  • Appointments & testimonials — read appointment bookings, filter by status, submit testimonials (with optional profile-picture fallback), read them back.
  • Car catalog & custom orders — full car listings, multi-filter search (model, price, features, engine, horsepower, 0–60 time), creation of new listings, and intake/read endpoints for additional-requirements and free-text customer-request submissions.
  • Auto-generated OpenAPI/Swagger docs at a configurable URL, environment-driven CORS, and continuous deployment to Vercel on every push to main.

My Contribution

I owned the car catalog and custom-order domain end-to-end. I designed the car_listing, additional_requirements and customer_requests tables and wrote the SQL in queries/student3_queries.py, plus the CarListing, AdditionalRequirement and CustomerRequest Pydantic schemas in models/student3_models.py.

In routes/student3_endpoints.py I implemented seven endpoints. The most substantive is GET /cars/search: a dynamic, injection-safe query builder that conditionally appends ILIKE and equality clauses for any subset of six optional filters while keeping every value bound through %s placeholders. I integrated my router into the shared FastAPI app in main.py and standardized response envelopes for the front-end ({"cars": …}, {"results": …}, {"success": …}).

I also owned the Vercel deployment — the production URL in the README runs under my account, configured via vercel.json and shipped automatically by the GitHub Actions workflow on every push to main.

Game Jam Team Project Python · Pygame Endless Runner

Escape the Darkness — Endless Runner Game

A 60 FPS Pygame endless runner shipped under a fixed Game-Jam deadline — control a severed foot fleeing through fog-covered, blood-grass terrain while a hand-drawn enemy closes in from behind.

Game Jam — Thomas More
Gameplay engine & main loop
1500×800 · 60 FPS
2 mini-games shipped

Context & Background

Built during a Game Jam course at Thomas More as part of a small student team working under a fixed time constraint. The brief was to design and ship a complete, playable game in Python from scratch, using only Pygame and standard libraries. The team produced two thematically linked horror mini-games in one repository: an endless runner (Escape the Darkness) and a carbon-footprint food-choice game (Carbon Kitchen).

Features

  • Cinematic intro and ending with line-by-line scrolling text and fade transitions.
  • Gravity-based player physics with a single-jump lockout and ground-snap collision.
  • Procedurally paced obstacle spawning with min/max-distance constraints.
  • Five-frame werewolf animation with a separate, fairness-tuned hitbox decoupled from the visual sprite.
  • Time-based Energy system with a colour-tiered HUD bar (green → yellow → red) and a low-energy warning.
  • Score + victory pipeline that transitions into a scripted ending sequence — clear obstacles, snap the player, frame-counted cabin reveal, "you survived the night".
  • Looping soundtrack with fade-outs on death and victory, plus graceful audio fallback.
  • Procedural atmosphere: parallax dark clouds, tombstones, dead trees, fog overlay, and four randomly selected background variants.

My Contribution

I owned the core gameplay engine and main loop of Escape the Darkness. I wrote the 60 FPS game loop in game_funcs/game.py — event handling, the update-draw pipeline, and the playing / won / lost / ending state machine. I built the Player class with gravity, single-jump lockout, sprite scaling and ground-snap collision, and centralized all tunables (gravity, jump strength, game speed, obstacle spacing, hunger rate, winning score) in sys_config.py so the team could iterate on game feel without touching logic.

I implemented the Obstacle class: a five-frame werewolf animation loader that mirrors and rescales frames at instantiation and decouples the visual sprite size from a smaller, centered hitbox for fairer collisions, plus procedural spawning with min/max distance constraints. I designed the Energy/Hunger system, the scoring + victory pipeline including the cinematic ending transition, and integrated the soundtrack via pygame.mixer with graceful fallback on missing audio and clean fade-outs.