BWhat did you ship lately?
Pinned
Open for new opportunities

Full-stack engineer for education & commerce platforms — open to work.

Production-grade features and engineering war stories from real, shipped products. No fluff — just the decisions that mattered. Scroll the feed: every project, pattern, and incident I've shipped, posted as it happened.

B
Belal Alkahlout@belal-eng3w
Pattern
Bulk invite tool for Facebook ad leads

A throttled, idempotent CLI that converts a CSV of ad-campaign leads into signup magic-link invites by driving the existing signup endpoint — and stops rather than stranding half-provisioned accounts when the email provider rate-limits.

The masked-failure guard — stop, don't strandtypescript
} else if (
  status === 429 ||
  (status >= 400 &&
    (bodyText.includes("Failed to send magic link") ||
      bodyText.includes("Account created but") ||
      bodyText.toLowerCase().includes("rate limit")))
) {
  // Route creates the auth user BEFORE sending the link and masks GoTrue 429s as
  // 400 "Failed to send magic link". A rate-limited/failed send leaves an account
  // that EXISTS with no usable link. Do NOT add to sent-log (a re-run would only
  // mark it "exists" and skip — the link never gets sent). Stop: budget is spent;
  // continuing only creates more half-provisioned accounts.
  createdNoLink.push({
    name: lead.name,
    email: lead.email,
    status,
    body: bodyText.slice(0, 500),
  });
  rateLimited = true;
  console.log(`${label}  STOP: account created, magic link NOT sent`);
  console.error(
    "\nMagic-link send failed (likely Auth email rate limit). Stopping.\n" +
      "Accounts in created_link_not_sent[] EXIST but got no link — raise Auth → Rate\n" +
      "Limits / increase DELAY_MS, then resend a link to JUST those addresses\n" +
      "(they are NOT retried automatically — the sent-log excludes them).",
  );
  break;
}
B
Belal Alkahlout@belal-eng1mo
Incident
The cookie read that flipped a static page to dynamic

A single cookies() call in a shared Supabase client crashed every non-prebuilt war-story page under Next 16 ISR

  1. Next 16 throws `static to dynamic at runtime: cookies`
  2. Traced the dynamic API to a cookie read two calls deep
  3. Add `lib/supabase/public.ts`, swap it into the war-stories queries
  4. Landed on `main` in commit d11af87
B
Belal Alkahlout@belal-eng1mo
Shipped
Portfolio

Developer portfolio with a full admin CMS.

PortfolioProduction
B
Belal Alkahlout@belal-eng1mo
Shipped
OnlineMihna

Landing + product surface for the onlinemihna platform.

OnlineMihnaProduction
B
Belal Alkahlout@belal-eng1mo
Shipped
CSHub

A community-first learning platform for CS students worldwide — curated courses, labs, learning pathways, and a community feed in one place.

CSHubIn Progress

TypeScript · React · shadcn/ui · Tailwind · Supabase · Zod · PostgreSQL · Vercel · Next.js

Live
B
Belal Alkahlout@belal-eng1mo
Pattern
Profile Quality Score: deterministic talent ranking

A 0–100 quality score that reorders OnlineMihna's public talent surfaces so complete, verified profiles rank first. The same scoring rule runs in both TypeScript and PostgreSQL, kept byte-for-byte identical by a parity script so the app and the database can never disagree.

The rule, once, in TypeScripttypescript
export function calculateJobseekerQualitySignals(
  input: JobseekerQualityScoreInput,
): QualitySignal[] {
  return [
    { key: "avatar", weight: 15, earned: isFieldFilled(input.avatar_url) ? 15 : 0 },
    { key: "job_title", weight: 10, earned: isFieldFilled(input.job_title) ? 10 : 0 },
    { key: "bio", weight: 10, earned: stripHtmlToText(input.description).length >= 100 ? 10 : 0 },
    { key: "country", weight: 5, earned: isFieldFilled(input.country) ? 5 : 0 },
    { key: "skills", weight: 10, earned: input.skillsCount >= 3 ? 10 : 0 },
    { key: "experience", weight: 10, earned: input.experienceCount >= 1 ? 10 : 0 },
    { key: "education", weight: 5, earned: input.educationCount >= 1 ? 5 : 0 },
    { key: "rate", weight: 5, earned: isFieldFilled(input.desired_compensation) ? 5 : 0 },
    { key: "phone", weight: 5, earned: isFieldFilled(input.phone) ? 5 : 0 },
    { key: "cv", weight: 5, earned: input.hasProfileCv ? 5 : 0 },
    { key: "email", weight: 10, earned: input.emailConfirmed ? 10 : 0 },
    { key: "verification", weight: 10, earned: Math.min(Math.floor((input.verificationPercentage ?? 0) / 10), 10) },
  ];
}

export function calculateJobseekerQualityScore(input: JobseekerQualityScoreInput): number {
  const total = calculateJobseekerQualitySignals(input).reduce((sum, signal) => sum + signal.earned, 0);
  return Math.max(0, Math.min(100, total));
}
B
Belal Alkahlout@belal-eng1mo
Incident
Four production deploys to parse one PDF

PDF text extraction passed every local test, then failed in production four times — each deploy peeling back one more layer of Next.js standalone bundling.

  1. Instrument the failure so it's legible
  2. Act 1 — externalize pdf-parse (PR #198)
  3. Act 2 — force-trace @napi-rs/canvas (PR #199)
  4. Act 3 — gnu → musl after reading the OS (PR #200)
B
Belal Alkahlout@belal-eng1mo
Incident
The non-atomic onboarding write that could strand users

A DELETE+INSERT on user_interests had a failure window that would leave new users with zero rows while the Zod schema demanded ≥1 — onboarding becomes un-completable until a human intervenes.

  1. Non-atomic write enters the codebase
  2. Sprint audit flags the failure window
  3. Upsert + prune ships
  4. Fix lands on main; ISSUES row closed
B
Belal Alkahlout@belal-eng1mo
Note

Draw the boxes, name the boundaries, define the contracts. Then write the implementation — not the other way around.

Architecture before code
note
B
Belal Alkahlout@belal-eng1mo
Note

Every meaningful decision lives in the code, not in someone's head. Future-me — and future-teammates — get to read the why.

Trade-offs documented
note

— you’re all caught up —