swbanga.com
AI & SaaSLivev1.0.0

GradKit Platform

Cloud-Native AI Resume Builder & Document Processing Engine

  • Node.js
  • Neon PostgreSQL
  • Redis
  • Azure
  • Docker
  • GitHub Actions
  • Nginx
  • DeepSeek AI
  • Paynow
  • Playwright

Trade-off Analysis & Lessons Learned

What Worked

  • Scale-to-zero cut idle cost without dropping steady-state traffic
  • The Nginx edge absorbed AI-triggered burst traffic before the app ever saw it
  • Playwright PDFs rendered in memory and vanished on completion

What Failed

  • The first deployment exposed the app directly, before the Nginx WAF landed
  • DeepSeek latency spikes taught us to queue document jobs, not run them inline
  • PDF generation initially staged files to disk, which privacy review rejected

Architectural Iterations

  1. Direct app exposure replaced by a hardened Nginx reverse proxy
  2. Inline AI document generation replaced by queued processing with Redis
  3. On-disk PDF staging replaced by transient in-memory rendering

Lessons Learned

  • Scale-to-zero is only free if cold starts are acceptable
  • Security headers belong at the edge, not the application
  • Server-to-server payments mean the server owns the money movement, not the browser

Overview

GradKit is a cloud-native AI resume builder and document processing engine — a commercial SaaS platform at gradkit.co.zw running on Node.js, Neon PostgreSQL, Redis, and Azure Container Apps. AI document drafting runs on DeepSeek AI, payments go through server-to-server Paynow Express Checkout (EcoCash and InnBucks USD), and PDF rendering happens transiently in memory via Playwright Chromium with zero client-data persistence.

Engineered by Super Washington Banga (DevOps, Security & Cloud Architecture) with co-developers Julius Marandure and Anesu Matanhire.

Architecture

GradKit is a three-tier platform: a hardened Nginx reverse proxy at the edge, the Node.js application on scale-to-zero Azure Container Apps, and managed data services behind it. AI document generation runs through a Redis-backed job queue so model latency never blocks the request path, and PDF rendering is an ephemeral, in-memory step that leaves nothing behind. The diagram below is interactive — zoom with the buttons or the mouse wheel.

100%
build & generate resumesreview documentscheckout (redirect)users, orders, metadataenqueue AI jobsinitiate & verify checkoutdraft resume contentrender PDF in memoryBuild, generate, and download resumesJob SeekersReview shared candidate documentsEmployersCheckout via EcoCash or InnBucks USDPayment UsersAI resume builder & document engine (v1.0.0)GradKitUsers, orders, and document metadataNeon PostgreSQLJob queue and session stateRedisServer-to-server checkout — EcoCash & InnBucks USDPaynow ExpressAI document draftingDeepSeek AITransient in-memory rendering — zero persistencePlaywright PDF Renderer

Serverless-First Platform

The application runs on Azure Container Apps with scale-to-zero: when no one is building a resume, the platform costs nothing. Traffic is small but bursty — exam season spikes, term-time silence — and scale-to-zero turns that shape into a bill that tracks actual use.

The trade-off is cold starts: the first request after idle pays a startup latency tax. The Nginx edge keeps the warm path cached where possible, and the Redis job queue decouples AI work from the request lifecycle entirely — a cold start delays a job, never a user's session.

Hardened Edge with Nginx

Every request crosses a hardened Nginx reverse proxy before the application sees it. The edge enforces rate limits per client IP, security headers (CSP, HSTS), and proxy behavior — the application never has to defend the wire:

nginx
server {
    listen 443 ssl;

    # Strict transport security and a locked-down content policy.
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Content-Security-Policy "default-src 'self'; frame-ancestors 'none'; base-uri 'self'" always;

    # Per-IP burst protection in front of the app.
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    location /api/ {
        limit_req zone=api burst=20 nodelay;
        proxy_pass http://gradkit-app:3000;
    }
}

Security headers at the edge mean the response is hardened before the application code runs, and rate limiting absorbs AI-triggered burst traffic before a single request reaches the container.

Paynow Express Checkout

Payments are server-to-server: the browser never touches the payment provider. The server builds the signed Paynow payload, redirects the user to the checkout, and verifies the return transaction hash server-side before crediting the order:

javascript
const payload = {
  result_url: `${APP_URL}/api/payments/return`,
  return_url: `${APP_URL}/checkout/complete`,
  reference: `GRADKIT-${order.id}`,
  amount: order.amountUsd,
  email: order.email,
};

const signature = crypto
  .createHmac("sha512", PAYNOW_INTEGRATION_KEY)
  .update(Object.entries(payload).map(([k, v]) => `${k}=${v}`).join("&"))
  .digest("hex")
  .toUpperCase();

// POST /paynow/transactions/init — server owns the money movement.
const { browserurl, status, hash } = await initTransaction({ ...payload, signature });

Verification happens in the return handler with a freshly recomputed hash, so a forged callback cannot credit an order. EcoCash and InnBucks USD both route through the same signed flow.

Transient PDF Rendering

Resumes and documents are rendered to PDF with Playwright Chromium in a transient, in-memory step — the HTML is painted in a headless browser, the PDF is streamed to the user, and nothing is written to disk:

javascript
const browser = await chromium.launch({ args: ["--disable-dev-shm-usage"] });
try {
  const page = await browser.newPage({ viewport: { width: 794, height: 1123 } });
  await page.setContent(html, { waitUntil: "networkidle" });
  const pdf = await page.pdf({ format: "A4", printBackground: true });
  return new Response(pdf, {
    headers: { "Content-Type": "application/pdf" },
  });
} finally {
  await browser.close(); // nothing persisted — zero client data on disk
}

Privacy review drove this: the first design staged PDFs to disk, and the review rejected it. Now the document lives only in memory, from render to response — the platform holds no residual copies of user documents.

Deployment Pipeline

Every merge to main builds the container, runs the smoke suite, and deploys to Azure Container Apps via GitHub Actions. Infrastructure — container environment, PostgreSQL, Redis, scale rules — is declared in the repository, so the platform is reproducible from a clean checkout.

Status

Live at v1.0.0. Commercial and closed source; the platform is a paid SaaS with Paynow Express Checkout processing EcoCash and InnBucks USD payments. The edge, the queue, and the in-memory renderer keep the platform cheap at rest, hardened at the wire, and empty of user data after every request.