amin.mallol
← All work

Side projects

Things I built with my own money

Experiments, mostly. One of them lost £60 and earned its place here by failing on schedule.

  • Ignitopedia

    2026

    Multi-tenant ebook storefront

    One deployment serving several ebook products, each on its own custom domain, with a new title added by a database row rather than a redeploy. Written in TypeScript, three languages, payments through Payhip, a daily email sequence on a cron.

    The interesting part

    Payhip does not sign its webhooks. What it calls a signature is a constant hash of the API key, identical on every request, so it is a bearer token: anyone who observes one webhook can forge paid orders forever. Rather than pretend otherwise, the threat model is written into the route handler and the mitigation is structural. The order is created as pending before the redirect, carrying its own id, and the webhook can only flip an order this server created, only while it is still pending, and only once, through a conditional update whose WHERE clause matches zero rows on a replay and nothing at all on a forged id.

    • TypeScript
    • Next.js 16
    • Prisma
    • Neon Postgres
    • next-intl
    • Resend
    • Vercel

    Outcome: Live, selling. Five titles plus a bundle, in French, English and Spanish.

    ignitopedia.com ↗
  • devSpec

    2026

    Specification gate for small teams

    Write the spec before you build it. A feature cannot leave discussion until six questions are answered: who it is for, the flow, the acceptance checks, what happens when it fails, what is out of scope, and what it might break.

    The interesting part

    The rule is a Postgres trigger, not application code. A BEFORE INSERT OR UPDATE function raises on any target status outside discussion with an unanswered question, so no client, no stray API call and no future refactor can route around it. The API layer only translates the database's exception into a 409, and the README shows the curl that tries to bypass it and the response it gets. The UI's own check is explicitly labelled a convenience.

    • TypeScript
    • Next.js 15
    • Drizzle
    • Neon Postgres
    • jose

    Outcome: Public repository. Built for my own use and kept small on purpose.

    github.com/Focus-me34/devspec ↗
  • Ever Near

    2026

    E-commerce experiment

    A premium UK gift store around two message bracelets at £34.99, built in a week: custom Shopify theme, brand guide, product photography, six ads, and a Meta Sales campaign at £40 a day.

    The interesting part

    It did not work, and that is why it is here. After 34 hours and £60.06 of spend: 113 visits from ads, a 2.2 to 3.4% click rate at about £1 a click, two add-to-carts, one checkout started, zero sales. People stopped and clicked and did not buy, which is a product problem, not a creative one. I killed it the next morning against a rule I had written before launching (stop when spend reaches roughly three times what a single sale could afford in acquisition), and wrote the retrospective the same evening, including the Amazon price comparison I should have taken seriously at product-selection time.

    • Shopify
    • Meta Ads
    • Higgsfield
    • Custom theme

    Outcome: Killed on day two by a pre-set rule. £60 spent, one retrospective, a better product filter.

    evernearco.com ↗
  • Golden Wài

    2026

    Marketing site

    A London lifestyle-management and relocation concierge for clients from East and Southeast Asia. Two pages, built to be read in whichever language the visitor actually speaks.

    The interesting part

    Thirteen locales with full hreflang alternates: English, both written forms of Chinese, Japanese, Korean, Thai, Vietnamese, Indonesian, Malay, Filipino, Burmese, Khmer and Lao. Every string lives in a per-locale message file, so the client can have a line rewritten in one language without touching the other twelve.

    • Next.js 16
    • React 19
    • next-intl
    • MUI 7
    • Motion

    Outcome: Delivered for a client. Thirteen locales, static, nothing to operate.

  • Ambelé

    2023 to 2026

    Non-profit fundraising site

    A fundraising site for a digital-literacy programme run with young women at the Lycée de jeunes filles de Conakry, in Guinea. The name means "we are together" in Malinké. Donations go through HelloAsso, so the site holds no payment code and no personal data.

    The interesting part

    The oldest thing here and the only one with a three-year maintenance tail: 116 commits from April 2023 to August 2026, including the framework upgrades and a Node migration nobody asked for. It is a brochure site, and keeping a brochure site working for three years for free is its own kind of signal.

    • Next.js 14
    • React 18
    • MUI 5
    • Sass
    • HelloAsso

    Outcome: Live and maintained since 2023, for a friend's association.