Back to projects

PHP 8, MySQL, Stripe, GitHub Actions

ghparts.hu

Full-stack developer · May 2026 – present · redesign in beta

GH Parts Hungary is a production car-parts e-commerce site I took over and hardened alone: storefront, admin, payments, hosting, and releases. The shop already had real traffic; from May 2026 I put the codebase in git, locked down security and ops, then keep shipping Stripe, vehicle search, a token-based design system, and CI/CD without taking the live store offline. The redesign is progressive and still in beta on the public site — staging stays isolated — while catalog, cart, and card payments already run in production.

Customer (ghparts.hu)
  → catalog / vehicle fitment / cart
  → multi-step checkout (server-side totals)
  → Stripe Checkout + webhook (idempotent capture)
  → order email once

Deploy: GitHub Actions FTP
  master push ≠ production
  dry-run → staging (beta) → manual production
  secrets and uploads stay off the deploy path

Deep dive

Own the live shop, do not rewrite it

There is no Laravel or Next.js rewrite. The shop was already earning, so a framework swap under traffic was the wrong risk. The hybrid stays intentional: procedural PHP pages plus OOP under compose/, small reviewable steps, and a gradual CSS redesign (GH Parts Redesign 2026) with tokens, BEM components, and 44 px touch targets — no build step, no big-bang cutover.

Stripe without double charges

Totals never come from the client — the server writes orders.grand_total. Checkout is idempotent: browser return and webhook race to flip paysuccess 0 → 1, and the paid email sends once. An open Stripe session is reused; a paid order returns 409 instead of starting a second charge. Interrupted or restarted payments cannot double-bill the customer.

Hardening a legacy codebase

Prepared statements against SQL injection, CSRF on every mutating form, XSS escaping, safe image uploads (magic bytes + random filenames), and DB / API secrets moved out of git into env and ignored local files. Google OAuth and session carts (synced to the DB when logged in) sit on the same hardened path.

Staging, then production by hand

GitHub Actions deploys over FTP with staging and production databases split. A push to master does not go live. The path is dry-run, then beta staging, then a checked production release. Secrets and uploaded product images are deliberately excluded from deploy artifacts. Local Docker (PHP + MariaDB) mirrors the stack for day-to-day work.

Fitment search and catalog ops

Vehicle search is make → model in session, with product lists filtered to that car; VIN validation plus WMI brand hints without an external API; saved garage cars for logged-in buyers. Checkout covers weight-banded shipping (no order if the band is missing), out-of-stock contact instead of a broken cart, and cart sync across devices. Admin is ~90 screens: orders, phone intake, product CRUD, Excel sync keyed on gh_code, banners, blog, customers, couriers, plus mojibake / double-UTF-8 name fixes.

What is still beta

Payments, catalog, and security hardening are live. The token-based storefront redesign and component roll-out are still in beta — visible on ghparts.hu as progressive UI work, verified on staging before each production cut. Critical money and auth paths have runnable assert scripts; the rest is walked manually on beta before release.

Highlights

Sole full-stack ownership of a live, framework-free PHP 8 / MySQL car-parts shop (storefront, admin, hosting, releases)
Stripe Checkout with server-side totals, webhooks, and idempotent order capture — no double charges on abandoned checkouts
Legacy hardening: prepared SQL, CSRF, XSS escaping, safe uploads, credentials out of git
Manual GitHub Actions FTP pipeline with isolated staging/production; production never deploys on push
Vehicle fitment search (make/model + VIN), logged-in cart sync, Google OAuth, Excel catalog import
Token-based CSS design system and progressive redesign in beta — shipping without taking the shop offline