<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jesper Deng</title>
    <description>The latest articles on DEV Community by Jesper Deng (@jesperdeng).</description>
    <link>https://dev.to/jesperdeng</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3921325%2Fed105e8d-1ec4-4781-97b6-0472188abc23.png</url>
      <title>DEV Community: Jesper Deng</title>
      <link>https://dev.to/jesperdeng</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jesperdeng"/>
    <language>en</language>
    <item>
      <title>I Built an AI Chinese Tutor That Actually Knows the HSK Syllabus</title>
      <dc:creator>Jesper Deng</dc:creator>
      <pubDate>Thu, 08 Oct 2026 08:40:15 +0000</pubDate>
      <link>https://dev.to/jesperdeng/i-built-an-ai-chinese-tutor-that-actually-knows-the-hsk-syllabus-fil</link>
      <guid>https://dev.to/jesperdeng/i-built-an-ai-chinese-tutor-that-actually-knows-the-hsk-syllabus-fil</guid>
      <description>&lt;p&gt;Most AI chat tools are terrible language tutors.&lt;/p&gt;

&lt;p&gt;Ask a generic chatbot to practice Chinese with you and you get walls of text at a difficulty level that has nothing to do with your actual ability. It corrects you politely but vaguely, it invents vocabulary that will never appear on an exam, and it has no memory of what you got wrong last Tuesday.&lt;/p&gt;

&lt;p&gt;That gap is what &lt;a href="https://be-chinese.com/" rel="noopener noreferrer"&gt;Be Chinese&lt;/a&gt; was built to close. It is a free AI Chinese learning platform that teaches toward a specific target: the &lt;strong&gt;HSK&lt;/strong&gt; (汉语水平考试), the standard Mandarin proficiency exam, from level 1 through level 6.&lt;/p&gt;

&lt;p&gt;Here is how I designed and shipped it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Idea: Vocabulary First, Conversation Second
&lt;/h2&gt;

&lt;p&gt;The language-learning market is saturated with AI chat wrappers. You type, it replies, you leave. The problem is that conversation practice without a syllabus is just noise — you practice random sentences and hope they transfer to the exam.&lt;/p&gt;

&lt;p&gt;Be Chinese inverts the order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Learn the vocabulary.&lt;/strong&gt; 5,000+ words across HSK 1-6, each with pinyin, audio, translations in four languages, and example sentences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lock it in with spaced repetition.&lt;/strong&gt; Interactive flashcards schedule reviews at optimal intervals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Then use those words in AI conversation.&lt;/strong&gt; The AI matches vocabulary difficulty to your current level, so you practice the words you just learned, not random advanced prose.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That loop — learn, review, then produce — is the whole product. Everything else supports it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Actually Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AI conversation practice with sentence analysis.&lt;/strong&gt; Chat with an AI tutor at your HSK level. The interesting part is the breakdown panel: any sentence the AI says can be tapped to get a word-by-word analysis with pinyin, part of speech, meaning, and the grammar pattern in play. This is the feature that turns "chatting with a bot" into actual study.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-time correction.&lt;/strong&gt; The AI corrects your grammar and word choice and suggests more natural phrasing. It does not just flag errors; it explains them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Daily study plans.&lt;/strong&gt; One focused lesson a day. New words, review, then a level-matched conversation. Fifteen minutes is enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free level test.&lt;/strong&gt; Twenty-five questions, five minutes, no signup. It places you at an HSK 1-6 level and CEFR level and recommends where to start. This is the lowest-friction entry point into the product, and it does most of the acquisition work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HSK grammar guide.&lt;/strong&gt; 100+ grammar points organized by level, with sentence patterns, worked examples with pinyin, multilingual explanations, and common mistakes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pronunciation and dictation.&lt;/strong&gt; Native audio for every word and sentence, plus a dictation mode for listening practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSV downloads.&lt;/strong&gt; The HSK vocabulary and grammar data can be exported as CSV at any time. Free resources should stay free even if you never subscribe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Four languages.&lt;/strong&gt; English, Chinese, Japanese, and Korean, fully localized — not machine-translated UI strings.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;p&gt;I wanted fast iteration on the front end, cheap infinite-ish scaling on the back end, and first-class internationalization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next.js 15 (App Router) + React 19
TypeScript + Tailwind CSS v4
Drizzle ORM + Cloudflare D1
Cloudflare Workers via OpenNext
better-auth (email + OAuth)
AI SDK v5 through OpenRouter
next-intl for i18n
Stripe / PayPal / Creem for billing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Cloudflare Workers and D1
&lt;/h3&gt;

