Things I've
Built

A detailed breakdown of my work: products, open source libraries, academic projects and fundamentals. Each entry covers the problem, the engineering decisions, and the outcomes. I care about code that ships, systems that hold, and software that actually helps people.

Filter by

Product · EdTech · Multi-Agent Development

Ledgerline

Live

"A CFA Level I study app I built for my brother: summaries, timed quizzes and a study plan drawn from 1,091 resources, written and checked by a team of 94 AI agents so that every answer is correct and every claim has a source."

My brother is preparing for the CFA Level I exam. He had far more material than he could filter, learn and practise from: curriculum books, past and mock papers, a Q-bank and hundreds of lecture videos, all open in a browser tab he studied from. He asked how I could help, so I built him a study app.

Ledgerline gives him a short revision summary for every module of the ten exam topics, timed quizzes in the real exam format, a mixed mock weighted like the exam, and a day-by-day study plan sized to the days and hours he has. It is a lightweight Vue app with no backend and no accounts. It loads only what each page needs, works on a phone, and is checked for accessibility on every page in light and dark mode.

The hard part was not the interface but the content. A study app that shows a wrong answer or a wrong formula does more harm than no app at all, so every summary and every question had to be correct, written in its own words, and traceable to a page, a timestamp or a paper question. The build agent first worked through all 1,091 resources and wrote study notes. Other agents then wrote questions from those notes. Separate agents graded every question blind, without seeing the answer key, and any disagreement went back for a fix and a fresh grade. Reviewer agents also read the summaries against the curriculum books and corrected what was wrong.

I built it alone, spec-first with Claude Code and OpenSpec: I wrote the product spec and the feature list, reviewed every plan, made the product and content decisions, and directed the agents through each feature.

Role

Solo engineer · Spec author & reviewer

Method

Spec-driven · 94 agents · Claude Code + OpenSpec

Stack

Vue 3 · TypeScript · Vite · Tailwind CSS

The Agent Team

  • Builder: the main agent studied the material, planned each feature through OpenSpec, and wrote the app and its tests
  • Question writers: wrote original questions from the study notes, each citing a page in its own module
  • Blind graders: answered every question without the key, recomputing every calculation, so wrong or ambiguous keys showed up as disagreements
  • Re-graders: confirmed each fix with a fresh, independent grade
  • Curriculum reviewers: read summaries line by line against the 2027 books and corrected formulas, definitions and worked examples

Keeping the Content Right

  • Every summary section and every question cites a page, a video timestamp or a paper question
  • Mock and Q-bank questions are rewritten with new wording and new figures, and an automated check rejects any 12-word run copied from the material
  • Where sources disagree, the content follows the curriculum and the disagreement is recorded
  • Content checks run with the unit tests, covering citations, maths that must parse, answer balance and every module's question target

By the Numbers

  • 1,091 resources catalogued (166 books and notes, 112 papers and 813 videos), 626 of them usable, studied and cited
  • 6,520 practice questions, every one graded blind against its key
  • 94 agents: one builder and 93 writers, graders and reviewers
  • 18 features built in order, with 23 capability specifications kept beside the code
  • 427 unit and component tests and 296 browser tests across four browsers

What Was Built

  • Revision summaries for every module, with typeset formulas, worked examples and cited sources
  • Timed 90-question course quizzes, 20-question module quizzes and a weighted mixed mock, all fully usable from the keyboard
  • Results with the weakest modules first and a review of every answer with its explanation and sources
  • A day-by-day study plan with a checklist, built to the days and hours available
  • An exam-year switch for the 2026 or 2027 curriculum, and saved quiz scores
  • Sharing from the phone, link previews, and axe accessibility checks on every page

Technologies

Multi-Agent Development Spec-Driven Development Claude Code OpenSpec Vue 3 TypeScript Vue Router Vite Tailwind CSS KaTeX Vitest Playwright axe-core Netlify

Client Work · E-commerce · AI-Driven Development

Miteno

Beta

"A WhatsApp-ordering storefront for an independent UK clothing brand, built spec-first with an AI agent: fifteen features under my supervision, then nine more in a single unattended run."

Miteno is a beta e-commerce site for an independent UK clothing brand. The owner signs in to a private admin area to publish designs with photos, sizes, colours, stock and prices, and to manage collections and site content. Shoppers browse, search and fill a bag without an account, then press "Order on WhatsApp" to open a pre-filled message listing their items and the total. There are no online payments in the beta.

The project is also my case study in AI-driven, spec-driven development. I wrote the product spec and a build-ordered feature list, then drove Claude Code through OpenSpec one feature at a time: propose a change (proposal, requirement deltas, design and tasks), review it, apply it, then archive it so the requirements merge into a living specification. Nothing counted as finished until Pint, PHPStan and the full test suite passed.

Supervised: for the first fifteen features I reviewed every plan before any code was written, made the product and dependency decisions, and merged each feature through its own pull request. Unsupervised: once the cycle was proven, I handed the remaining nine features to the agent in one run. It built each on its own branch stacked on the last, checked its own plans, verified pages in a headless browser, and recorded every decision that needed me in a final "owner's list" feature for me to review afterwards.

Role

Engineer · Spec author & reviewer

Method

Spec-driven · Claude Code + OpenSpec

Stack

Laravel 13 · PostgreSQL · Alpine.js · Bootstrap 5

