{
  "markdown": "# thechrisgrey.com\n\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.2-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)\n[![React](https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=black)](https://react.dev/)\n[![Vite](https://img.shields.io/badge/Vite-5-646CFF?logo=vite&logoColor=white)](https://vitejs.dev/)\n[![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-4-06B6D4?logo=tailwindcss&logoColor=white)](https://tailwindcss.com/)\n[![AWS Amplify](https://img.shields.io/badge/AWS_Amplify-Hosted-FF9900?logo=awsamplify&logoColor=white)](https://aws.amazon.com/amplify/)\n[![Amazon Bedrock](https://img.shields.io/badge/Amazon_Bedrock-Claude_Haiku_4.5-232F3E?logo=amazonaws&logoColor=white)](https://aws.amazon.com/bedrock/)\n[![CI](https://img.shields.io/github/actions/workflow/status/thechrisgrey/thechrisgrey/ci.yml?branch=main&label=CI&logo=github)](https://github.com/thechrisgrey/thechrisgrey/actions)\n[![License](https://img.shields.io/badge/License-All_Rights_Reserved-lightgrey)](#license)\n\nPersonal website for **Christian Perez** ([@thechrisgrey](https://thechrisgrey.com)) | Founder & CEO of Altivum Inc. | Former Green Beret (18D Special Forces Medical Sergeant) | Bronze Star Recipient | Host of The Vector Podcast | Author of \"Beyond the Assessment\"\n\n**[https://thechrisgrey.com](https://thechrisgrey.com)**\n\n---\n\n## Table of Contents\n\n- [Technology Stack](#technology-stack)\n- [Features](#features)\n- [Architecture](#architecture)\n- [AWS Infrastructure](#aws-infrastructure)\n- [Getting Started](#getting-started)\n- [Testing](#testing)\n- [Environment Variables](#environment-variables)\n- [Deployment](#deployment)\n- [Project Structure](#project-structure)\n- [Key Integrations](#key-integrations)\n- [Design System](#design-system)\n- [License](#license)\n\n---\n\n## Technology Stack\n\n| Layer             | Technology                                                       |\n| ----------------- | ---------------------------------------------------------------- |\n| **Frontend**      | React 19, TypeScript 5, Vite 5 (Vitest 4, ESLint 10 flat config) |\n| **Styling**       | Tailwind CSS 4 (CSS-first `@theme` config, Oxide engine)         |\n| **Routing**       | React Router 7                                                   |\n| **CMS**           | Sanity.io (blog content)                                         |\n| **AI Chat**       | Amazon Bedrock (Claude Haiku 4.5) + RAG                          |\n| **Auth**          | Amazon Cognito (admin panel)                                     |\n| **Hosting**       | AWS Amplify                                                      |\n| **CDN/Analytics** | Cloudflare Web Analytics                                         |\n| **Testing**       | Vitest + React Testing Library + Cypress                         |\n| **Code Quality**  | ESLint, strict TypeScript                                        |\n\n---\n\n## Features\n\n### Pages\n\n- **Home** : Scroll-based animations with sticky profile sections\n- **About** : Personal biography and military background\n- **Altivum Inc** : Company showcase and services\n- **The Vector Podcast** : YouTube embeds, Spotify player, collapsible episode list\n- **Beyond the Assessment** : Book information and purchase links\n- **Blog** : Sanity CMS-powered with categories, tags, series, and reading progress\n- **AI Chat** : Full-viewport conversational AI with RAG-enhanced responses\n- **Claude** : AWS certifications and Claude expertise showcase\n- **AWS** : AWS partnership and community builder profile\n- **Admin** : Cognito-authenticated KB management and site health dashboard\n- **Links** : Linktree-style quick links\n- **Contact** : Contact form, speaking topics, downloadable press kit\n\n### Technical Highlights\n\n- **SEO** : JSON-LD structured data, Open Graph, dynamic sitemap, RSS feed\n- **AI Chat with RAG** : Bedrock Knowledge Base retrieval with streaming responses\n- **Podcast Auto-Sync** : YouTube Data API fetches episodes at build time\n- **Chat Widget** : Floating chat widget available across all pages\n- **Metrics Dashboard** : CloudWatch and DynamoDB-backed operational metrics\n- **Error Boundaries** : Page-level error handling with custom fallback UIs\n- **Accessibility** : Focus trapping, keyboard navigation, ARIA labels, skip links\n- **Performance** : Image optimization (Sharp/SVGO), lazy loading, code splitting, manual chunking\n\n---\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                        FRONTEND (React)                         │\n│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐           │\n│  │   Home   │ │  Podcast │ │   Blog   │ │   Chat   │   ...     │\n│  └──────────┘ └──────────┘ └──────────┘ └──────────┘           │\n└─────────────────────────────────────────────────────────────────┘\n        │               │              │              │\n        ▼               ▼              ▼              ▼\n┌───────────┐   ┌───────────┐   ┌───────────┐   ┌───────────────┐\n│  Amplify  │   │  YouTube  │   │  Sanity   │   │    Bedrock    │\n│  Hosting  │   │  Data API │   │    CMS    │   │  + RAG (KB)   │\n└───────────┘   └───────────┘   └───────────┘   └───────────────┘\n                (build-time)     (runtime)       (Lambda stream)\n```\n\n### AI Chat Request Flow\n\n```\nUser Message\n    │\n    ▼\nLambda Function URL (streaming)\n    │\n    ├──> Bedrock Knowledge Base (retrieve context)\n    │         │\n    │         ▼\n    │    S3 Vectors (autobiography chunks)\n    │\n    ├──> Bedrock Guardrails (content filtering)\n    │\n    └──> Bedrock ConverseStream API (Claude Haiku 4.5)\n              │\n              ▼\n         Streaming Response -> Client\n```\n\n---\n\n## AWS Infrastructure\n\n| Service             | Resource                               | Region    | Purpose                          |\n| ------------------- | -------------------------------------- | --------- | -------------------------------- |\n| **Amplify**         | `d3du8eg39a9peo`                       | us-east-2 | Hosting, CI/CD                   |\n| **Lambda**          | `thechrisgrey-chat-stream`             | us-east-1 | AI chat streaming                |\n| **Lambda**          | `thechrisgrey-contact-email`           | us-east-2 | Contact form                     |\n| **Lambda**          | `thechrisgrey-newsletter-subscription` | us-east-2 | Newsletter                       |\n| **Lambda**          | `thechrisgrey-kb-sync`                 | us-east-1 | KB auto-sync on S3 changes       |\n| **Lambda**          | `thechrisgrey-kb-builder`              | us-east-1 | KB admin CRUD operations         |\n| **Lambda**          | `thechrisgrey-metrics`                 | us-east-1 | Metrics collection and reporting |\n| **Bedrock KB**      | `ARFYABW8HP`                           | us-east-1 | RAG knowledge base               |\n| **Cognito**         | User Pool                              | us-east-1 | Admin authentication             |\n| **S3**              | `thechrisgrey-kb-source`               | us-east-1 | KB source documents              |\n| **S3**              | `thechrisgrey-vectors`                 | us-east-1 | Vector embeddings                |\n| **DynamoDB**        | `thechrisgrey-chat-ratelimit`          | us-east-1 | Rate limiting (20 req/hr/IP)     |\n| **Secrets Manager** | `thechrisgrey/youtube-api-key`         | us-east-1 | YouTube API key                  |\n| **CloudWatch**      | `tcg-AI-chat`                          | us-east-1 | Bedrock invocation logs          |\n\n---\n\n## Getting Started\n\n### Prerequisites\n\n- Node.js 20.x (see `.nvmrc`)\n- npm\n- AWS CLI (for deployment)\n\n### Installation\n\n```bash\ngit clone https://github.com/thechrisgrey/thechrisgrey.git\ncd thechrisgrey\nnpm install\n```\n\n### Development\n\n```bash\nnpm run dev             # Start dev server at http://localhost:5173\nnpm run build           # Full production build\nnpm run preview         # Preview production build\nnpm run lint            # Run ESLint\n```\n\n### Build Pipeline\n\nThe production build runs these steps in sequence:\n\n```\nvalidate-env -> podcast-episodes -> lint -> tsc -> vite build -> sitemap -> rss\n```\n\n---\n\n## Testing\n\n| Framework     | Scope                  | Command                 |\n| ------------- | ---------------------- | ----------------------- |\n| **Vitest**    | Unit + Integration     | `npm test`              |\n| **Vitest**    | Watch mode             | `npm run test:watch`    |\n| **Vitest**    | Coverage report        | `npm run test:coverage` |\n| **Cypress**   | E2E (headless)         | `npm run cy:run`        |\n| **Cypress**   | E2E (interactive)      | `npm run cy:open`       |\n| **node:test** | Lambda unit + contract | `npm run test:lambda`   |\n\nThe test suite includes unit tests for components, hooks, and utilities; integration tests for page-level behavior; and end-to-end tests covering navigation, chat, blog, and contact flows.\n\n### Live-API contract tests (opt-in)\n\nCritical external boundaries — Cognito admin auth, the live Sanity client, Bedrock KB retrieval, and the Bedrock guardrail — are also covered by **opt-in contract tests** that exercise the real services (green mocks alone can drift from reality). They **skip cleanly** during `npm run test:lambda` and CI, and only run when their flag + AWS/Sanity credentials are present:\n\n```bash\nCOGNITO_CONTRACT_TESTS=1 COGNITO_CLIENT_ID=… COGNITO_TEST_EMAIL=… COGNITO_TEST_PASSWORD=… \\\n  node --test lambda/shared/__tests__/cognito-contract.test.mjs\nSANITY_CONTRACT_TESTS=1      node --test lambda/chat-stream/__tests__/sanity-contract.test.mjs\nKB_RETRIEVE_CONTRACT_TESTS=1 node --test lambda/chat-stream/__tests__/kb-retrieve-contract.test.mjs\nBEDROCK_CONTRACT_TESTS=1     node --test lambda/blueprint/__tests__/guardrail-contract.test.mjs\n```\n\nSee `.env.example` for the full list of flags and required permissions. Run these before a release (or on a scheduled job) to catch response-shape/schema drift that unit mocks can't.\n\n---\n\n## Environment Variables\n\nSet in AWS Amplify console or in a local `.env` file:\n\n| Variable                    | Description                               | Required |\n| --------------------------- | ----------------------------------------- | -------- |\n| `VITE_CHAT_ENDPOINT`        | Lambda Function URL for AI chat           | Yes      |\n| `VITE_CONTACT_ENDPOINT`     | Lambda Function URL for contact form      | Yes      |\n| `VITE_NEWSLETTER_ENDPOINT`  | Lambda Function URL for newsletter        | Yes      |\n| `VITE_COGNITO_USER_POOL_ID` | Cognito User Pool ID (admin auth)         | Yes      |\n| `VITE_COGNITO_CLIENT_ID`    | Cognito App Client ID                     | Yes      |\n| `VITE_KB_BUILDER_ENDPOINT`  | Lambda Function URL for KB admin          | Yes      |\n| `VITE_CHAT_SIGNING_KEY`     | HMAC signing key for chat requests        | Yes      |\n| `VITE_METRICS_ENDPOINT`     | Lambda Function URL for metrics           | Yes      |\n| `YOUTUBE_API_KEY`           | YouTube Data API v3 key (build-time only) | Yes      |\n\n`VITE_` prefixed variables are bundled into the frontend. `YOUTUBE_API_KEY` is only used during the build step.\n\n---\n\n## Deployment\n\n### Automatic (Recommended)\n\nPush to `main` triggers automatic Amplify deployment:\n\n```bash\ngit push origin main\n```\n\n### Manual Rebuild\n\n```bash\naws amplify start-job \\\n  --app-id d3du8eg39a9peo \\\n  --branch-name main \\\n  --job-type RELEASE \\\n  --region us-east-2\n```\n\n### Lambda Deployment\n\nEach Lambda function is deployed independently via a single verified script. The script\ninstalls from the lockfile, dereferences the `lambda-shared` symlink into the bundle, and\n**verifies the entire module graph resolves before upload** — so a deploy can no longer ship\na Lambda that crashes on cold start.\n\n```bash\n# Verify the bundle builds and resolves, without uploading:\nnpm run deploy:lambda -- chat-stream --dry-run\n\n# Deploy for real:\nnpm run deploy:lambda -- chat-stream\n```\n\nWorks for any Lambda under `lambda/` (e.g. `chat-stream`, `blueprint`, `kb-builder`,\n`metrics`, `kb-sync`, `mcp-server`). Pass `--region <r>` to override the default\n(`us-east-1`). Do **not** hand-build `function.zip` — the manual `zip` glob omits the\nsibling modules each handler imports and produces a broken artifact.\n\n---\n\n## Project Structure\n\n```\nthechrisgrey/\n├── public/                          # Static assets (served as-is)\n│   ├── assets/documents/            # Downloadable PDFs\n│   ├── press-kit/                   # Press materials + archive\n│   ├── .well-known/security.txt\n│   ├── robots.txt\n│   ├── og.png                       # Open Graph image\n│   └── favicon.png\n│\n├── src/\n│   ├── components/\n│   │   ├── admin/                   # Admin panel (login, KB entries, site health)\n│   │   ├── chat/                    # AI chat (message, input, suggestions, widget)\n│   │   ├── ui/                      # Base UI (Button, FormInput, IconButton)\n│   │   ├── Navigation.tsx\n│   │   ├── Footer.tsx\n│   │   ├── SEO.tsx                  # Meta tags + JSON-LD\n│   │   ├── ErrorBoundary.tsx\n│   │   ├── ErrorFallbacks.tsx\n│   │   ├── EpisodeCard.tsx\n│   │   ├── NewsletterForm.tsx\n│   │   ├── ReadingProgressBar.tsx\n│   │   └── ...\n│   │\n│   ├── pages/                       # Route-level page components\n│   │   ├── Home.tsx, About.tsx, Altivum.tsx, Podcast.tsx\n│   │   ├── BeyondTheAssessment.tsx, Blog.tsx, BlogPost.tsx\n│   │   ├── Chat.tsx, Claude.tsx, AWS.tsx, Admin.tsx\n│   │   ├── Contact.tsx, Links.tsx, Privacy.tsx\n│   │   └── NotFound.tsx\n│   │\n│   ├── hooks/                       # Custom React hooks\n│   │   ├── useAuth.ts               # Cognito authentication\n│   │   ├── useChatEngine.ts         # Chat state and streaming\n│   │   ├── useFocusTrap.ts          # Modal focus management\n│   │   ├── useKbAdmin.ts            # KB admin operations\n│   │   ├── usePageContext.ts        # Page-level context for chat\n│   │   ├── useSessionStorage.ts     # Typed sessionStorage with Date revival\n│   │   └── useSiteHealth.ts         # Site health monitoring\n│   │\n│   ├── sanity/                      # Sanity CMS client, queries, types, cache\n│   ├── utils/                       # Typography, schemas, validators, web vitals\n│   ├── constants/                   # Social links\n│   ├── types/                       # TypeScript interfaces\n│   ├── data/                        # Podcast episode data (generated + fallback)\n│   ├── assets/                      # Optimized images (Vite processed)\n│   │\n│   ├── __tests__/\n│   │   ├── integration/             # Page-level integration tests\n│   │   └── setup.ts\n│   │\n│   ├── App.tsx                      # Routes, layout, error boundaries\n│   ├── main.tsx                     # Entry point\n│   └── index.css                    # Tailwind directives\n│\n├── lambda/\n│   ├── shared/                      # Shared utilities (auth, rate limiting, response)\n│   ├── chat-stream/                 # Bedrock streaming Lambda\n│   ├── kb-sync/                     # Knowledge Base auto-sync\n│   ├── kb-builder/                  # KB admin CRUD\n│   └── metrics/                     # Metrics collection\n│\n├── scripts/\n│   ├── validate-env.js              # Build-time env validation\n│   ├── generate-podcast-episodes.js # YouTube API fetch\n│   ├── generate-sitemap.js          # Sitemap from Sanity\n│   └── generate-rss.js             # RSS feed from Sanity\n│\n├── cypress/                         # E2E tests\n│   ├── e2e/                         # Test specs\n│   ├── fixtures/                    # Test data\n│   └── support/                     # Custom commands\n│\n├── docs/                            # Internal documentation and plans\n├── .github/workflows/ci.yml        # GitHub Actions CI\n├── amplify.yml                      # Amplify build config\n├── tailwind.config.js\n├── vite.config.ts\n├── vitest.config.ts\n├── cypress.config.ts\n└── tsconfig.json\n```\n\n---\n\n## Key Integrations\n\n### Sanity CMS (Blog)\n\n- **Project ID:** `k5950b3w` | **Dataset:** `production`\n- Content includes blog posts with categories, tags, series, and Portable Text rich content\n- Client-side caching via `postCache.ts` with Date revival\n\n### YouTube Data API (Podcast)\n\nEpisodes are fetched at build time from the `@AltivumPress` channel.\n\n1. `generate-podcast-episodes.js` runs during the build step\n2. Fetches channel, uploads playlist, and video details\n3. Generates `src/data/generatedEpisodes.json`\n4. Falls back to static data if the API is unavailable\n\n### Amazon Bedrock (AI Chat)\n\n- **Model:** Claude Haiku 4.5 (`us.anthropic.claude-haiku-4-5-20251001-v1:0`)\n- **Knowledge Base:** `ARFYABW8HP` (autobiography chunks)\n- **Guardrail:** `5kofhp46ssob` (content filtering)\n- **Rate Limit:** 20 requests/hour per IP (DynamoDB-backed)\n- Streaming responses via Lambda Function URL with RAG retrieval (5 chunks per query)\n\n### Cloudflare Web Analytics\n\nPrivacy-friendly, cookie-free analytics with no personal data collection.\n\n---\n\n## Design System\n\n### Color Palette\n\n| Name             | Hex       | Usage            |\n| ---------------- | --------- | ---------------- |\n| `altivum-dark`   | `#0A0F1C` | Backgrounds      |\n| `altivum-navy`   | `#1A2332` | Cards, nav       |\n| `altivum-blue`   | `#2E4A6B` | Accents          |\n| `altivum-slate`  | `#4A5A73` | Borders, muted   |\n| `altivum-silver` | `#9BA6B8` | Body text        |\n| `altivum-gold`   | `#C5A572` | Highlights, CTAs |\n\n### Typography\n\nSF Pro Display with system font fallbacks. Ultra-light weight (200) throughout. Defined in `src/utils/typography.ts`.\n\n### Animations\n\n- `animate-fade-in` : Hero entrance (1.2s)\n- `animate-nav-fade-in` : Nav delayed entrance (0.8s, 2s delay)\n- `shimmer` : Background shimmer effect\n- `widget-open` : Chat widget expansion (250ms)\n\n---\n\n## License\n\nCopyright 2026 Christian Perez. All rights reserved.\n\nFor inquiries, use the [contact form](https://thechrisgrey.com/contact) or email via the website.\n",
  "bytes": 17843,
  "sha": "f87b3cd5a3aac2e4cfa274ee8fcc61bf553d8019afc2f90efb8b877843db1e9d",
  "repo_slug": "thechrisgrey/thechrisgrey",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_thechrisgrey_mcp_b623b6c0/readme"
}