&lt;p&gt;The entire app runs on Cloudflare Workers with a D1 database. A language-learning app is read-heavy — vocabulary lists, grammar guides, blog content are all public reads that rarely change — while the write path is small: chat messages, study progress, check-ins.&lt;/p&gt;

&lt;p&gt;D1 handles that comfortably. The real win was infrastructure cost: the free tier carries the free users, and the app does not need a big always-on server to stay alive overnight.&lt;/p&gt;

&lt;p&gt;Running Next.js on Workers is done through the &lt;a href="https://opennextjs.org/cloudflare" rel="noopener noreferrer"&gt;OpenNext&lt;/a&gt; adapter. One detail worth calling out: the Worker HTML cache uses a versioned namespace that is only bumped on releases which change the HTML/asset contract. Routine deploys keep the cache namespace stable, so shipping a fix does not silently invalidate every cached page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why OpenRouter
&lt;/h3&gt;

&lt;p&gt;Chat quality for language learning is not uniform across providers, and I wanted to be able to switch without rewriting business logic. Routing through OpenRouter means the model is configuration, not code. The provider layer also supports Gemini, DeepSeek, and image/video generation adapters for other features.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Data
&lt;/h3&gt;

&lt;p&gt;The HSK vocabulary and grammar content lives as static structured data in the repo. That was a deliberate choice: the syllabus is stable and versioned, the content needs to be diffable in git, and shipping it with the build means vocabulary pages are fast and always available. The database stores only what is genuinely per-user — progress, streaks, saved words, chat history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Decisions I Would Make Again
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Free must be genuinely useful.&lt;/strong&gt; New users get 60 free conversation credits, full access to all vocabulary lists, the grammar guide, and the level test, with no credit card. The subscription unlocks unlimited AI conversations and removes message caps. If the free tier is a frustrating demo, nobody converts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One obvious next action per screen.&lt;/strong&gt; The level test is the primary call to action everywhere. Once you know your level, everything else — which words to learn, which grammar to study, how hard the AI talks — follows from it. Leading with features instead of "find your level" would have added friction at exactly the wrong moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sentence analysis over chat history.&lt;/strong&gt; Chats scroll away. A breakdown panel that explains one sentence is worth more than fifty messages you cannot revisit. Learners come back to parse the sentence they did not understand, not to reread yesterday's small talk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where It Stands
&lt;/h2&gt;

&lt;p&gt;The site is live at &lt;a href="https://be-chinese.com/" rel="noopener noreferrer"&gt;be-chinese.com&lt;/a&gt;, fully localized in four languages, with the free tier open to everyone. Paid plans start at $9.90/month, $19.90/quarter, or $49.90/year — all unlimited AI conversation while active, and cancel anytime.&lt;/p&gt;

&lt;p&gt;The honest gap is content depth. The syllabus coverage is broad; the &lt;em&gt;individual&lt;/em&gt; lesson experience is not yet as good as a dedicated human course. That is the next thing I am working on — turning the vocabulary lists and grammar guide into properly guided lesson paths, not just reference material.&lt;/p&gt;

&lt;p&gt;If you are learning Chinese, I would genuinely like to hear what breaks for you. The support inbox is real, and the roadmap is short enough that feedback still changes it.&lt;/p&gt;




&lt;p&gt;Try it: &lt;a href="https://be-chinese.com/" rel="noopener noreferrer"&gt;be-chinese.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hsk</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Built an AI Search Monitoring Platform Because “Are We in ChatGPT?” Shouldn’t Be a Guess</title>
      <dc:creator>Jesper Deng</dc:creator>
      <pubDate>Wed, 07 Oct 2026 09:16:16 +0000</pubDate>
      <link>https://dev.to/jesperdeng/i-built-an-ai-search-monitoring-platform-because-are-we-in-chatgpt-shouldnt-be-a-guess-2m4j</link>
      <guid>https://dev.to/jesperdeng/i-built-an-ai-search-monitoring-platform-because-are-we-in-chatgpt-shouldnt-be-a-guess-2m4j</guid>
      <description>&lt;p&gt;AI search monitoring is a repeatable way to observe whether a brand appears, is mentioned, and is cited in answers to a stable set of buyer questions.&lt;/p&gt;