Spec-Driven Workflow

  • Propose: each feature starts as a written change with a proposal, requirement deltas with scenarios, a design and a task list
  • Apply: the agent works through the tasks, writing the tests alongside the code
  • Archive: the deltas merge into the main specification, which is validated strictly on every archive
  • Gate: formatting, static analysis and the full test suite must all pass before a feature is ticked
  • Guardrails: a short project rules file sets the stack, bans new dependencies without my approval and keeps the code simple
  • Deferred decisions: anything the agent could not verify or decide alone goes to an owner's checklist instead of being guessed

By the Numbers

  • 24 features built in order, from admin sign-in to launch readiness
  • 15 supervised features, 9 unsupervised in one run
  • 32 capability specifications, kept in the repository beside the code
  • 1,103 automated tests, with Pint and PHPStan clean

What Was Built

  • Admin area with two-factor sign-in, products, variants, photos, pricing, sales, stock and collections
  • Editable site content: banner, announcement bar, size guide and information pages with sanitised rich text
  • Shop and collection pages with size, colour and price filters, sorting and paging
  • Product page with gallery, zoom, variant picker and live stock
  • Search using PostgreSQL full-text search
  • Account-free bag kept in the browser and re-checked against live prices and stock
  • "Order on WhatsApp" and custom request messages built on the server
  • Meta and social tags, product structured data, sitemap and robots file
  • Security headers, an accessibility scan with axe-core and a launch-check command

Technologies

AI-Driven Development Spec-Driven Development Claude Code OpenSpec PHP 8.3 Laravel 13 PostgreSQL Laravel Fortify Blade Alpine.js Bootstrap 5 Vite Spatie Media Library Pest Pint Larastan Docker Render

Product · SaaS · Developer Tool

JCLcheck

Live

"A free JCL checker for people learning the mainframe — a custom lexer → parser → AST → rule-engine pipeline, a 3270-style workbench, and a CLI for CI. No mainframe connection required."

JCLcheck is a free online checker for z/OS JCL (Job Control Language), built for students and new mainframe developers who don't have a z/OS system to practise on. Paste JCL into the workbench and every problem appears straight away with its line and column, an error code, a plain-English explanation and a suggested fix. The checking is done by my own lexer, parser and rule engine, based on the IBM JCL Reference.

Since the first release it has grown into a full toolset: hover explanations for every keyword and value, a dataset-flow grid that follows each dataset through a job's steps, one-key formatting into the standard columns, site profiles and inline suppressions for a shop's own rules, shareable links, drafts, a z/OS level and JES picker, and a jclcheck command published on npm whose SARIF output shows problems on the right lines of a GitHub pull request.

Much of that second phase was AI-driven and spec-driven. Each feature was written up first — what it does, how it works and its tests — then planned as an OpenSpec change (proposal, spec deltas, tasks) and built with Claude Code as an AI pair programmer, against a regression suite of exact-diagnostic fixtures. I set the direction, answered the open questions on JCL behaviour, and reviewed and approved every change.

The workbench takes its look from classic IBM 3270 terminals, including a PF-key action bar (F1 Help · F4 Format · F5 Validate · F6 Share · F9 Sample · F12 Clear), so the interface itself teaches the conventions new mainframe developers need.

Role

Sole Engineer & Founder

Stack

Node.js · Express · Vue 3 · Vite

Process

Spec-driven · AI-assisted

What Gets Checked

  • Reading lines: 80-column records (71 for the statement, 72 for continuation, 73–80 ignored), comments, continuations including quoted strings resuming in column 16, in-stream data with DLM=, and exact positions on continued statements
  • Structure: several jobs per stream, JOB/EXEC/DD order, JCLLIB and NOTIFY placement, IF/THEN/ELSE conditions and their step references, PROC/PEND balance, and JES2 job groups with dependency-loop detection
  • Keywords and values: JOB/EXEC/DD and other statements against IBM JCL Reference tables, with Levenshtein "did you mean…" suggestions, positional limits, value rules, and DISP/SPACE/DCB/REGION/TIME/dataset-name syntax
  • z/OS levels and JES: keywords and statements checked against z/OS 2.3 to 3.2, with JES2 and JES3 control statements
  • Procedures and INCLUDE: in-stream and catalogued PROCs and INCLUDE members, symbolic &SYM parameters resolved per call, DD overrides and procedure steps
  • Dataset flow: temporary datasets read before they exist, passes nobody reads, datasets catalogued twice, reads after a delete, and referbacks to nothing
  • JCL inside JCL: jobs sent to the internal reader are checked as jobs of their own

Diagnostic System

  • Every diagnostic carries { code, severity, line, column, length, message, suggestion }, with a deliberate default severity per code so a job z/OS would reject is never shown as clean
  • 100 codes in groups such as JCLLxxx lines · JCLPxxx structure · JCLKxxx keywords · JCLSxxx values · JCLRxxx procedures · JCLCxxx IF conditions · JCLFxxx dataset flow
  • Editor with syntax highlighting, underlines under the exact text, a cursor column readout, and hover explanations linked to IBM's documentation
  • Inline //* JCLCHECK OFF-NEXT code suppressions and JSON site profiles for naming standards, allowed values and severities

