15 KiB
Feature Research
Domain: Personal AI chat web application (single-user, OpenAI GPT backend, Blazor WebAssembly) Researched: 2026-03-27 Confidence: HIGH (core features verified against live ChatGPT/Claude, OpenAI API docs, and Blazor ecosystem)
Feature Landscape
Table Stakes (Users Expect These)
Features users assume exist. Missing these = product feels incomplete.
| Feature | Why Expected | Complexity | Notes |
|---|---|---|---|
| Send message and receive response | Core function of any AI chat app | LOW | POST to backend API; backend calls OpenAI chat completions endpoint |
| Streaming token-by-token responses | ChatGPT normalized this; blocking responses feel broken | MEDIUM | Server-Sent Events (SSE) from backend; HttpClient streaming or SignalR on WASM client; creates "typewriter" effect |
| Markdown rendering in AI responses | GPT always responds with markdown; raw markdown is unreadable | MEDIUM | Markdig library on backend or client; MarkupString in Blazor to render HTML; Markdown.ColorCode for syntax highlighting |
| Syntax-highlighted code blocks | Code responses are a primary GPT use-case; unformatted code is unusable | MEDIUM | Markdown.ColorCode NuGet package; note: CsharpToColouredHTML has WASM compatibility issues — use base ColorCode package |
| Copy-to-clipboard on code blocks | Standard expectation from ChatGPT/Claude; users paste code constantly | LOW | JavaScript interop in Blazor (navigator.clipboard.writeText); small JS interop call |
| Multiple named conversations | Users need to separate topics; single-thread apps feel like a toy | MEDIUM | Conversation list in sidebar; each conversation has ID, title, message list; JSON file per conversation |
| Create and switch between conversations | Navigation between conversations is core workflow | LOW | Once multi-conversation storage exists, switching is just loading by ID |
| Delete conversations | Users need to clean up; no delete = clutter accumulates | LOW | Remove JSON file; update conversation list |
| Persist conversation history across sessions | Without persistence, app is useless after refresh | MEDIUM | JSON file storage on disk; load on startup; save on every message |
| Auto-scroll to latest message | Standard chat behavior; missing it feels broken | LOW | JavaScript interop to scroll div; or CSS scroll-behavior |
| Loading/thinking indicator | Users need feedback that a request is in-flight | LOW | Show spinner or "..." while awaiting first token; hide once streaming starts |
| Input disabled during response | Prevent double-submit while response is streaming | LOW | Boolean state flag; disable textarea and button while isStreaming = true |
| Send on Enter key | Standard text input convention for chat | LOW | @onkeydown handler; Shift+Enter for newline |
| Responsive layout | Mobile-friendly is expected even for personal tools | LOW | CSS flexbox/grid; sidebar collapses on small screens |
Differentiators (Competitive Advantage)
Features that set the product apart. Not required, but valuable.
| Feature | Value Proposition | Complexity | Notes |
|---|---|---|---|
| Auto-generated conversation titles | Reduces naming friction; GPT can summarize first message as title | LOW | Call GPT with "Summarize this in 5 words" after first exchange; update conversation title |
| System prompt / persona configuration | Power users want to customize GPT behavior per conversation | MEDIUM | Add systemPrompt field to conversation model; include as first message in API payload |
| Message edit and regenerate | Fix typos without starting over; common in ChatGPT | MEDIUM | Truncate conversation at edited message; resend; requires re-streaming |
| Token usage display | Helps users understand context window consumption; teaches GPT behavior | LOW | OpenAI API returns usage in response; display in footer or message metadata |
| Conversation search | Find a past conversation by keyword | MEDIUM | Client-side search over loaded conversation titles; full-text needs indexing |
| Export conversation | Save as markdown or text file | LOW | Serialize messages to markdown string; trigger browser download via JS interop |
| Model selector (GPT-4o vs GPT-4o-mini) | Cost vs quality tradeoff is real; power users want control | LOW | Dropdown stored in app settings or per-conversation; passed as model parameter in API call |
| Well-commented tutorial-style code | The project doubles as a Blazor learning resource | LOW (implementation cost) | Inline // Blazor: comments on lifecycle hooks, DI, component patterns — this is a core differentiator for this specific project's purpose |
Anti-Features (Commonly Requested, Often Problematic)
Features that seem good but create problems.
| Feature | Why Requested | Why Problematic | Alternative |
|---|---|---|---|
| Authentication / login | "What if someone else uses it?" | Single-user personal tool; adds OAuth complexity with zero value | Leave open; document that it's intentionally single-user |
| Database (SQL/SQLite) | "JSON doesn't scale" | Premature optimization for a personal tool; adds EF Core migration complexity | JSON files are fast, human-readable, and zero-setup — perfect for this scope |
| Real-time sync across tabs | "What if I have two windows open?" | SignalR state sync complexity; no real use case for single user | Reload on focus; acceptable for personal tool |
| Plugin / tool calling system | "GPT can call functions!" | That's LangChain/MCP territory; v2 scope — building it now adds architecture complexity before core chat works | Defer to v2 milestone with LangChain and MCP servers |
| Voice input / output | ChatGPT has it | OpenAI Realtime API is being deprecated May 2026; adds Web Speech API complexity; out of scope | Text-only for v1 |
| Image uploads / multimodal | GPT-4o supports it | WASM file upload + base64 encoding + vision API adds significant complexity | Text chat first; defer multimodal to v2 |
| Conversation branching | "What if I want to explore different answers?" | Complex tree data structure; confusing UX; rare real-world use | Regenerate last response is sufficient for 95% of cases |
| Infinite scroll / lazy loading | "What about long conversations?" | Adds virtual scrolling complexity; JSON load is fine at personal scale | Load full conversation on select; revisit if performance suffers |
| PWA / offline support | "Make it installable" | Service worker complexity; AI chat requires internet anyway | Responsive web design is sufficient |
Feature Dependencies
[JSON File Storage]
└──required by──> [Multiple Conversations]
└──required by──> [Create / Switch / Delete Conversations]
└──required by──> [Persist History Across Sessions]
[OpenAI API Call (blocking)]
└──required by──> [Streaming Responses]
└──required by──> [Loading Indicator]
└──required by──> [Input Disabled During Streaming]
[Markdown Rendering]
└──required by──> [Syntax-Highlighted Code Blocks]
└──required by──> [Copy-to-Clipboard on Code Blocks]
[Streaming Responses] ──enhances──> [Auto-Scroll to Latest Message]
[Multiple Conversations] ──enables──> [Auto-Generated Titles]
[Multiple Conversations] ──enables──> [Conversation Search]
[Multiple Conversations] ──enables──> [Export Conversation]
[System Prompt Config] ──enhances──> [Multiple Conversations]
(each conversation can have its own persona)
[Token Usage Display] ──conflicts with [Streaming]
(usage metadata only available when stream=false or in the final chunk)
Dependency Notes
- JSON File Storage required by Multiple Conversations: Conversations need somewhere to live before the list/switch UI can be built. Storage phase must precede conversation management phase.
- Blocking API call required by Streaming: Must implement the non-streaming call first to understand the request/response shape, then layer SSE streaming on top.
- Markdown Rendering required by Syntax Highlighting: ColorCode is a Markdig pipeline extension — Markdig must be wired in before syntax highlighting can be added.
- Token Usage Display conflicts with Streaming: OpenAI streams individual content chunks; the
usagefield only appears in the final chunk (finish_reason: stop). Implementation must capture the last chunk separately.
MVP Definition
Launch With (v1)
Minimum viable product — what's needed to validate the concept.
- Send message, receive non-streaming GPT response — validates API connectivity and basic loop
- Streaming responses — core UX differentiator; blocking responses feel unacceptable
- Markdown rendering with syntax highlighting — GPT responses are markdown; unrendered output is unusable
- Create / switch / delete multiple conversations — without this, the app is a single disposable thread
- JSON file persistence — conversations must survive page refresh to be useful
- Auto-scroll and loading indicator — baseline polish that makes the app feel complete
- Copy-to-clipboard on code blocks — high-frequency action for developer-focused use
- Tutorial-style inline code comments — this project's defining purpose as a learning resource
Add After Validation (v1.x)
Features to add once core is working.
- Auto-generated conversation titles — reduces friction once the core loop is validated
- System prompt / persona configuration — natural extension once multi-conversation is stable
- Model selector — easy add once API layer is clean; real value for cost control
- Export conversation — low complexity, high occasional value
Future Consideration (v2+)
Features to defer until product-market fit is established.
- Message edit and regenerate — medium complexity; wait until core loop is solid
- Token usage display — useful but not blocking; needs streaming completion handling
- Conversation search — only valuable when there are many conversations to search
- LangChain / agentic workflows — explicitly v2 scope per PROJECT.md
- RAG document retrieval — v2 scope
- MCP server integration — v2 scope
Feature Prioritization Matrix
| Feature | User Value | Implementation Cost | Priority |
|---|---|---|---|
| Send message / receive response | HIGH | LOW | P1 |
| Streaming responses | HIGH | MEDIUM | P1 |
| Markdown + syntax highlighting | HIGH | MEDIUM | P1 |
| Multiple conversations + persistence | HIGH | MEDIUM | P1 |
| Auto-scroll + loading indicator | HIGH | LOW | P1 |
| Copy code to clipboard | HIGH | LOW | P1 |
| Tutorial-style code comments | HIGH (for this project) | LOW | P1 |
| Auto-generated conversation titles | MEDIUM | LOW | P2 |
| System prompt configuration | MEDIUM | MEDIUM | P2 |
| Model selector | MEDIUM | LOW | P2 |
| Export conversation | LOW | LOW | P2 |
| Token usage display | LOW | LOW | P2 |
| Message edit and regenerate | MEDIUM | MEDIUM | P3 |
| Conversation search | LOW | MEDIUM | P3 |
Priority key:
- P1: Must have for launch
- P2: Should have, add when possible
- P3: Nice to have, future consideration
Competitor Feature Analysis
| Feature | ChatGPT (OpenAI) | Claude (Anthropic) | This Project |
|---|---|---|---|
| Streaming responses | Yes, token-by-token | Yes, token-by-token | Yes — SSE via backend API |
| Markdown rendering | Yes | Yes | Yes — Markdig + MarkupString |
| Syntax highlighted code | Yes + copy button | Yes + copy button | Yes — Markdown.ColorCode |
| Multiple conversations (sidebar) | Yes | Yes (Projects) | Yes — JSON file per conversation |
| Conversation persistence | Yes (cloud) | Yes (cloud) | Yes — local JSON files |
| Auto-generated titles | Yes | Yes | v1.x — GPT summarization call |
| System prompt | Via custom instructions | Via system prompt | v1.x — per-conversation field |
| Model selector | Yes (GPT-5.4 variants) | Yes (Opus/Sonnet/Haiku) | v1.x — GPT-4o vs GPT-4o-mini |
| Voice input/output | Yes (Advanced Voice Mode) | No | Deliberately excluded from v1 |
| Image uploads | Yes (multimodal) | Yes (multimodal) | Deliberately excluded from v1 |
| Plugin / tool calling | Yes (via GPT Actions) | Yes (via tool use) | v2 — MCP servers |
| RAG / document search | Yes (file attachments) | Yes (Projects + files) | v2 — RAG milestone |
| Auth / multi-user | Yes | Yes | Deliberately excluded (single user) |
Blazor-Specific Implementation Notes
These are not features per se, but implementation constraints that affect feature complexity in Blazor WebAssembly:
- JavaScript Interop is required for: clipboard access, scroll-to-bottom, syntax highlighting via client-side JS libraries (Highlight.js alternative to server-side ColorCode)
- API key must never reach WASM client: all OpenAI calls must go through the ASP.NET Core backend API — the WASM client calls the backend, the backend calls OpenAI
- Streaming from backend to WASM client: options are SSE (Server-Sent Events via
HttpClientstreaming) or SignalR HubConnection; SSE is simpler for one-way server-to-client streaming; SignalR is better if bidirectional messaging is needed later - MarkupString in Blazor: required to render HTML from Markdig; must be used intentionally as it bypasses Blazor's XSS protections — only render trusted content (GPT output is untrusted; sanitize or accept risk as single-user personal tool)
- Markdown.ColorCode WASM note: base
Markdown.ColorCodepackage works in WASM;Markdown.ColorCode.CSharpToColoredHtmldoes NOT — avoid the latter
Sources
- ChatGPT vs Claude feature comparison 2026 — LogicWeb
- OpenAI Streaming API documentation
- OpenAI Streaming Responses Guide
- OpenAI Conversation State Guide
- Best practices for OpenAI Chat streaming UI — Pamela Fox
- PalmHill.BlazorChat — Blazor WASM + LLM reference implementation
- Blazor Live Preview Markdown with Markdig — Syncfusion
- Markdown.ColorCode NuGet package
- 16 Chat UI Design Patterns 2025
- AI Chat Interface UX Patterns — UXPatterns.dev
- Conversational AI UI Comparison 2025 — IntuitionLabs
- Token management best practices — OpenAI Community
Feature research for: Personal AI Chat WebApp (Blazor WebAssembly + OpenAI GPT) Researched: 2026-03-27