Skip to main content

Platform Architecture

Overview

This article provides the complete architectural blueprint for the uzdavines.ai platform -- a monorepo containing three independently deployed web applications unified by shared infrastructure, a consistent design language, and automated CI/CD pipelines.

  • Why it matters: Understanding the platform's architecture is essential for making informed decisions about development, deployment, and scaling. This document serves as the single source of truth for how the system is structured and why.
  • What you will learn: The application stack and framework choices, DNS and hosting configuration via Cloudflare and Render, the CI/CD deployment pipeline, monorepo directory structure, and the shared design language across all applications.

The uzdavines.ai platform is built as a monorepo with three independently deployed applications, unified by shared infrastructure and a consistent design language.

High-Level Architecture

                         ┌─────────────────────────┐
│ Cloudflare DNS │
│ (Proxy + SSL/TLS) │
└────┬─────┬─────┬────────┘
│ │ │
┌───────────┘ │ └───────────┐
│ │ │
v v v
┌──────────────┐ ┌─────────────┐ ┌──────────────┐
│ Homepage │ │ Docs │ │ Resume │
│ (Render │ │ (Render │ │ (Render │
│ Web Svc) │ │ Static) │ │ Web Svc) │
└──────────────┘ └─────────────┘ └──────────────┘
uzdavines.ai docs.uzdavines resume.uzdavines
.ai .ai

Application Stack

ApplicationFrameworkRender TypeKey Features
HomepageNext.js + Tailwind CSSWeb Service (SSR)AI chatbot, scroll-snap sections, /coffee route
DocsDocusaurus + TypeScriptStatic SiteKnowledge base, dual-tier content
ResumeNext.js + Tailwind CSSWeb Service (SSR)Interactive resume, Pierre chatbot

Why SSR for Homepage and Resume?

Both the homepage and resume applications require server-side rendering because they include API routes (/api/chat) that proxy requests to the Claude API. The API key must stay server-side.

Why Static for Docs?

Docusaurus generates static HTML/CSS/JS at build time. No server-side logic is needed — the content is pre-rendered and served directly.

Infrastructure

DNS and CDN — Cloudflare

uzdavines.ai          CNAME --> Render homepage service
docs.uzdavines.ai CNAME --> Render docs service
resume.uzdavines.ai CNAME --> Render resume service
  • SSL/TLS mode: Full
  • Proxy status: Proxied (after Render TLS cert validation)
  • Cloudflare handles DNS resolution, CDN caching, and SSL termination

Hosting — Render

Each application is deployed as a separate Render service. Auto-deploy is disabled — deployments are triggered by GitHub Actions via deploy hooks.

CI/CD — GitHub Actions

Path-filtered workflows ensure only the affected application is built and deployed when changes are pushed to main.

Push to main

├── apps/homepage/** changed? --> deploy-homepage.yml
├── apps/docs/** changed? --> deploy-docs.yml
└── apps/resume/** changed? --> deploy-resume.yml

Monorepo Structure

uzdavines-platform/
├── apps/
│ ├── homepage/ # Next.js — uzdavines.ai
│ │ ├── src/app/ # App router pages
│ │ │ ├── api/chat/ # AI chatbot API route
│ │ │ ├── coffee/ # Cloud City Roasters page
│ │ │ ├── layout.tsx # Root layout
│ │ │ └── page.tsx # Homepage
│ │ ├── public/ # Static assets
│ │ └── package.json
│ │
│ ├── docs/ # Docusaurus — docs.uzdavines.ai
│ │ ├── docs/ # Public Markdown docs (Tier 1)
│ │ ├── static/ # Static assets
│ │ │ └── private/ # Hidden docs (Tier 2)
│ │ ├── src/css/ # Custom styling
│ │ └── package.json
│ │
│ └── resume/ # Next.js — resume.uzdavines.ai
│ ├── src/app/ # App router pages
│ │ └── api/chat/ # Pierre chatbot API route
│ └── package.json

├── packages/
│ └── shared/ # Shared utilities

├── .github/
│ └── workflows/ # CI/CD pipelines
│ ├── deploy-homepage.yml
│ ├── deploy-docs.yml
│ ├── deploy-resume.yml # (future)
│ ├── pr-check-homepage.yml
│ ├── pr-check-docs.yml
│ └── pr-check-resume.yml # (future)

└── package.json # npm workspaces root

Design Language

All applications share a consistent visual identity:

AspectStandard
Color paletteMonochrome (black, white, grays) + dark navy (#0a1628 → #1a2744)
ModeDark mode default
TypographyPlus Jakarta Sans
LayoutMobile-first
AestheticSleek, professional, modern, understated