← Aryan Patel

How it's built

Every number on this sheet comes from this build or from your own request. None of it is typed by hand.

1 · Your request, up close

How this page reached you

Connecting…

your visitmy deploysYour browserCloudflare · edgeSite files (Worker)git push · mainGitHub Actionswrangler deploybuilt 9 Oct, 10:50 pm IST
Last deploy
9 Oct, 10:50 pm IST, from main
Visits today
–
Pipeline
git push · main → GitHub Actions → wrangler deploy
Revision4.7
Buildca45814
Statusstatic

2 · How it got here

git push · main → GitHub Actions → wrangler deploy · see the run

3 · What shipped with this build

  1. ca45814Cards: round case study arrow instead of the strip; honest 300+ sign-ups wording; bigger photo9 Oct 2026
  2. 64152e6Project pages: What it does as a simple ruled list9 Oct 2026
  3. 603a6f3Plainer headline, clearer GFG line, case-study strip on cards, key decisions and what I'd do differently on project pages9 Oct 2026
  4. 50869dfSearch: sitemap, robots.txt, llms.txt, canonical links and who-I-am data for Google9 Oct 2026
  5. edcd2bePhones: photo and role above the name, open-to line, stack after the buttons; no sideways scroll on small screens9 Oct 2026
  6. 7644619Menu as bordered buttons; side panel stays in view and its grid reaches the screen edge; tidier profile card on phones9 Oct 2026
  7. 13d19a7Keep design previews out of the site repo9 Oct 2026
  8. cb463c8Menu without client code, one arrow id per card, VP in the profile; ignore resume source9 Oct 2026
  9. 61a1787Home: top menu, photo panel, project cards, resume button; richer case-study drawings9 Oct 2026
  10. f500879Add the resume PDF; QR attendance stack is JavaScript9 Oct 2026

4 · What the homepage weighs

HTML
10.0 KB
CSS
4.8 KB
JavaScript
137.9 KB of a 150.0 KB budget
Fonts (preloaded)
91.6 KB
Total, gzipped
244.2 KB

the build fails if JavaScript goes over budget

5 · The Worker, annotated

01 The two endpoints

The page asks the Worker for the live numbers. The ping never counts as a visit, and if the counter breaks, the endpoint still answers so the page does not.

See the codeHide the code worker/handlers.ts · 31 lines
const NO_STORE = { 'cache-control': 'no-store' };

const json = (body: unknown, status = 200, headers: Record<string, string> = {}) =>
  new Response(JSON.stringify(body), { status, headers: { 'content-type': 'application/json', ...NO_STORE, ...headers } });

export const utcDay = (d: Date) => d.toISOString().slice(0, 10);

// The browser times this round trip. It never counts as a visit.
export function handlePing(req: Request): Response {
  if (req.method !== 'HEAD' && req.method !== 'GET') return json({ error: 'method not allowed' }, 405, { allow: 'GET, HEAD' });
  return new Response(null, { status: 204, headers: NO_STORE });
}

export async function handleVisit(
  req: Request,
  hit: (day: string) => Promise<number>,
  build: { sha: string; time: string },
  now = new Date(),
): Promise<Response> {
  if (req.method !== 'GET') return json({ error: 'method not allowed' }, 405, { allow: 'GET' });
  const colo = (req as Request & { cf?: { colo?: string } }).cf?.colo ?? null;
  let visitsToday: number | null = null;
  try {
    visitsToday = await hit(utcDay(now));
  } catch (err) {
    console.error('visit counter failed', err); // the panel shows "–"; the rest still works
  }
  return json({ colo, visitsToday, build });
}

export const notFound = () => json({ error: 'not found' }, 404);
View on GitHub ↗

02 Today's count

The count lives in a Durable Object, so two visits at the same moment never overwrite each other and no count is lost.

See the codeHide the code worker/visit-counter.ts · 12 lines
import { DurableObject } from 'cloudflare:workers';
import { nextCount, type DayCount } from './counter';

// One global instance. Durable Object storage is strongly consistent, so two
// visits at the same moment never overwrite each other's count.
export class VisitCounter extends DurableObject {
  async hit(day: string): Promise<number> {
    const next = nextCount(await this.ctx.storage.get<DayCount>('today'), day);
    await this.ctx.storage.put('today', next);
    return next.count;
  }
}
View on GitHub ↗

6 · Decisions

Drawn byAryan Patel
Revision4.7
Buildca45814
Sheet2 / 2