{"id":50925465,"url":"https://github.com/sairam0424/anvilry","last_synced_at":"2026-06-16T22:30:42.721Z","repository":{"id":364498379,"uuid":"1267688390","full_name":"sairam0424/anvilry","owner":"sairam0424","description":"Anvilry — a Sairam's engineering portfolio with three switchable experiences over one content source: a classic SSG site, an AI concierge chat (RAG-grounded, AWS Bedrock ), and a gamified WebGL Build Graph. Next.js 16 · React 19 · TypeScript · Tailwind v4 · R3F · zero-fabrication content layer.","archived":false,"fork":false,"pushed_at":"2026-06-13T07:58:48.000Z","size":590,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"develop","last_synced_at":"2026-06-13T09:25:19.029Z","etag":null,"topics":["ai-chatbot","anthropic-claude","app-router","aws-bedrock","developer-portfolio","framer-motion","gamification","llm","nextjs","portfolio","rag","react","react-three-fiber","ssg","streaming","tailwindcss","three-js","typescript","vercel","webgl"],"latest_commit_sha":null,"homepage":"https://anvilry.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sairam0424.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-12T19:16:59.000Z","updated_at":"2026-06-13T07:52:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sairam0424/anvilry","commit_stats":null,"previous_names":["sairam0424/anvilry"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/sairam0424/anvilry","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sairam0424%2Fanvilry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sairam0424%2Fanvilry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sairam0424%2Fanvilry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sairam0424%2Fanvilry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sairam0424","download_url":"https://codeload.github.com/sairam0424/anvilry/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sairam0424%2Fanvilry/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34426737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-chatbot","anthropic-claude","app-router","aws-bedrock","developer-portfolio","framer-motion","gamification","llm","nextjs","portfolio","rag","react","react-three-fiber","ssg","streaming","tailwindcss","three-js","typescript","vercel","webgl"],"created_at":"2026-06-16T22:30:41.793Z","updated_at":"2026-06-16T22:30:42.715Z","avatar_url":"https://github.com/sairam0424.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Anvilry\n\n\u003e **Sairam Ugge** — GenAI \u0026 Backend Engineer. Live at **[anvilry.vercel.app](https://anvilry.vercel.app)**.\n\nA recruiter-facing engineering portfolio built as a **beast with four switchable experiences over one canonical content source** — pick the way you want to explore the same verified work:\n\n- **🗂 Classic** — a fast, static (SSG) portfolio. The SEO-indexed default and the recruiter-in-a-hurry path.\n- **🎮 Play** — an explorable **WebGL \"Build Graph\"**: every node is a real project/work system that opens its actual card. Accessible DOM-first index as the mobile / reduced-motion / no-JS fallback.\n- **💬 Chat** — an **AI concierge console**: a RAG-grounded, first-person chatbot over the real résumé, with streaming markdown answers and generative project/work cards. Optional **voice** — push-to-talk mic input, read-aloud answers, and a hands-free two-way \"talk mode\" (all opt-in, free, browser-native).\n- **⌨️ Developer** — a focused, full-page **keyboard-native terminal** over the same content: ~16 commands (`whoami`, `ls work`, `cat \u003cslug\u003e`, `grep`, `open \u003cslug\u003e`, `tree`, …) with history, autocomplete, a boot banner, theme cycling, and a fullscreen overlay. Reachable from the nav switcher, ⌘K, the `developer` command, or `?view=developer`.\n\nAll four render from **one content layer** — zero duplication, zero fabrication. The honest contribution register (*Co-built / Architected / Owned / Led*) is preserved everywhere, and every metric traces to a source file.\n\n---\n\n## ✨ Highlights\n\n- **4-view architecture** — a single client `ViewProvider` switches Classic / Play / Chat / Developer without a navigation, so the WebGL context and chat transcript survive a switch. `/` stays SSG; `?view=` deep-links collapse to one canonical URL (no duplicate-content SEO hit).\n- **AI concierge (AWS Bedrock)** — Claude **Sonnet 4.6 → Opus 4.6 → Haiku 4.5** availability fallback with a streaming byte-gate invariant, in-context RAG grounding, prompt-injection guardrails, and per-IP rate limiting (Upstash, fails open).\n- **Generative chat cards** — the model emits only a `[[card:work:slug]]` intent token; the client resolves it against a build-time slug allowlist and renders the *real* Velite card. Zero fabrication is structural, not prompt-based.\n- **Safe streaming markdown** — `react-markdown` + `rehype-sanitize` + `skipHtml` (no raw model HTML, `javascript:` links stripped), with a preprocessor that gracefully renders partial markdown mid-stream.\n- **Interactive 3D Build Graph** — R3F scene with clickable/keyboard-focusable nodes, gated behind a WebGL capability probe (graceful DOM fallback), with GL-context disposal on view exit.\n- **Anti-drift content layer** — a build-time test asserts a bijection between graph nodes and content (fails the deploy on an orphaned node).\n- **Voice (opt-in, free-first)** — push-to-talk **mic input**, per-answer **read-aloud**, and a hands-free turn-based **talk mode** (modal or a 5th view), all bolted onto the existing `useChat` transport with **zero backend change**. Browser-native (`SpeechRecognition` + `speechSynthesis`) by default; optional **AWS Polly / Transcribe** behind flags using the existing Bedrock creds (no new vendor). Strictly opt-in, feature-detected (degrades to text on Firefox), with cloud-audio disclosure, a no-double-speak `aria-live` reconciliation, and a wake word that is off by default behind a disclosure + persistent \"Listening\" banner.\n- **WCAG 2.2 AA** — keyboard operability, focus management, `aria-live` announce-on-settle chat, reduced-motion + mobile fallbacks throughout; voice is an addition, never a requirement (text always works).\n\n## 🧱 Stack\n\n| Area | Tech |\n|---|---|\n| Framework | **Next.js 16** (App Router, Turbopack) · **React 19** · **TypeScript** (strict) |\n| Styling | **Tailwind v4** — dark-technical design system (`src/app/globals.css`) |\n| Content | **Velite** — type-safe MDX content layer (`content/` → `.velite/`) |\n| Motion / 3D | **Motion** (reduced-motion aware) · **React Three Fiber** + **three.js** |\n| Chat | **AWS Bedrock** (`@anthropic-ai/bedrock-sdk`) · **react-markdown** · **Upstash** rate limiting |\n| Voice | **Web Speech API** (`SpeechRecognition` + `speechSynthesis`, free, browser-native) · optional **AWS Polly** / **Transcribe** behind flags (existing creds) |\n| UI | **cmdk** (⌘K command palette) · lucide icons |\n| Hosting | **Vercel** — Analytics + Speed Insights |\n| Tests | **Vitest** — content-coverage + chat injection/XSS guards (chained into `build`) |\n\n## 🚀 Develop\n\n```bash\npnpm install\npnpm dev          # http://localhost:3000  (Velite runs in watch mode via predev)\npnpm build        # velite --clean \u0026\u0026 vitest run \u0026\u0026 next build\npnpm lint\npnpm test         # vitest run\npnpm clean        # wipe .next/.turbo/.velite caches (run after moving/renaming the folder)\n```\n\n## 📇 Content (single source of truth)\n\nAll site content is data-driven — no fabrication, mirrors the résumé / LinkedIn / GitHub pack:\n\n- `content/work/*.mdx` — **5 production systems** (Pensieve, AAVA Code, Wireframe Generator, Prompt-to-React, Execution Engine), honest *Co-built / architected* register + real metrics.\n- `content/projects/*.mdx` — **8 open-source repos** (architecture + tech + commit counts only).\n- `src/lib/profile.ts` — identity, headline, impact metrics, skills, achievements, résumé variants.\n- `src/lib/game-model.ts` — derives the Play view's nodes/dossiers from the same content (build-time coverage test enforces no drift).\n\nEdit those files; the home grids, case-study pages, the Build Graph, sitemap, chatbot corpus, and JSON-LD all update automatically.\n\n## 💬 Chatbot configuration\n\nThe chat uses **AWS Bedrock** by default (toggle to the direct Anthropic API with `LLM_PROVIDER=anthropic`). Without credentials it degrades gracefully (`503` → the widget tells visitors to email / check the résumé).\n\n```bash\ncp .env.example .env.local\n# LLM_PROVIDER=bedrock\n# BEDROCK_ACCESS_KEY_ID / BEDROCK_SECRET_ACCESS_KEY   (base64 or raw)\n# BEDROCK_REGION=us-east-1                            (NOT AWS_REGION — reserved on Vercel)\n# UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN   (optional rate limiting)\n```\n\nThe grounding corpus is built in-context from `src/lib/corpus.ts` — the portfolio is small enough that no vector DB is needed (upgrade path: pgvector + BM25 if a blog is added). The model chain + streaming fallback live in `src/lib/llm.ts`.\n\n## 🎙️ Voice (optional, opt-in)\n\nVoice is **progressive enhancement over the text chat** — it attaches to the existing `useChat` transport, so the chat backend is unchanged. Everything defaults **off** and is toggled from the ⌘K palette's **Voice** group; the text composer is always the primary channel.\n\n| Feature | How | Cost |\n|---|---|---|\n| **Mic input** (push-to-talk) | A mic button in the chat composer. Speak → transcript fills the input for review. | **$0** — browser `SpeechRecognition`. |\n| **Read-aloud** | A per-answer \"Listen\" button speaks the reply (per-sentence, starts early). | **$0** — browser `speechSynthesis`. |\n| **Talk mode** | Hands-free turn-based loop (listen → think → speak) as a modal or an optional 5th view. | **$0** — STT + Bedrock + TTS. |\n| **Wake word** | \"Hey portfolio\" continuous listen. **Off by default**, behind a disclosure + a persistent \"Listening\" banner with one-tap kill. | **$0** — browser `SpeechRecognition`. |\n\n**Privacy:** on Chrome/Edge, browser `SpeechRecognition` sends audio to the browser vendor's cloud (Google) — disclosed in-UI before the first listen; nothing is stored server-side. `getUserMedia` runs only on an explicit gesture, with a visible mic indicator and a one-tap stop that releases the mic.\n\n**Browser support:** feature-detected. Chrome/Edge/Safari get full voice; **Firefox** (where `SpeechRecognition` is off-by-default) silently keeps the text composer — or can use the AWS Transcribe path.\n\n**Optional AWS upgrades (flags, no new vendor — reuse the Bedrock creds):**\n\n```bash\n# Higher-quality voice output: AWS Polly Neural via /api/tts (else free browser voice).\n#   Toggle in-app: ⌘K → \"Use higher-quality voice (Polly)\"\n# Private speech-to-text: AWS Transcribe via /api/transcribe (audio processed on your\n#   own AWS, not Google; also enables voice in Firefox).\n#   Toggle in-app: ⌘K → \"Mic: use private transcription (AWS)\"\n```\n\nBoth reuse `BEDROCK_*` creds, are per-IP rate-limited (Upstash), and **fail closed** — any error degrades to the free browser path, so voice never breaks. Needs IAM `polly:SynthesizeSpeech` / `transcribe:StartStreamTranscription` on the same key (see `DEPLOY.md`).\n\n📖 **Full reference: [`VOICE.md`](./VOICE.md)** — architecture, the complete feature-flag/settings table, env + IAM + cost, the privacy \u0026 a11y model, and developer notes (testing, adding an engine).\n\n## 🌐 Deploy (Vercel)\n\nSee **[`DEPLOY.md`](./DEPLOY.md)** for the full guide (env vars, verified Bedrock model chain + IAM policy, rate limiting, the region gotcha). In short:\n\n1. Repo: **[github.com/sairam0424/anvilry](https://github.com/sairam0424/anvilry)**.\n2. Import at [vercel.com/new](https://vercel.com/new) — framework auto-detected as Next.js.\n3. Add env vars (Production + Preview): `LLM_PROVIDER`, `BEDROCK_ACCESS_KEY_ID`, `BEDROCK_SECRET_ACCESS_KEY`, `BEDROCK_REGION`, `UPSTASH_REDIS_REST_URL`, `UPSTASH_REDIS_REST_TOKEN`.\n4. **Branch model:** `develop` = primary working branch (Preview deploys) · `main` = release branch (Production → the live domain).\n5. Live at **[anvilry.vercel.app](https://anvilry.vercel.app)** (custom domain optional, via Settings → Domains).\n\nThe public base URL is `https://anvilry.vercel.app` (in `src/app/layout.tsx` `siteUrl`, plus `sitemap.ts`, `robots.ts`, `json-ld.tsx`, `opengraph-image.tsx`) — update those four files if you point a custom domain at the deployment.\n\n---\n\n\u003csub\u003eAnvilry is the project codename; the deployed site is **[anvilry.vercel.app](https://anvilry.vercel.app)**.\u003c/sub\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsairam0424%2Fanvilry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsairam0424%2Fanvilry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsairam0424%2Fanvilry/lists"}