Architecture

  • validator/ — the engine as its own zero-dependency package, published to npm as jclcheck: lexer, parameter tokenizer, parser, rule modules, formatter and CLI
  • backend/ — Express API (/api/validate, /api/format, /api/keywords) on Render, using the npm package
  • frontend/ — Vue 3 SPA on Netlify: landing page, about page and the dark 3270-themed workbench
  • Around 750 tests: exact-diagnostic fixtures and unit tests on Node's built-in test runner, plus Vitest component tests; ESLint on every package
  • Privacy by design: JCL is never stored, drafts stay in the browser, shared links carry the job after the #, and usage is counted anonymously with GoatCounter

Technologies

Node.js Vue 3 Express Vite npm Vue Router Custom Lexer AST / Parser Levenshtein Distance SARIF Vitest OpenSpec Claude Code IBM JCL Reference 3270 UI Design

Academic · Security · Dissertation

OWASP SecBank

Live

"The research artefact behind my BSc dissertation: one banking app built twice, once deliberately vulnerable and once hardened, then tested by people and by scanners."

OWASP SecBank grew out of the OWASP Top 10 talks I gave at DevFest Ogbomoso 2022 and DevFest London 2023. Later, my dissertation turned that talk into a controlled experiment around one question: how are OWASP Top 10 threats best managed in modern database-driven web applications?

The method is A/B. Version A (Insecure) deliberately implements all ten OWASP categories, from string-concatenated SQL and plaintext passwords to a vulnerable node-serialize cookie and an avatar upload that will fetch any URL. Version B (Secure) is the same application rebuilt with a specific, verifiable fix for each one. Both were deployed separately and tested under the same conditions by four manual penetration testers, SonarQube (SAST), OWASP ZAP (DAST) and Snyk (SCA), alongside a 24-respondent developer survey.

Role

Author & Researcher

Context

BSc Dissertation (6CS007) · P81

Stack

Vue 3 · Express 5 · PostgreSQL

A/B Methodology: What's Compared

  • Insecure: String-concatenated SQL in every controller
  • Secure: Parameterised queries throughout
  • Insecure: Plaintext passwords, hardcoded JWT secret, 30-day tokens
  • Secure: bcrypt (cost 12), secrets required at boot, 1-hour tokens stored server-side so logout revokes them
  • Insecure: Trusts user and account IDs sent by the client
  • Secure: Ownership checks and admin-only routes, 403 on mismatch
  • Insecure: Negative transfer amounts accepted
  • Secure: Joi validation on every input; transfers run in a database transaction with SELECT … FOR UPDATE
  • Insecure: node-serialize cookie deserialised on every request
  • Secure: Dependency removed; signed JSON cookie instead
  • Insecure: Avatar upload fetches any URL (SSRF)
  • Secure: HTTPS only, private and loopback ranges blocked, image types allowlisted
  • Insecure: Raw database errors returned, no logging
  • Secure: Generic error responses; Winston logs to rotating files and a system_logs table

Full Feature Set (Both Versions)

  • Registration, login and logout with token auth
  • Money transfer with recipient lookup by account number
  • Transaction history per account
  • Profile management, including avatar upload
  • Admin dashboard: all users, transactions and system logs
  • Users, accounts, transactions, system_logs and tokens tables via node-pg-migrate

Engineering & Research Notes

  • GitHub Actions run SonarQube (SonarCloud), Snyk and OWASP ZAP against both versions and publish comparison reports
  • ZAP API scan driven by the OpenAPI spec, authenticated with a fetched JWT
  • Manual test reports, scanner reports and survey responses kept in the repo's artefacts/ folder
  • Postman collection published; Swagger UI served at /api-docs
  • Frontends on Netlify, backends on Render
  • Findings and the full comparison are on the research page

Technologies

Vue 3 Express 5 PostgreSQL Node.js Pinia Bootstrap 5 Joi bcrypt Winston node-pg-migrate SonarQube Snyk OWASP ZAP GitHub Actions Swagger / OpenAPI Netlify Render

Academic · Full-Stack · RIA

FootballSite

Academic

"A full-stack football match tracker with live API sync, AJAX navigation, geolocation filtering, and social comments — graded 100/100."

Built for the 6CC001 Advanced Web Technologies module at the University of Wolverhampton, FootballSite is a dynamic football fixture and fan engagement platform. It integrates a live third-party football data API (API-Football v3), supports AJAX-driven browsing without full page reloads, and uses the browser Geolocation API to surface matches relevant to the user's location. Graded 100/100.

The architecture is deliberately lean — a custom service class centralises all outbound API calls, fixtures are cached in MySQL to avoid redundant requests, and the same controller method serves both full-page loads and AJAX partial updates by detecting $request->ajax() server-side. Lineups and match stats are fetched lazily on first visit and stored as JSON columns, keeping the database write load minimal.

Module

6CC001 Advanced Web Technologies

Grade

100 / 100

Stack

Laravel 12 · MySQL · Alpine.js · API-Football

Core Features

  • Daily fixture dashboard split into completed & upcoming
  • Live API sync — refreshes automatically for today/yesterday if stale >10 min
  • Match detail: starting XIs, substitutes, managers, comparative stat bars
  • AJAX search with 300ms debounce — no full-page reload on team name filter
  • AJAX date navigation — prev/next day updates match list in-place via Fetch API
  • Geolocation "Matches near me" using Browser Geolocation + BigDataCloud reverse geocode
  • Auth system — register, login, email verification, password reset, account deletion
  • Social comments per match — authenticated users only, displayed newest-first
  • Responsive design with collapsible mobile nav, fluid breakpoints
  • Custom 404 page with football-themed copy

