skip to content
~/portfolio
~/portfolio:~$ cat about.txt

I ship web apps that handle payments and keep running when load spikes.

Full-stack freelancer. I take a small number of live-event and payment projects at a time, and finish them.

[online] open to work

// selected work

~/work/selected-projects

Apps I've shipped

Live scoring, academy software, seat locks. Production, not demos.

sts-competition.com
Special Talent Stars● production
live-scores|connected
#contestantscorestatus
01Team Alpha94.2live
02Team Beta91.8live
03Team Gamma89.5live

Special Talent Stars

sts-competition.com ↗

problem

500+ people voting at once during a live event. Scores and sign-ups had to stay in sync — nothing could drop.

built

Scoring dashboard and registration over WebSockets. Uploads go to object storage through signed URLs, not through the app server.

ReactTypeScriptNode.jsWebSocketsPostgreSQLAWS
▸ 500+ concurrent users▸ scores stay in sync live▸ signed-URL uploads

01/03

solo-arts-academy.com
Solo Arts Academy● production
academy-dashboardmarch 2026
MTWTFSS12345678910111213141516171819202122232425262728

Solo Arts Academy

solo-arts-academy.com ↗

problem

The academy ran on spreadsheets. Staff and students needed one app, and the academy needed to take payment.

built

Portals and attendance for the academy. Fawry and X-PAY integrated as payment gateways. Postgres and auth on Supabase; Firebase for the live bits. Roles are enforced on the server.

Next.jsTypeScriptSupabaseFirebaseFawryX-PAY
▸ 3 roles, server-side RBAC▸ Fawry & X-PAY gateways▸ idempotent charges

02/03

// private tool
Event Booking & Ticketing● private
seat-map12 seats locked

Event Booking & Ticketing

// private tool

problem

Two people clicking the same seat at the same time. You know the race condition.

built

Seat map over WebSockets. The lock lives on the server; the map is just a view of it.

ReactTypeScriptWebSocketsFirebaseAWS
▸ server-side seat locks▸ no double-bookings

03/03

// process

~/notes/how-i-work

How I keep production from eating itself

Same threat model on a scoring night, a seat map, and a payment webhook. Cybersecurity degree in progress — this is what I actually ship.CCST Cybersecurity (Cisco) ↗

Special Talent Stars

Live events

Scoring and sign-up have to stay in sync when hundreds of people hit at once. WebSocket messages are authenticated. Scores are validated on the server so a client cannot invent a result.

Solo Arts Academy

Payments

The academy takes payment through Fawry and X-PAY. I integrated those gateways — webhooks verified, charges idempotent so a retry does not bill twice. Card data stays with the provider.

Event booking

Contention

Two clicks on one seat is a race, not a UI bug. The lock lives on the server. The map is a view of that lock, not the source of truth.

Special Talent Stars

Uploads

Files go to object storage through signed URLs, with type and size limits. The browser is not trusted to decide what gets stored.

// stack

~/stack.json

What I actually use

Tools from the apps above — not a keyword list.

~/portfolio:~$ cat stack.json

{
  "frontend": [
    "React.js",
    "Next.js",
    "TypeScript",
    "Tailwind CSS"
  ],
  "backend": [
    "Node.js",
    "Express.js",
    "REST APIs",
    "WebSockets"
  ],
  "data": [
    "PostgreSQL",
    "MySQL",
    "Supabase",
    "Firebase"
  ],
  "cloud": [
    "AWS S3",
    "Docker (basics)",
    "CI/CD",
    "Git/GitHub"
  ]
}

frontend

React.jsNext.jsTypeScriptTailwind CSS

backend

Node.jsExpress.jsREST APIsWebSockets

data

PostgreSQLMySQLSupabaseFirebase

cloud

AWS S3Docker (basics)CI/CDGit/GitHub
// contact

~/scripts/contact.sh

Want to work together?

Live events, payments, real-time. I take a small number of projects.

~/contact
~/contact:~$ ./contact.sh

[status] available for projects