Skip to content

Latest commit

 

History

History
107 lines (82 loc) · 3.94 KB

File metadata and controls

107 lines (82 loc) · 3.94 KB

This repository is now a pnpm workspace monorepo.

Layout

apps/
  ai/         WebGL portfolio chat assistant
  portfolio/  Current jeremiah.dev Next.js app
packages/     Shared packages and shared data for workspace apps

The existing site lives in apps/portfolio, and the repository root now owns the workspace-level scripts.

Getting Started

Install dependencies:

pnpm dev

Run the current site:

pnpm dev

Open http://localhost:3000 to view the app.

Useful workspace commands:

pnpm dev:ai
pnpm dev:portfolio
pnpm build:ai
pnpm build
pnpm lint:ai
pnpm build:portfolio
pnpm lint
pnpm sanity:seed

AI app setup

The portfolio assistant lives in apps/ai.

Local setup:

cp apps/ai/.env.example apps/ai/.env.local
pnpm dev:ai

Required environment variables for apps/ai:

NEXT_PUBLIC_TURNSTILE_SITE_KEY=
CLOUDFLARE_TURNSTILE_SECRET_KEY=
OPENAI_API_KEY=
OPENAI_MODEL=
ASSISTANT_SPEECH_SIGNING_SECRET=
ELEVENLABS_API_KEY=
ELEVENLABS_VOICE_ID=
ELEVENLABS_MODEL_ID=
ELEVENLABS_OUTPUT_FORMAT=

Key assistant files:

  • System prompt: apps/ai/lib/prompt/system-prompt.ts
  • Approved Jeremiah profile context loader: apps/ai/lib/context/profile.ts
  • Approved Jeremiah profile context data: packages/profile-data
  • Approved Jeremiah context tool: apps/ai/lib/context/context-tools.ts
  • Speech pipeline helpers: apps/ai/lib/speech
  • Assistant response API route: apps/ai/app/api/assistant/respond/route.ts
  • Conversation request processing: apps/ai/lib/conversation
  • OpenAI service: apps/ai/lib/openai/service.ts
  • Turnstile verification utility: apps/ai/lib/turnstile/verify.ts
  • Speech normalization: apps/ai/lib/speech/normalization.ts
  • Speech authorization: apps/ai/lib/speech/authorization.ts
  • Text-to-speech service: apps/ai/lib/assistant/text-to-speech.ts
  • TTS API route: apps/ai/app/api/assistant/speech/route.ts

Request flow:

  1. The client submits the current message, recent validated history, and a Turnstile token to app/api/assistant/respond/route.ts.
  2. The route validates the body, applies rate limiting, and verifies the Turnstile token with Cloudflare.
  3. Only after Turnstile succeeds does the route call the isolated OpenAI service.
  4. The OpenAI service builds the assistant instructions from the dedicated system prompt and approved Jeremiah profile context, then calls the Responses API with OPENAI_MODEL.
  5. The assistant response route signs the exact assistant text with ASSISTANT_SPEECH_SIGNING_SECRET and returns that speechToken alongside the text response.
  6. The client renders the assistant text immediately and requests speech only when the visitor presses the voice control.
  7. The protected app/api/assistant/speech/route.ts verifies the signed token, normalizes the assistant text for speech, applies TTS-specific rate limiting, and then streams MP3 audio from ElevenLabs.

TTS notes:

  • Arbitrary visitor text is not synthesized. The speech route accepts only assistant text paired with a valid signed token generated by the assistant response route.
  • ELEVENLABS_API_KEY is the standard variable name, but the current implementation also accepts ELEVEN_LABS_KEY as a local compatibility fallback.
  • ELEVENLABS_VOICE_ID must be set to your cloned voice ID from ElevenLabs.
  • ELEVENLABS_MODEL_ID defaults to eleven_multilingual_v2.
  • ELEVENLABS_OUTPUT_FORMAT defaults to mp3_44100_128.
  • Voice defaults live in apps/ai/lib/speech/config.ts.
  • To disable TTS locally, leave ELEVENLABS_VOICE_ID or the API key unset.
  • The current tests mock provider requests, so pnpm --filter @jeremiah-dev/ai test does not spend ElevenLabs credits.

You can start editing the portfolio site by modifying apps/portfolio/app/page.tsx, or the AI assistant by modifying apps/ai/app/page.tsx.

This project uses next/font to automatically optimize and load Inter, a custom Google Font.