← All works

engineering · Since 2026

This Site

timurmanczy.com

The site you are on is a project too: 55,000 lines of Next.js that render this portfolio and run a real agency behind it, with a CRM, contracts, invoices, an in-house e-signature pipeline, a store, and ARC, the AI guide in the corner.

This Site

Most portfolios describe work; this one is the work. One content file feeds every page and grounds ARC, so the copy and the AI can never disagree. Behind the public site sits a working back office: client CRM, engagements, briefs, contracts signed in the browser through an e-sign pipeline built on pdf-lib, QuickBooks invoicing over raw REST, and a store with Stripe checkout. Every AI route sits behind a five-layer prompt-injection guard and a daily cost circuit breaker.

Role

Design · Engineering

Production

Since 2026

Scope

Next.jsTypeScriptSupabaseRemotionAI security

01

Pre-production

02

Production

03

Creation & Deliverables

The site in numbers

from the repo

54,987

Lines of TypeScript across 403 files

70 + 58

Pages + API route handlers

44

SQL migrations, RLS on Supabase

34

Remotion product films, rendered in-page

How it works

one source of truth

One content file feeds every page and grounds ARC, the AI guide, so the copy you read and the answers it gives can never drift apart. Around that core sits a working back office: the same codebase serves the portfolio, the store, the client portal, contract signing rooms, and the console that runs the agency day to day.

PortfolioStore + StripeClient portalE-signature roomsConsole CRMInvoices · QuickBooksReview deliveryARC chat

Under the hood

real excerpts, this repo
lib/ratelimit.ts
const MAX_CHAT_EVENTS_PER_DAY = 1500;
let breakerCache: { tripped: boolean; checkedAt: number } | null = null;

export async function chatBreaker(
  db: NonNullable<ReturnType<typeof supabaseAdmin>>,
): Promise<boolean> {
  const now = Date.now();
  if (breakerCache && now - breakerCache.checkedAt < 5 * 60_000) return breakerCache.tripped;
  const dayAgo = new Date(now - 24 * 3600_000).toISOString();
  const { count } = await db
    .from("chat_events")
    .select("*", { count: "exact", head: true })
    .gte("created_at", dayAgo);
  const tripped = (count ?? 0) >= MAX_CHAT_EVENTS_PER_DAY;
  breakerCache = { tripped, checkedAt: now };
  return tripped;
}
The global daily circuit breaker on AI conversations. If the whole site crosses the ceiling, chat degrades gracefully instead of running up an overnight bill.
lib/security/token-vault.ts
/** Encrypt a token for storage. Without a key, stores plaintext (degraded). */
export function sealToken(plain: string): string {
  const key = keyBytes();
  if (!key) return plain;
  const iv = randomBytes(12);
  const cipher = createCipheriv("aes-256-gcm", key, iv);
  const data = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
  return `enc:v1:${iv.toString("base64")}:${cipher.getAuthTag()
    .toString("base64")}:${data.toString("base64")}`;
}

/** Decrypt a stored token. Legacy plaintext passes through; a sealed
 *  token without the key (or tampered) returns null. */
export function openToken(stored: string): string | null {
  if (!stored.startsWith("enc:v1:")) return stored;
  // ...
}
The AES-256-GCM vault that seals third-party OAuth tokens at rest. Legacy rows pass through and self-seal on next save, so the rollout needed no migration.