Key Engineering Decisions

  • FootballApiService — dedicated service class for all API-Football calls; maps status codes to local ENUM
  • Smart sync: only re-fetches when date is today/yesterday & last sync >10 min old
  • Lineups & stats lazy-loaded on first match detail visit, cached as JSON columns
  • updateOrCreate throughout to prevent duplicate records on re-sync
  • Same controller action serves full-page load and AJAX partial (detects via $request->ajax())
  • Full PHPUnit test suite — Feature and Unit coverage across Auth, Profile, and core flows

Technologies

PHP 8.2 Laravel 12 MySQL API-Football v3 Blade Templates Alpine.js Tailwind CSS Fetch API (AJAX) Geolocation API Laravel Breeze PHPUnit Vite

Academic · Team Project

ColabDev

Academic

"An open day companion app for the University of Wolverhampton, built from scratch by a team of eight. It scored 96, the highest mark of the year."

Built for the 5CS024 Collaborative Development module, ColabDev is a web app for running university open days. Prospective students browse events and FAQs and register to attend, while staff manage everything from an admin dashboard. The team of eight was split across development, security, business and project management. I led the four-person development team, covering frontend, backend, database and DevOps, and worked hand in hand with the security and business teams and the project manager.

The Flask API is layered into routes, controllers, services and SQLAlchemy models over PostgreSQL, with schema changes tracked in Alembic migrations. Each registration captures personal, contact, course interest and event details, then sends HTML emails over Brevo SMTP: a confirmation to the applicant, a notification to admissions, and a separate email to a parent or carer when their details are given.

Role

Lead, 4-person dev team

Module

5CS024 Collaborative Development

Grade

96 · Highest of the year

Core Features

  • Open day registration with nested field validation
  • Events listing, grouped by date
  • Public FAQ page
  • Applicant, admissions and carer emails on every registration
  • Admin dashboard to create, edit and delete events and FAQs
  • Admin views of registrations and staff, plus adding new staff accounts

Engineering Decisions

  • Flask blueprints → controllers → services → models, one module per domain
  • JWT auth with tokens stored server-side, so logout revokes the session
  • Passwords hashed with PBKDF2-SHA256 via Werkzeug
  • Five Alembic migrations tracking every schema change
  • OpenAPI spec served through Swagger UI, plus a Postman collection
  • Vue Router guards on every admin route, backed by a Pinia auth store
  • API on Render, deploying automatically from main; SPA on Netlify

Technologies

Python Flask PostgreSQL Vue 3 SQLAlchemy Alembic PyJWT Pinia Vue Router Vite Axios Brevo SMTP Swagger / OpenAPI Render Netlify

Product · Open Source

IslamicHub

Live

"A free, open-source Islamic education and tools platform: scholarly guides to the Five Pillars alongside a Zakat calculator, prayer times engine and inheritance calculator."

IslamicHub is a free Islamic education and tools platform built for Muslims seeking accurate, well-sourced religious guidance online. The problem: most Islamic sites are either overly simplified, source-poor, or built without real attention to the differences between schools of thought. IslamicHub treats religious accuracy as a hard requirement, not an afterthought.

Every feature — from the prayer times calculation to the inheritance calculator — is grounded in Qur'an, Hadith, and cross-referenced with all four major schools of Islamic jurisprudence (Hanafi, Maliki, Shafi'i, Hanbali). The platform is co-founded with Yusuf Saif and is actively used and maintained.

Role

Co-founder & Lead Engineer

Timeline

2026 – Present

Stack

Vue 3 · Vite · Pinia

Core Features

  • Accurate prayer times with Qibla direction finder
  • Zakat calculator with live gold & silver prices
  • Islamic inheritance calculator
  • Live API-driven Hijri calendar
  • Five Pillars guides grounded in primary sources
  • Cross-school jurisprudence references throughout
  • Extensive Hadith library

Engineering Decisions

  • Migrated from the original design in HTML, CSS, and JavaScript to Vue 3 Composition API
  • Pinia for predictable, modular state management
  • Live external API integration for financial data (Zakat)
  • Structured content architecture for multi-madhab content

Technologies

Vue 3 JavaScript Pinia Vite Vue Router REST APIs Responsive HTML & CSS

Product · Developer Tool

Kueri

Building

"TablePlus meets Cursor — an AI-native desktop database client for developers."

Most database clients are UI wrappers around SQL. Kueri is an IDE-style tool — you can write queries the traditional way, or describe what you want in plain English and let the AI generate and explain the SQL. It's positioned at the intersection of developer tooling and AI assistance, for teams that already know SQL but want to move faster.

Built during a focused 10-day pivot from concept to MVP. Currently in active development, with a pre-seed pitch deck, AI cost-reduction roadmap, and launch strategy in progress. Supports PostgreSQL, MySQL, MongoDB, and SQLite.

Role

Solo founder & Engineer

Timeline

2025 – Present

Stack

Electron · Vue 3 · Tailwind · Gemini

Core Features (MVP)

  • Natural language → SQL query generation
  • AI query explanation for onboarding & learning
  • Multi-database support (PG, MySQL, MongoDB, SQLite)
  • IDE-style interface with schema explorer
  • Connection management with encrypted credentials
  • Query history and saved snippets