&lt;p&gt;It is an observation loop, not an official ranking.&lt;/p&gt;

&lt;p&gt;I built AI Search Vitals because traditional SEO reports were not answering a question I kept hearing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When a potential customer asks an AI system for a recommendation, what does it actually say about our brand?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Problem No One Talks About
&lt;/h2&gt;

&lt;p&gt;Traditional search gives you familiar signals: impressions, clicks, rankings, and backlinks.&lt;/p&gt;

&lt;p&gt;AI answers are different.&lt;/p&gt;

&lt;p&gt;The same buyer question can produce different results depending on the model, prompt wording, market, language, retrieval mode, source set, and time of day. A screenshot may show what happened once, but it does not explain whether the result is a pattern.&lt;/p&gt;

&lt;p&gt;There are four problems I wanted to solve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A brand can be relevant to a category but never appear in the answer.&lt;/li&gt;
&lt;li&gt;A brand can be mentioned without being cited as a source.&lt;/li&gt;
&lt;li&gt;A competitor can be recommended while your better explanation is ignored.&lt;/li&gt;
&lt;li&gt;A single visibility score cannot explain what changed or what to fix next.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The hard part is not generating another score. The hard part is preserving enough evidence to understand the answer behind the score.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What I Decided to Build
&lt;/h2&gt;

&lt;p&gt;AI Search Vitals is an AI search visibility monitoring platform for brands, marketing teams, SEO and GEO practitioners, agencies, and founders.&lt;/p&gt;

&lt;p&gt;The workflow starts with a project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a brand, website, market, language, and competitors.&lt;/li&gt;
&lt;li&gt;Save the buyer questions you want to monitor.&lt;/li&gt;
&lt;li&gt;Select the AI channels enabled for the workspace.&lt;/li&gt;
&lt;li&gt;Run an initial baseline.&lt;/li&gt;
&lt;li&gt;Review mentions, recommendations, competitors, and citations.&lt;/li&gt;
&lt;li&gt;Schedule daily or weekly observations.&lt;/li&gt;
&lt;li&gt;Use the results to decide which page, prompt, or content gap to improve.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The product keeps the evidence behind every successful observation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The original buyer prompt&lt;/li&gt;
&lt;li&gt;The actual model and provider&lt;/li&gt;
&lt;li&gt;Market and language&lt;/li&gt;
&lt;li&gt;Search mode and run timestamp&lt;/li&gt;
&lt;li&gt;Raw AI answer&lt;/li&gt;
&lt;li&gt;Brand and competitor mentions&lt;/li&gt;
&lt;li&gt;Ordered recommendation position when available&lt;/li&gt;
&lt;li&gt;Citation URLs, domains, titles, and snippets&lt;/li&gt;
&lt;li&gt;Token usage and request metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it possible to ask better questions than “Did our score go up?”&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the brand move from absent to mentioned?&lt;/li&gt;
&lt;li&gt;Was the mention accurate or misleading?&lt;/li&gt;
&lt;li&gt;Did the model cite our website or a competitor?&lt;/li&gt;
&lt;li&gt;Which page became the source?&lt;/li&gt;
&lt;li&gt;Did the change happen across a prompt group or only once?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI Search Vitals also includes competitor share of voice, citation exploration, prompt research, monitoring history, CSV export, and GEO audit tools for crawlability, content readiness, and AI Query Expansion.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works Under the Hood
&lt;/h2&gt;

&lt;p&gt;The application runs on Next.js 15, React, and TypeScript, with OpenNext and Cloudflare Workers handling the production runtime.&lt;/p&gt;

&lt;p&gt;Workspace, project, prompt, run, observation, mention, and citation data are stored in Cloudflare D1 through Drizzle. OpenRouter adapters keep provider metadata, usage information, citations, and raw response context instead of reducing every response to a plain string.&lt;/p&gt;

