Fastman
A SvelteKit chat app that streams Cerebras responses, supports message editing, and puts rate limits in the interface
Try it
Fastman answers questions about my work through a custom system prompt. Cerebras handles generation, while the interface streams each response as NDJSON instead of waiting for the full message.
Try asking Prakhar something
Why I built it
A portfolio can explain what I shipped, but it cannot answer a follow-up question. I built Fastman to handle those questions without making people wait through a slow chat interface.
The system prompt covers my projects, how I make technical decisions, and how I tend to explain them. It is more useful than a generic assistant wearing my name.
What the chat can do
- Stream responses as they are generated
- Edit an earlier message and regenerate from that point
- Regenerate the latest response
- Render Markdown and highlighted code blocks
- Export a conversation as JSON with ISO timestamps
- Show the remaining rate limit and its reset countdown
Editing an old message removes everything after it. That keeps the conversation linear instead of inventing a branching model the interface does not support.
How it works
Chat.svelte # Message state, requests, and scrolling
Message.svelte # Message rendering and actions
CodeBlock.svelte # Syntax highlighting
EmptyState.svelte # Starter questions
RateLimitOverlay.svelte # Reset state and countdown
The frontend uses SvelteKit 2, Svelte 5 runes, TypeScript, and Tailwind CSS v4. A single /api/chat/+server.ts endpoint validates the request origin, sends the prompt to Cerebras through the Vercel AI SDK, and forwards the streamed response and rate-limit headers.
Decisions that mattered
Cerebras for response time
The first token matters more than the total generation time in a chat interface. Cerebras gave this project the short delay I wanted, and its free tier was enough for a portfolio-sized workload.
Svelte for streaming state
This interface updates the active message, loading state, scroll position, and rate-limit state during one request. Svelte 5 runes kept those updates close to the values they affect, without a stack of React effects.
Visible limits
The API returns its rate-limit headers to the client. The interface shows what remains and replaces the composer with a countdown when the limit is exhausted. A blocked request should not look like a broken one.
The parts that took work
Streaming exposed small timing problems. Scrolling too early missed the newest text. Clearing the loading state too late made a finished answer look unfinished. Each state change had to follow the stream rather than the original request.
The endpoint also checks both origin and referer headers. That does not replace proper authentication, but it stops the public endpoint from being casually reused by another site.