Key Engineering Challenges

  • AI token cost optimisation across query volumes
  • Cross-database query normalisation layer
  • Electron IPC architecture for secure DB connections
  • Context-aware prompt engineering for schema-aware AI

Technologies

Electron Vue 3 Google Gemini Tailwind CSS PostgreSQL MySQL MongoDB SQLite Node.js

Academic · Big Data

ScholarSearch

Academic

"A full-stack academic search engine over an arXiv dataset — built for a Big Data module."

ScholarSearch is a research paper discovery tool built as a university project for a Big Data module (6CS030). The system ingests a large arXiv dataset into Elasticsearch, exposing a fast full-text search API via FastAPI, consumed by a Vue 3 frontend.

The project required not just engineering but academic rigour — including a Literature Review covering information retrieval systems, an IEEE-formatted report, and multiple audit passes to catch bugs including XSS via v-html, pagination edge cases, sort value mismatches, and null pointer crashes.

Role

Lead Engineer & Author

Module

6CS030 — Big Data

Dataset

arXiv research papers

Technical Highlights

  • Elasticsearch for full-text search at scale
  • FastAPI backend with pagination & filtering
  • Vue 3 Composition API frontend
  • XSS remediation (v-html audit)
  • arXiv dataset ingestion pipeline
  • IEEE-formatted academic report

Technologies

Vue 3 FastAPI Elasticsearch Python arXiv Dataset Docker

Academic · AI · Complex Systems

ACO Agent

Academic

"An agent in a Unity world that plans its route with Ant Colony Optimisation, written from scratch, with a Gemini assistant and an on-device image classifier alongside it."

Built for the 6CS014 Complex Systems module at the University of Wolverhampton. Waypoints placed in a 3D Unity scene are joined into a fully connected graph, and a colony of simulated ants searches it for the shortest tour. Each ant picks its next waypoint by weighing pheromone against distance, and after every round the three best tours lay down fresh pheromone while the rest evaporates. Once the colony settles, an agent walks the highest-pheromone route through the scene.

Every ant's tour is logged to a file, so convergence can be measured, not just watched. With 25 ants on a 10-waypoint graph, the average tour fell from 334.8 to 297.7 units, and by round 10 every ant was taking the same optimal tour. The project also covers two other kinds of AI in Unity: a Gemini assistant that answers questions from a small built-in knowledge store, and MobileNet image classification running on the GPU.

Module

6CS014 Complex Systems

Result

Converged in 10 rounds

Stack

Unity · C# · Gemini API · ONNX

Core Features

  • Ant Colony Optimisation over a graph built from the scene's active waypoints
  • Agent moves and turns smoothly along the chosen route
  • Route and pheromone levels drawn in the Unity editor; selecting a waypoint shows its connections
  • Per-round log of every ant's start node, tour length and path
  • Gemini 2.5 Flash assistant that looks up facts before answering
  • MobileNet classifier returning top-3 ImageNet labels with confidence

Key Engineering Decisions

  • Pheromone and distance weights (α, β), evaporation and Q kept as named parameters for tuning
  • Only the three best ants deposit pheromone each round, which speeds up convergence
  • Ties between equally likely paths go to the shorter connection
  • Final route follows the strongest pheromone trail, with a cap on path length
  • Image normalisation folded into the model graph, so the GPU does the preprocessing
  • Tensors and workers disposed on teardown to avoid GPU memory leaks

Technologies

C# Unity Ant Colony Optimisation Gemini API Unity Inference Engine MobileNet (ONNX) UnityWebRequest Newtonsoft.Json LINQ

Academic · Robotics

Robot Navigation

Academic

"Simulated robots that follow lines, solve mazes and steer around obstacles, controlled from Python in CoppeliaSim."

A series of robot programming tasks for the 5CS036 module, each one building on the last. A Python wrapper class around CoppeliaSim's remote API turns motor and sensor handles into simple calls like move_forward() and left_sensor(). Every robot behaviour is written against that wrapper, not against the raw API.

The tasks moved from purely reactive control to structured decision-making. First a three-sensor line tracer, then a robot that solves a line maze by following the left wall, then a DR20 robot that uses infrared and ultrasonic sensors to get through a winding course. The last version swaps hand-written if/else logic for a behaviour tree: a selector tries "go forward if clear" first, then "turn towards the more open side".

Module

5CS036

Robots

Line tracer · DR20

Stack

Python · CoppeliaSim · Jupyter

Core Features

  • Line following with three downward-facing vision sensors
  • Left-wall maze solving, with dead-end U-turns and end-of-maze detection
  • Obstacle avoidance on the DR20 using five infrared and ultrasonic sensors
  • Behaviour-tree navigation built from condition and action nodes
  • Screen recordings of each robot running its course

Key Engineering Decisions

  • Wrapper class keeps the remote API calls apart from the robot's behaviour
  • Robot behaviour exposed as an overridable method, so strategies can be swapped through inheritance
  • Behaviour-tree nodes share sensor readings through a common data store, so each tick reads the sensors only once
  • Selector of sequences gives a clear priority order: forward, then left, then right
  • Time limit on every control loop so a stuck robot can't hang the simulation

Technologies

Python CoppeliaSim (V-REP) Behaviour Trees Remote API NumPy Jupyter

Academic · High-Performance Computing

Parallel Computing in C & CUDA