&lt;p&gt;Scheduled monitoring uses a server-controlled workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloudflare Cron finds prompts that are due.&lt;/li&gt;
&lt;li&gt;Each prompt and model target becomes a queue job.&lt;/li&gt;
&lt;li&gt;The worker executes the observation.&lt;/li&gt;
&lt;li&gt;The parser extracts mentions, positions, and citations.&lt;/li&gt;
&lt;li&gt;The observation is stored with an idempotency key.&lt;/li&gt;
&lt;li&gt;Retryable provider failures can be inspected without duplicating the result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to make AI search look deterministic.&lt;/p&gt;

&lt;p&gt;The goal is to make changes comparable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Harder Than It Sounds
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Prompt stability matters
&lt;/h3&gt;

&lt;p&gt;If the question changes every time, the result is difficult to compare.&lt;/p&gt;

&lt;p&gt;That is why AI Search Vitals stores prompt snapshots and encourages teams to separate discovery, evaluation, comparison, and task-based questions. A stable prompt set creates a baseline that can be reviewed over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Mentions need context
&lt;/h3&gt;

&lt;p&gt;Counting a brand name is not enough.&lt;/p&gt;

&lt;p&gt;The system needs to distinguish between a useful recommendation, a passing reference, an incorrect description, and a competitor comparison. A mention without context can lead to the wrong content decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. A mention is not a citation
&lt;/h3&gt;

&lt;p&gt;A model can name a brand without linking to its website.&lt;/p&gt;

&lt;p&gt;It can also cite a page for one narrow fact without recommending the whole brand. These are different signals, so they need to be measured separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Citation formats are inconsistent
&lt;/h3&gt;

&lt;p&gt;Different providers can return citations through annotations, markdown links, metadata, or no structured source list at all.&lt;/p&gt;

&lt;p&gt;The parser therefore checks provider annotations first and then uses deterministic URL extraction as a fallback. The result is not perfect, but it is inspectable and tied to the actual answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evidence beats an opaque score
&lt;/h3&gt;

&lt;p&gt;A score can tell you that something changed. Raw answer evidence helps explain why.&lt;/p&gt;

&lt;p&gt;The useful unit is not “visibility increased by 8%.” It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For this prompt and channel, the answer changed, the brand became more specific, and this page became the cited source.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Measurement boundaries build trust
&lt;/h3&gt;

&lt;p&gt;AI Search Vitals does not claim to reproduce the first-party consumer experience of ChatGPT, Google AI Overviews, or any other platform.&lt;/p&gt;

&lt;p&gt;The current product records provider and API proxy observations. These observations are useful for repeatable analysis, but they are not official or universal rankings.&lt;/p&gt;

&lt;p&gt;Google AI Overviews still require a manual check in the target market. Estimated intent is directional, not official search volume. A citation is evidence, not a guarantee of future visibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  GEO and monitoring should be connected
&lt;/h3&gt;

&lt;p&gt;Monitoring tells you what the answer system did.&lt;/p&gt;

&lt;p&gt;A GEO audit helps investigate why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can the page be fetched?&lt;/li&gt;
&lt;li&gt;Are the headings and metadata clear?&lt;/li&gt;
&lt;li&gt;Is the entity defined consistently?&lt;/li&gt;
&lt;li&gt;Does the page contain enough evidence?&lt;/li&gt;
&lt;li&gt;Are there related questions the content should answer?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That creates a loop:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Observe → inspect evidence → improve the page → observe again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;Start with a small prompt set instead of monitoring everything at once.&lt;/p&gt;

&lt;p&gt;Use five to twelve buyer questions across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Category discovery&lt;/li&gt;
&lt;li&gt;Product comparison&lt;/li&gt;
&lt;li&gt;Recommendation&lt;/li&gt;
&lt;li&gt;Problem solving&lt;/li&gt;
&lt;li&gt;Brand-specific queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read the raw answers before reacting to the metrics. Then compare the same prompts, channel, market, and language after a content change.&lt;/p&gt;

&lt;p&gt;At the time of writing, AI Search Vitals includes a seven-day trial without a credit card, so the easiest way to start is with one project and a focused baseline.&lt;/p&gt;

