Ojo Ifeanyi Ukiwe

Projects

Projects I’ve designed and built myself, from an accessibility auditing tool that became my MSc research to a tested SvelteKit map application. Each case study covers the problem, what I built, a decision I made and what I learnt.

PHP 8.2 (OOP, PDO) · MySQL · JavaScript · Chart.js

WebAudit: accessibility auditing tool

Enter a public web address and WebAudit runs 15 automated WCAG 2.1 AA checks, explains each issue with the offending HTML and a fix, scores the page out of 100 and tracks the score over time.

WebAudit dashboard showing 3 audits run, 33 critical issues, an average score of 63 and 1 project; a score trend rising from 0 to 100 then 89 across three runs; a doughnut chart of issues by severity; and a recent audits table for gov.uk (89), the W3C demo after page (100) and the W3C demo before page (0)

The problem

Accessibility reports are often long lists of errors. Developers struggle to see what matters most, so serious problems stay unfixed.

What I built

An object-oriented PHP audit engine using DOMDocument and XPath, a JSON API, and a six-table MySQL schema with foreign keys. Every query that uses input is a prepared statement.

A decision I made

Because the tool fetches any address a user types, I protected it against server-side request forgery: only public http and https addresses are allowed, private ranges are blocked, and every redirect is checked again.

What I learnt

Auditing my own React app gave a perfect score, because the crawler only sees the empty root element before JavaScript runs. I documented the limitation and planned a warning for JavaScript-rendered pages.

SvelteKit · Svelte 5 · TypeScript · MapLibre GL JS · Tailwind CSS · Vitest

North East Places: accessible map

An interactive map of towns across North East England, with a searchable list beside it. Selecting a place in the list flies the map to it, and clicking a marker highlights it in the list.

North East Places: a street map zoomed in on Hartlepool with its popup open, beside a search box showing 10 places found and Hartlepool highlighted in the list.

The problem

Interactive maps are hard or impossible to use with a keyboard or a screen reader, so the information on them is often out of reach for the people who need it most.

What I built

A SvelteKit app using Svelte 5 runes. One piece of shared state keeps the MapLibre map and the place list in sync in both directions, and a search filters the list by town or county. The search logic is a separate function covered by five Vitest unit tests.

A decision I made

I built the list as the accessible alternative to the map, not an afterthought: real buttons with aria-pressed, a labelled search box, and a results count that screen readers announce as you type.

What I learnt

The map worked in development but its tiles were blank in production. I traced it to MapLibre's background worker, whose path broke when the build bundled the library, and fixed it by importing the worker as a URL. Now I always check a production build locally before deploying.

PHP · MySQL · JavaScript · HTML · CSS

Padfect Store: gaming e-commerce platform

My highest-scoring MSc project: an online shop where gamers can browse and buy gaming accessories, with customer accounts, live search, a cart, checkout and an admin dashboard for managing orders.

Padfect Store home page: a purple navigation bar with Home, Product, Cart, Search, Contact, Resources, Login and Admin links, above a photo of a white game controller on a bowl of tortilla chips, with the heading "Everything Game", the tagline "Fascinating. Fun. Affordable." and a Shop Now button.

The problem

Gamers needed one place to find accessories, compare them and buy them, and the shop needed a simple way to manage orders.

What I built

A full-stack PHP application with sign-up and login using hashed passwords, separate session-based access for customers and admins, and a six-table MySQL database (users, admins, products, cart, orders and order items) queried with joins.

A decision I made

I made the PHP endpoints return JSON, so JavaScript could update the search results and cart without reloading the page, and I used prepared statements for every query that takes user input.

What I learnt

Looking back, the white tagline over a busy hero photo does not meet colour contrast requirements. Since specialising in accessibility, I check contrast while designing rather than after.

React · Tailwind CSS · Node.js · Express · MongoDB · Vercel

Infinisculpt: booking platform for a local business

A full website and booking system I built, unpaid, for a local beauty business, so customers could choose a treatment and book a time online.

Infinisculpt home page: a navigation bar with the IS Sculpt logo, a 24-hour badge and Book, Express, Gallery and Find Us links, above a large nail-polish bottle image with the heading "Enhance Your Natural Beauty", the line "Premium nail, lash and beauty treatments tailored just for you" and a Book Now button.

The problem

The business needed customers to book treatments online without the risk of two people booking the same slot.

What I built

A five-step booking journey backed by a REST API, with an admin area secured by bcrypt and JWT, a CORS allowlist, a health-check route and clear error responses.

A decision I made

I generated the available slots and checked for overlaps on the server, not in the browser, so double bookings could not happen even if two customers booked at the same moment.

What I learnt

Working for a real client taught me to turn their needs into features and to keep the booking journey simple for customers on their phones.

Next.js · TypeScript · Tailwind CSS · Jest · GitHub Actions

Foodash: delivery app for corner shops (in progress)

A delivery app for local corner shops, which I'm building the way a professional team would: planned on a Jira board, with unit tests and a CI pipeline from the start.

The problem

Local corner shops rarely have a simple way to take orders for delivery, so customers go to larger chains instead.

What I built

So far: postcode validation covered by Jest unit tests, and a GitHub Actions pipeline with branch protection and preview deployments.

A decision I made

I set up testing and continuous integration before building features, so every change is checked automatically from the first commit.

What I learnt

Planning work in sprints on a Jira board has helped me break a large app into small, testable pieces.