Academic

"The same problems solved three ways, with POSIX threads, OpenMP and CUDA, from counting words to cracking passwords on a GPU."

Coursework from two modules, 5CS021 Numerical Methods and Concurrency and 6CS005 High Performance Computing, all written in C. Each program takes its thread count as an argument and splits the work evenly, handing any leftover items to the first threads.

On the CPU: a multithreaded word-frequency counter, an estimate of π from the Leibniz series, polynomial evaluation, box blur over PNG images, and a set of OpenMP matrix operations (element-wise maths, transpose and multiplication). On the GPU: a Sobel edge detector with one CUDA thread per pixel, and a brute-force password cracker that gives each password its own block and spreads the 67,600 candidates across that block's threads.

Modules

5CS021 · 6CS005

Models

pthreads · OpenMP · CUDA

Language

C / CUDA C

Core Features

  • Sobel edge detection on RGBA PNGs, run on the GPU
  • GPU brute-force reversal of an encryption scheme over every letter-letter-digit-digit password
  • OpenMP matrix add, subtract, multiply, divide, transpose and product, with shape checks
  • Word-frequency counter over a large text dataset, using pthreads
  • π from the Leibniz series and multithreaded polynomial evaluation
  • Multithreaded box blur on PNG images, plus linear regression from data files

Key Engineering Decisions

  • Even work split with remainder handling, so no thread gets more than one extra item
  • Each thread sums its own share before taking the mutex once to add it to the total
  • OpenMP thread count capped at the number of rows, so no threads sit idle
  • CUDA password search uses a grid-stride loop, so any block size from 1 to 1024 works
  • Sobel edges clamped to the image border, and alpha forced opaque on output
  • All host and device memory freed explicitly

Technologies

C CUDA OpenMP POSIX Threads LodePNG CMake Image Processing Numerical Methods

Open Source · CLI · Agentic Development

konvertoj

Live on npm

"A private, local file converter, like FreeConvert but nothing is uploaded: 149 modes for images, iPhone photos, PDFs, GIFs, video and audio, built spec-first by a team of AI agents that I directed, and released as 1.0.0 with npm provenance."

konvertoj (Esperanto for "to convert") is a command-line tool that converts and edits files on your own computer. npx konvertoj -m heictojpg holiday.heic turns an iPhone photo into a JPG with nothing to install but Node.js. It converts between JPG, PNG, WebP, AVIF, GIF, TIFF, BMP, ICO, HEIC and SVG; resizes, compresses, crops, rotates and strips location data; turns images into PDFs and PDF pages into images; makes GIFs; and converts video to MP4 and extracts audio. Video uses FFmpeg: an installed copy, or a checksummed add-on that konvertoj downloads once, only after asking.

I built it to solve a problem I had: converting files without uploading them to a website. It was developed through spec-driven, agentic development. I wrote the product spec, a build-ordered list of 20 features and the agent's rules, then directed Claude Code through OpenSpec: every feature was proposed, checked by a reviewer agent, built, regression-tested by a second agent and archived into a living specification.

Unsupervised: features 5 to 19 were built in a single run, each on its own branch. Human in the loop: I stayed in the loop by testing and validating the output at every stage, through to the release.

Role

Sole Product Engineer

Method

Spec-driven · Agentic · Claude Code + OpenSpec

Stack

TypeScript · Node.js · sharp · pdf.js · FFmpeg

Agentic Workflow

  • Propose: each feature starts as an OpenSpec change with a proposal, requirement deltas, a design and tasks, validated strictly
  • Review: a reviewer agent checks the plan against the spec and feature list, and the plan is revised until it is approved
  • Apply and gate: code and tests are written together; formatting, type checks, linting, tests and the build must all pass
  • Regression: a tester agent re-checks every feature built so far on real files and reports confirmed bugs, which are fixed before archiving
  • Archive: requirement deltas merge into 25 capability specifications kept beside the code
  • Agents: 1 orchestrator and 30 sub-agents (plan reviewers and regression testers)
  • Safety: the entire agentic process ran in a sandboxed environment on the principle of least privilege; sub-agents could only read and test, never edit, commit or publish

Architecture

  • Mode registry: the single source of truth for every mode; help, --list-modes, input checks, suggestions and the README are generated from it
  • Pipeline: argument parsing → input planning and safe output naming → format detection from file contents → parallel batch runner → reporter with exit codes
  • Converters: sharp, heic-decode, bmp-ts, decode-ico and a custom ICO encoder for images; pdf-lib and pdf.js for PDFs; exifr for metadata
  • Video add-on: FFmpeg from the PATH or a pinned, checksummed download, with proxy support and no shell
  • Safe by default: originals are never modified, outputs are written atomically, and nothing is overwritten without --overwrite

Quality & Release

  • 937 Vitest tests, including every README and help example run as a test
  • CI on Windows, macOS and Linux, plus clean-install smoke tests on 5 platforms × 3 Node.js versions with install-size and start-up-time budgets
  • Released from a GitHub Actions tag with npm provenance, staged publishing approved with two-factor authentication, then tokenless trusted publishing

Technologies

Agentic Development Spec-Driven Development Claude Code OpenSpec TypeScript Node.js sharp pdf-lib pdf.js FFmpeg Vitest GitHub Actions npm Provenance

Open Source · npm Package

toRoman

Published