&lt;p&gt;You can try &lt;a href="https://aisearchvitals.com/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=ai-search-monitoring-build" rel="noopener noreferrer"&gt;AI Search Vitals&lt;/a&gt;, read the &lt;a href="https://aisearchvitals.com/blog/ai-search-monitoring-guide" rel="noopener noreferrer"&gt;AI Search Monitoring Guide&lt;/a&gt;, or review the &lt;a href="https://aisearchvitals.com/blog/how-to-track-ai-citations" rel="noopener noreferrer"&gt;AI Citation Tracking Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am especially interested in hearing how other teams measure AI visibility without turning a changing answer into a fake ranking report.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>seo</category>
    </item>
    <item>
      <title>I Built an AI Mock Trial Platform Because Practicing Law Shouldn't Require a Full Cast</title>
      <dc:creator>Jesper Deng</dc:creator>
      <pubDate>Wed, 20 May 2026 05:20:41 +0000</pubDate>
      <link>https://dev.to/jesperdeng/i-built-an-ai-mock-trial-platform-because-practicing-law-shouldnt-require-a-full-cast-2cl5</link>
      <guid>https://dev.to/jesperdeng/i-built-an-ai-mock-trial-platform-because-practicing-law-shouldnt-require-a-full-cast-2cl5</guid>
      <description>&lt;h2&gt;
  
  
  The Problem No One Talks About
&lt;/h2&gt;

&lt;p&gt;If you're a law student preparing for mock trial, or a lawyer rehearsing for court, you face a frustrating reality: you can't practice alone.&lt;/p&gt;

&lt;p&gt;A real trial involves a judge, opposing counsel, witnesses, and jurors. To run even a basic practice session, you need to coordinate 3-5 people's schedules. Most of the time, that just doesn't happen.&lt;/p&gt;

&lt;p&gt;So what do people actually do?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Law students&lt;/strong&gt; rehearse opening statements in front of a mirror&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mock trial teams&lt;/strong&gt; only get 1-2 full run-throughs before competition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Young lawyers&lt;/strong&gt; go into their first trial with almost no live courtroom experience&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solo practitioners&lt;/strong&gt; have zero way to simulate cross-examination or hostile witnesses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fundamental bottleneck isn't skill — it's access to practice partners.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Decided to Build
&lt;/h2&gt;

&lt;p&gt;I asked a simple question: what if AI could play every other role in the courtroom?&lt;/p&gt;

&lt;p&gt;Not a chatbot that answers legal questions. Not a document tool. A full courtroom simulation where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You play the attorney (plaintiff or defense)&lt;/li&gt;
&lt;li&gt;AI plays the &lt;strong&gt;judge&lt;/strong&gt; — ruling on objections, managing procedure&lt;/li&gt;
&lt;li&gt;AI plays &lt;strong&gt;opposing counsel&lt;/strong&gt; — making arguments against you, objecting to your questions&lt;/li&gt;
&lt;li&gt;AI plays &lt;strong&gt;witnesses&lt;/strong&gt; — responding to direct and cross-examination with realistic personalities&lt;/li&gt;
&lt;li&gt;The trial follows real procedure: voir dire → opening → witness examination → closing → verdict&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end, you get scored on your performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Harder Than It Sounds
&lt;/h2&gt;

