react
Technical notes on web development, DevOps, and AI integration.
53 articles
- 22:45frontend
I Filled the Textarea, React Never Noticed
The text visibly entered the textarea, yet React never saw a change. Why plain assignment fails on controlled components and how the native prototype setter fixes it.
TL;DR: Automating React apps like DeepSeek fails when you set textarea.value directly, because React replaces the setter on each element instance and swallows non-user input events. The fix: grab the native setter from HTMLTextAreaElement.prototype, call it with your text, then dispatch a bubbling input event. Since the icon-only send button has no label, press Enter instead.
#deepseek#react#automation - 15:39ai
That Time a Control Flag Showed Up in the Chat Bubble
A raw CTA_FLAG: YES marker leaked into a live chat bubble. The strip regex only matched end-of-string, and the SSE stream bypassed it entirely.
TL;DR: A CTA_FLAG marker leaked into the UI because the model ignored placement instructions and SSE streaming sent chunks before the strip regex ran. The fix moved CTA data into a structured field on the knowledge source, rendered directly by the frontend. Lesson: never parse UI-critical data out of model prose; use structured fields.
#llm#streaming#sse - 10:40frontend
One Wheel Flick, Two Jobs: Scroll First, Flip Later
Adding wheel paging to my AI answers popup: a listener that never attached, passive-by-default events, edge detection, and reduced motion.
TL;DR: Building wheel-based answer navigation in a React popup hit two traps: the useEffect ran before the dialog content existed, so the listener attached to a null ref, and wheel listeners default to passive in most browsers, silently neutering preventDefault. Fixing both required dependency-aware attachment and an explicit non-passive listener. Scroll-edge detection plus prefers-reduced-motion CSS handles the rest.
#react#frontend#ux - 00:54frontend
Chat result rows, timeline style: metadata first
The time chip and tags in the chat popup were never a CSS problem. Metadata had to travel from SQL up to the DTO before the UI could dress up.
TL;DR: The popup rows looked flat because the API never sent published_at, tags, or categories—the fix started at the database, lifting metadata through repositories, DTOs, and SSE until the frontend had data to render. The existing TimelineRow component was reused across all three popup contexts instead of copying markup. Total cost: seven files, 214 lines added.
#react#pydantic#sqlmodel - 00:33ai
Prompt labels leaked into my AI chat: sanitize both ends
A RINGKAS label leaked into the chat bubble. The fix was not a stricter prompt but sanitizing input and output at both ends of the pipeline.
TL;DR: The author's chatbot kept leaking prompt labels like RINGKAS into answers, and adding prompt prohibitions never fixed it. They moved control to code: sanitizing knowledge-base text before injection and rendering output through react-markdown with rehype-sanitize allowlists. Lesson: prompts give rough direction only; reliable formatting enforcement belongs at input and output boundaries.
#llm-security#react#prompt - 16:38ai
One SSE Stream, Two AI Answers
A chatbot needs both a quick summary and a full explanation from one LLM generation. The answer: marker-based splitting in the SSE stream, with separate cache storage and mid-stream parsing.
#sse#ai#streaming - 15:06frontend
Chat History That Lives in Local Storage
The AI search box now remembers yesterday's questions. The trick: localStorage, a 30-turn cap, and a try/catch that silently surrenders when the browser says no
#react#frontend#nextjs - 13:16frontend
Chat Left, Results Right: Splitting One Overlay Into Two
The source list and the chat fought over one overlay. Two panels with different z-index plus render-time visibility ended the fight.
#react#css#tailwind - 12:55frontend
Search Dialog to AI Thread: One Array, Seven useState Gone
Follow-up questions wiped the previous answer. One ThreadEntry array with functional updates turned the single-slot dialog into a real thread.
#react#nextjs#sse