"A zero-dependency library for Roman numeral operations — shipped with a full interactive docs playground."

toRoman is a lightweight TypeScript library for converting between Arabic integers and Roman numerals, validating Roman numeral strings, and performing arithmetic entirely in Roman notation. What started as a focused utility grew into a full-featured package with a rich API and a custom-built interactive documentation site.

The library handles edge cases the obvious implementation misses — invalid character sequences, repetition limits per Roman character, subtractive notation rules — all enforced with clear, typed error messages. The accompanying docs playground lets users try every API method in the browser without setup.

Role

Author & Maintainer

Distribution

npm · CDN (unpkg)

Stack

TypeScript · Zero deps

API Surface

  • toRoman(n) — integer → Roman
  • fromRoman(s) — Roman → integer
  • isRoman(s) — full validation
  • addRoman / subtractRoman
  • multiplyRoman / divideRoman
  • rangeRoman / tableRoman

Technologies

TypeScript npm Vanilla JS Zero dependencies Custom Docs Site

Open Source · npm Package · CLI

jclcheck

Published

"Check z/OS JCL from a terminal or a CI pipeline — the JCLcheck engine as a zero-dependency npm package."

jclcheck is the validation engine behind JCLcheck, published on its own so mainframe teams that keep JCL in Git can check it before it ever reaches z/OS. It reads JCL the way z/OS does and reports each problem with its line and column, a code, a plain-English explanation and a fix, with no mainframe connection and no dependencies.

npx jclcheck "jcl/**/*.jcl" --format sarif writes SARIF 2.1.0 that GitHub code scanning shows on the right lines of a pull request, and exit codes fail the build on errors. The same package formats JCL into the standard columns, and can be used as a library. Like the rest of JCLcheck, it was built spec-first with AI assistance.

Role

Author & Maintainer

Distribution

npm · npx

Stack

Node.js · Zero deps

Command and API

  • jclcheck <files> — text, JSON or SARIF output; exit 0, 1 or 2 for CI
  • --zos / --jes — check against z/OS 2.3–3.2, JES2 or JES3
  • --library — catalogued PROCs and INCLUDE members from a folder
  • --profile — a site profile for naming standards and severities
  • jclcheck format — lay JCL out in the standard columns
  • validate() / format() — the same engine in your own code
  • Opt-in, anonymous usage counting that respects DO_NOT_TRACK

Technologies

Node.js npm CLI SARIF 2.1.0 GitHub Actions Zero dependencies z/OS JCL

Fundamentals · Data Structures & Algorithms

DSA Practice

Practice

"Classic data structures and algorithms written from scratch in PHP and TypeScript, with tests and Big-O notes for each."

DSA Practice is where I build the fundamentals by hand instead of reaching for built-ins, working through PHP 7 Data Structures and Algorithms alongside articles and videos. The PHP side is a Composer package using PHP 8 typed properties and union types, tested with PHPUnit. The TypeScript side covers searching and sorting, tested with Jest. The README records the time and space complexity of each structure.

Alongside it, my snippets repo holds 59 solutions to HackerRank, LeetCode and freeCodeCamp problems in TypeScript and PHP, from Two Sum and Group Anagrams to Product of Array Except Self and Median of Two Sorted Arrays.

Role

Author

Languages

PHP 8 · TypeScript

Testing

PHPUnit · Jest

Data Structures (PHP)

  • Linear, circular and doubly linked lists on a shared abstract base that implements Iterator, so lists work in foreach
  • Stacks backed by an array (with overflow and underflow exceptions) and by a linked list
  • Binary search tree with insert, search, and delete via in-order successor
  • Binary max heap with trickle-up insert and trickle-down delete
  • Hash table, reused as the child map inside the trie
  • Balanced-bracket checker as a stack application

Algorithms (TypeScript)

  • Linear search, ordered linear search and binary search
  • Bubble, selection and insertion sort
  • Quick sort and quickselect with in-place partitioning
  • Table-driven Jest tests for every algorithm

Technologies

PHP 8 TypeScript PHPUnit Jest Composer Big-O Analysis

Experiment · Logistics · Full-Stack

Shipping Label Management System

Complete

"A secure, role-based shipping label manager with a web dashboard and a token-authenticated REST API, both backed by the same authorisation policies."

A time-boxed Laravel build for managing shipping labels. Standard users sign in, create shipments with a customer name, delivery address and courier, and manage their own shipment history. Admins get a separate dashboard with full courier management, a system-wide view of every shipment and a list of registered users.

The same features are exposed through a RESTful API secured with Laravel Sanctum tokens. Authorisation lives in policies rather than controllers, so the web routes and the API enforce identical rules: standard users only ever see their own shipments, and couriers that still have shipments cannot be deleted.

Role

Sole Engineer

Auth

Breeze (web) · Sanctum (API)

Stack

Laravel 13 · MySQL · Tailwind CSS · Alpine.js

Architecture

  • Thin controllers: controllers only coordinate input, domain logic and responses
  • Form requests: validation and request-level authorisation sit in dedicated request classes
  • Policies: courier and shipment policies give one source of truth for permissions across web and API
  • API resources: a transformation layer keeps database columns out of the public JSON contract
  • Backed enum: user roles are a PHP enum, removing magic strings
  • Schema constraints: unique courier codes, restrict-on-delete for couriers and indexed foreign keys