&lt;p&gt;The challenge isn't just "make AI talk like a lawyer." It's:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Multi-role coherence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The judge, opposing counsel, and witness are all AI — but they need to behave as separate people with different goals. The judge is neutral. Opposing counsel is adversarial. The witness has a backstory and may be unreliable. One model, multiple conflicting personas, in the same conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Stage management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A trial isn't a free-form chat. It has strict procedural stages. You can't cross-examine during opening statements. The AI needs to enforce courtroom rules while still feeling natural.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Reactive complexity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you raise an objection, the judge must rule. If sustained, opposing counsel must rephrase. If you introduce surprise evidence, the witness must react consistently with their backstory. Every action cascades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Solo practice must feel real&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If it feels like talking to a chatbot, lawyers won't use it. The responses need enough unpredictability and pushback to create genuine practice pressure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start with the state machine, not the prompts.&lt;/strong&gt; I spent too long tweaking AI personalities before realizing the real problem was managing trial flow. Once I built a proper stage system (8 stages, with rules for what's allowed in each), the AI behavior fell into place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring creates motivation.&lt;/strong&gt; Early testers would quit mid-trial. Adding a verdict with performance scoring changed everything — people now complete full trials because they want to see their score.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credits &amp;gt; subscriptions for this audience.&lt;/strong&gt; Law students are broke. A generous free tier with credits lets them actually use the tool. Power users (practicing attorneys) will pay when they see the value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;If you're curious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live platform:&lt;/strong&gt; &lt;a href="https://mocktrialonline.com" rel="noopener noreferrer"&gt;mocktrialonline.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demo video:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=CNXzT5zIVpg" rel="noopener noreferrer"&gt;YouTube walkthrough&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's free to sign up and run several full trials without paying. I'm a solo developer building this actively — feedback from anyone (devs, lawyers, or just people curious about legal AI) is genuinely welcome.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>buildinpublic</category>
      <category>startup</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I Made AI Behave Differently Based on Conversation Context (Multi-Role Prompt Engineering)</title>
      <dc:creator>Jesper Deng</dc:creator>
      <pubDate>Sat, 09 May 2026 08:35:09 +0000</pubDate>
      <link>https://dev.to/jesperdeng/how-i-made-ai-behave-differently-based-on-conversation-context-multi-role-prompt-engineering-26o6</link>
      <guid>https://dev.to/jesperdeng/how-i-made-ai-behave-differently-based-on-conversation-context-multi-role-prompt-engineering-26o6</guid>
      <description>&lt;p&gt;I've been working on a project that requires multiple AI "characters" to behave differently in the same conversation — think of it like NPCs in a game, except each one needs to respond based on their role, personality, and the current situation.&lt;/p&gt;

&lt;p&gt;Here's what I learned about making this work reliably.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;If you just tell an AI "you are character A" and "you are character B" in separate prompts, they all end up sounding the same. Generic. Helpful. Boring. You need them to have distinct behaviors — one should be cooperative, another defensive, another authoritative.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Behavioral constraints &amp;gt; personality descriptions
&lt;/h3&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a friendly witness who is helpful.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a witness being questioned. Rules:
- Only answer what is directly asked
- If the question is vague, ask for clarification
- Never volunteer extra information
- If pressed on a contradiction, become defensive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Constraints produce more consistent behavior than adjectives.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Context-dependent behavior switching
&lt;/h3&gt;

&lt;p&gt;The same character might need to behave differently depending on who's talking to them. I handle this by passing a &lt;code&gt;mode&lt;/code&gt; parameter in the system prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;friendly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hostile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You are &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Background: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bio&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;friendly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n\nBehavior: Be cooperative. Give detailed answers. Expand on your responses when appropriate.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n\nBehavior: Be defensive. Give minimal answers. Only confirm what you cannot deny. Redirect when possible.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tiny switch makes a huge difference in how natural the responses feel.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. State management across turns
&lt;/h3&gt;

&lt;p&gt;The hardest part: making characters remember what happened earlier and adjust. I maintain a simplified state object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ConversationState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;currentSpeaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;previousStatements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;contradictions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;mood&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;neutral&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;defensive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;confident&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before each AI call, I inject a summary of what's happened so far. This keeps responses contextually aware without blowing up the token count.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The "don't be helpful" problem
&lt;/h3&gt;

&lt;p&gt;LLMs are trained to be helpful. When you need a character to be evasive or unhelpful, you have to fight against this training. What works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicitly say "you do NOT want to help the questioner"&lt;/li&gt;
&lt;li&gt;Give the character a motivation for being difficult&lt;/li&gt;
&lt;li&gt;Add examples of deflection in the prompt
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are being questioned about something you want to hide.
Your goal is to answer without revealing [specific fact].
Techniques you use: giving technically true but misleading answers,
answering a different question than what was asked, saying "I don't recall."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Temperature matters more than you think
&lt;/h3&gt;

&lt;p&gt;For authoritative characters (judges, experts), use lower temperature (0.3-0.5). They should be consistent and decisive.&lt;/p&gt;

&lt;p&gt;For emotional or unpredictable characters, bump it up (0.7-0.9). The randomness makes them feel more human.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaway
&lt;/h2&gt;

&lt;p&gt;Multi-role AI isn't about writing better character descriptions. It's about defining behavioral rules, injecting context, and fighting the model's default "helpful assistant" mode. Once I figured that out, everything clicked.&lt;/p&gt;

&lt;p&gt;Would love to hear if anyone else is doing multi-agent stuff — what patterns are you using?&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
  </channel>
</rss>
