{"id":40511953,"url":"https://github.com/sequenzia/portfolio-ai","last_synced_at":"2026-01-20T20:12:36.058Z","repository":{"id":331175771,"uuid":"1125947792","full_name":"sequenzia/portfolio-ai","owner":"sequenzia","description":null,"archived":false,"fork":false,"pushed_at":"2026-01-18T00:11:57.000Z","size":664,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-18T07:21:54.280Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://sequenzia.ai","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sequenzia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":null,"dco":null,"cla":null}},"created_at":"2025-12-31T17:50:59.000Z","updated_at":"2026-01-18T00:12:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sequenzia/portfolio-ai","commit_stats":null,"previous_names":["sequenzia/sequenzia-ai","sequenzia/portfolio-ai"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/sequenzia/portfolio-ai","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequenzia%2Fportfolio-ai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequenzia%2Fportfolio-ai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequenzia%2Fportfolio-ai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequenzia%2Fportfolio-ai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sequenzia","download_url":"https://codeload.github.com/sequenzia/portfolio-ai/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequenzia%2Fportfolio-ai/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28612166,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T18:56:40.769Z","status":"ssl_error","status_checked_at":"2026-01-20T18:54:26.653Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-01-20T20:12:35.245Z","updated_at":"2026-01-20T20:12:36.052Z","avatar_url":"https://github.com/sequenzia.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sequenzia AI\n\nA streaming AI chat application that transforms your portfolio into an interactive conversation. Visitors explore your professional background, experience, projects, and skills through natural dialogue with rich inline content blocks.\n\n## Features\n\n- **Conversational Portfolio** - Visitors chat with an AI assistant to explore your work\n- **Streaming Responses** - Real-time streaming with reasoning display\n- **Rich Content Blocks** - Interactive portfolio sections, charts, code snippets, forms, and cards\n- **Multi-Provider LLM Support** - OpenAI, Google, DeepSeek via AI Gateway\n- **Dark Mode** - System, light, and dark themes with OKLch color system\n- **Responsive Design** - Mobile-optimized with smooth animations\n- **Type-Safe** - Full TypeScript with Zod validation\n\n## Tech Stack\n\n| Category | Technology |\n|----------|------------|\n| Framework | Next.js 16.1 + React 19.2 + TypeScript |\n| AI | Vercel AI SDK v6 + AI Gateway |\n| UI | shadcn/ui (New York) + Custom AI Elements |\n| Styling | Tailwind CSS v4 + OKLch Colors |\n| Animation | Framer Motion |\n| Validation | Zod v4 |\n| State | React Context + TanStack Query |\n| Markdown | Streamdown (streaming renderer) |\n\n## Getting Started\n\n### Prerequisites\n\n- Node.js 18+\n- npm, yarn, or pnpm\n\n### Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/yourusername/portfolio-ai.git\ncd portfolio-ai\n\n# Install dependencies\nnpm install\n```\n\n### Configuration\n\nCreate a `.env.local` file in the root directory:\n\n```env\n# Required\nAI_GATEWAY_API_KEY=your_ai_gateway_key\nTAVILY_API_KEY=your_tavily_key  # For web search (https://tavily.com)\n\n# Optional\nNEXT_PUBLIC_DEFAULT_MODEL_ID=openai/gpt-5-nano  # Default: openai/gpt-5-nano\nNEXT_PUBLIC_DEBUG_ON=true                        # Enable AI SDK devtools\n```\n\n### Development\n\n```bash\nnpm run dev      # Start development server (http://localhost:3000)\nnpm run build    # Production build\nnpm run start    # Start production server\nnpm run lint     # Run ESLint\n```\n\n## Project Structure\n\n```\nsrc/\n├── app/\n│   ├── api/chat/route.ts      # Streaming chat endpoint\n│   ├── globals.css            # Theme tokens + Tailwind\n│   ├── layout.tsx             # Root layout with providers\n│   └── page.tsx               # Main chat page\n├── components/\n│   ├── ai-elements/           # AI-specific UI (message, input, reasoning)\n│   ├── blocks/                # Content block renderers\n│   │   ├── portfolio/         # Portfolio section components\n│   │   ├── ContentBlock.tsx   # Block router\n│   │   ├── ChartContent.tsx   # Chart visualizations\n│   │   ├── CodeContent.tsx    # Syntax highlighting\n│   │   └── FormContent.tsx    # Dynamic forms\n│   ├── chat/                  # Chat management\n│   ├── providers/             # React context providers\n│   └── ui/                    # shadcn/ui components\n├── lib/\n│   ├── ai/                    # AI configuration + tools\n│   ├── motion/                # Animation variants\n│   └── portfolio/             # Portfolio data + config\n└── types/                     # TypeScript definitions\n```\n\n## How It Works\n\n### Architecture\n\n```\nUser Message\n    ↓\nChatProvider (manages conversation state)\n    ↓\nPOST /api/chat { messages, modelId }\n    ↓\nstreamText({\n  model: AI Gateway model,\n  system: Portfolio instructions + metadata,\n  tools: { renderPortfolio },\n})\n    ↓\nStreaming response (text, reasoning, tool calls)\n    ↓\nParts-based rendering:\n  • text → Streamdown markdown\n  • reasoning → Collapsible display\n  • tool-* → Content blocks with animations\n```\n\n### Portfolio Tool\n\nThe AI has access to a `renderPortfolio` tool that displays portfolio sections:\n\n```typescript\nrenderPortfolio({\n  viewType: \"bio\" | \"experience\" | \"projects\" | \"education\" | \"skills\" | \"contact\",\n  filter?: string,      // Filter content (e.g., \"ai\", \"react\")\n  highlightId?: string, // Focus on specific item\n})\n```\n\n### Metadata-First System Prompt\n\nThe system prompt uses a metadata-first approach that provides the AI with a summary of your portfolio content, reducing token usage by ~40-50% while enabling intelligent tool decisions.\n\n## Customization\n\n### Update Portfolio Content\n\nEdit `src/lib/portfolio/data.ts` with your information:\n\n```typescript\nexport const portfolioContent: PortfolioContent = {\n  bio: {\n    name: \"Your Name\",\n    title: \"Your Title\",\n    location: \"Your Location\",\n    summary: \"Your professional summary...\",\n    // ...\n  },\n  experience: [...],\n  projects: [...],\n  education: [...],\n  skills: [...],\n  contact: {...},\n};\n```\n\n### Configure Greeting \u0026 Suggestions\n\nEdit `src/lib/portfolio/config.ts`:\n\n```typescript\nexport const PORTFOLIO_GREETING = \"Your custom greeting message\";\n\nexport const PORTFOLIO_SUGGESTIONS = [\n  { label: \"Bio\", prompt: \"Show me your bio\" },\n  { label: \"Work\", prompt: \"Tell me about your experience\" },\n  // Add or modify suggestions\n];\n```\n\n### Theme Colors\n\nModify OKLch color tokens in `src/app/globals.css`:\n\n```css\n:root {\n  --background: oklch(100% 0 0);\n  --foreground: oklch(14.08% 0.004 285.82);\n  --primary: oklch(20.55% 0.006 285.88);\n  /* ... */\n}\n\n.dark {\n  --background: oklch(13.5% 0.02 265);\n  /* ... */\n}\n```\n\n## Adding Content Blocks\n\nThe content block system is extensible. To add a new block type:\n\n1. **Define the schema** in `src/types/message.ts`:\n```typescript\nexport const myBlockSchema = z.object({\n  type: z.literal(\"my-block\"),\n  data: z.object({ /* your fields */ }),\n});\n```\n\n2. **Create the tool** in `src/lib/ai/tools.ts`:\n```typescript\nexport const myBlockTool = tool({\n  description: \"Renders my custom block\",\n  parameters: myBlockSchema.shape.data,\n  execute: async (params) =\u003e ({ type: \"my-block\", data: params }),\n});\n```\n\n3. **Create the renderer** in `src/components/blocks/MyBlockContent.tsx`\n\n4. **Add to router** in `src/components/blocks/ContentBlock.tsx`:\n```typescript\ncase \"my-block\":\n  return \u003cMyBlockContent data={block.data} /\u003e;\n```\n\n5. **Register the tool** in `src/app/api/chat/route.ts`\n\n## Available Models\n\nThe application supports multiple LLM providers via AI Gateway:\n\n| Provider | Models |\n|----------|--------|\n| OpenAI | GPT-5 Nano, GPT-5 Mini, GPT-4o Mini, GPT-OSS 120B |\n| Google | Gemini 2.0 Flash |\n| DeepSeek | DeepSeek V3.2 |\n\nConfigure the default model with `NEXT_PUBLIC_DEFAULT_MODEL_ID`.\n\n## Portfolio Data Structure\n\n```typescript\ninterface PortfolioContent {\n  bio: {\n    name: string;\n    title: string;\n    location: string;\n    summary: string;\n    highlights: string[];\n    social: { platform: string; url: string; }[];\n  };\n  experience: {\n    id: string;\n    company: string;\n    role: string;\n    period: string;\n    achievements: string[];\n    technologies: string[];\n  }[];\n  projects: {\n    id: string;\n    name: string;\n    description: string;\n    category: string;\n    technologies: string[];\n    featured?: boolean;\n    links?: { label: string; url: string; }[];\n  }[];\n  education: {\n    id: string;\n    institution: string;\n    degree: string;\n    field: string;\n    period: string;\n    honors?: string;\n  }[];\n  skills: {\n    category: string;\n    items: { name: string; proficiency: \"expert\" | \"advanced\" | \"intermediate\"; }[];\n  }[];\n  contact: {\n    email: string;\n    calendly?: string;\n    social: { platform: string; url: string; }[];\n  };\n}\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsequenzia%2Fportfolio-ai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsequenzia%2Fportfolio-ai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsequenzia%2Fportfolio-ai/lists"}