Testing

  • Pest suite covering authentication, role-based routing and middleware boundaries
  • Courier and shipment CRUD, validation rules and delete-constraint protection
  • API contract tests for status codes (200, 201, 401, 403, 422) and cross-user data isolation

Technologies

Laravel 13 REST API RBAC PHP 8.3 MySQL Laravel Sanctum Laravel Breeze Blade Tailwind CSS Alpine.js Vite Pest

Experiment · Charity · Full-Stack

Be Kind Initiative

Live

"A full-stack web presence for a Lagos-based charity — with a contact form that saves to MongoDB and sends email notifications in real time."

Be Kind Initiative is a Lagos-based NGO working to reduce poverty, train youth in leadership and volunteering, and support under-resourced communities across Nigeria. The project needed a public-facing website to expand reach and support grant applications.

Built with Node.js, Express, and EJS templating, the site includes a multi-page layout (Home, About, Contact), a Bootstrap-powered responsive carousel, and a contact form that persists submissions to MongoDB and triggers an email notification to the organisation via Nodemailer — giving the team a real-time inbox alert for every inquiry.

Role

Main Developer

Client

Be Kind Initiative, Lagos

Stack

Node.js · Express · EJS · MongoDB

Features

  • Multi-page site: Home, About, Contact, 404
  • Bootstrap 4 responsive carousel on homepage
  • Contact form with name, email, and message
  • MongoDB persistence via Mongoose for all submissions
  • Real-time email alerts to the org via Nodemailer
  • Custom 404 page with styled error handling

Engineering Notes

  • Express routing with separate GET/POST handlers
  • EJS partials (header/footer) for DRY templating
  • Per-page CSS loaded dynamically via EJS locals
  • Mongoose schema with timestamps and optional name field
  • Morgan HTTP request logging in development
  • Environment config via dotenv for DB URI and port

Technologies

Node.js Express MongoDB Mongoose EJS Nodemailer Bootstrap 4 Morgan dotenv Render

Experiment · Productivity

ZTodo

Live

"A clean, distraction-free todo app — built to explore Vue 2, Vuetify, and the full Vue CLI ecosystem."

ZTodo is a todo application built with Vue 2 and Vuetify, deployed as a Progressive Web App. The project was a deliberate exercise in learning the Vue CLI ecosystem end-to-end — from component architecture and Vuex state management, to routing, service workers, and PWA configuration for offline support.

Each todo supports a title and an optional body for additional context, and the interface handles inline editing by clicking an existing item — a small UX detail that keeps the workflow keyboard-friendly and fast. Clean, focused, and ships with zero build warnings.

Role

Author

Deployment

Netlify · PWA

Stack

Vue 2 · Vuetify · Vuex · Vue Router

Features

  • Create todos with optional detail body
  • Inline edit by clicking any existing item
  • Delete individual todos
  • Completion checkbox state per item
  • Offline support via service worker (PWA)
  • Enter key submission for keyboard-first flow

Engineering Notes

  • Vuex store wired for global state management
  • Vue Router with history mode and 404 fallback
  • Service worker registered via register-service-worker
  • Full PWA manifest with multi-size icon set
  • Vuetify Material Design component library
  • ESLint configured with Vue essential rules

Technologies

Vue 2 Vuetify Vuex Vue Router PWA Service Workers Netlify JavaScript Babel

Experiment · CLI

Node Image Finder

Experiment

"My first command-line tool: search Unsplash from the terminal and get clickable image and download links back."

A small Node.js CLI that takes a search term and an optional orientation, queries the Unsplash API, and prints the top ten results as clickable terminal hyperlinks, each with a direct download link. Flags are parsed and validated with yargs, so a missing search term or an unsupported orientation fails with a clear usage message instead of a stack trace.

Role

Author

Type

Node.js CLI

Stack

Node.js · yargs · Unsplash API

Features

  • -s / --search: required search term
  • -o / --orientation: landscape, portrait or squarish
  • Ten results per search, titles linked to full-size images
  • Download link for every image
  • Installs as a global zubs command via the bin field
  • API key kept out of the code with dotenv

Technologies

Node.js JavaScript yargs Unsplash API chalk boxen terminal-link dotenv

Experiment · Utility

GPCalc

Utility

"A GPA/CGPA calculator that supports multiple grading scales — built because the existing ones were too rigid."

GPCalc is a GPA and CGPA calculator utility built for students who need to quickly compute grade point averages without wrestling with inflexible tools. It supports different grading scales across institutions and handles the running CGPA calculation across multiple semesters.

Role

Author

Type

Student utility

Users

Students

Technologies

JavaScript HTML/CSS

Experiment · AI-Paired

BrickBreaker Challenge

Experiment

"An experiment in human-AI co-authorship — building a game with an AI pair programmer."

A fully playable Brick Breaker game built in collaboration with an AI pair-programmer. The project was an intentional exploration of human-AI co-authorship in game development: where does the human add value, where does the AI excel, and what does the handoff look like?

Beyond the game itself, this is a study in prompt engineering, AI output review, and the pragmatics of building software with generative tools — a skill set increasingly relevant across the industry.

Role

Lead + AI co-author

Type

Browser game

Stack

Vanilla JavaScript · Canvas API

Technologies

JavaScript HTML5 Canvas AI-assisted dev

Want to talk about
working together?

Send me an email ↗ Read testimonials → Download CV ↗

← Back to portfolio