<?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: JD Liu</title>
    <description>The latest articles on DEV Community by JD Liu (@liujd6).</description>
    <link>https://dev.to/liujd6</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%2F4097602%2Fb0043f68-6096-49f7-83fd-e1ce7f799866.png</url>
      <title>DEV Community: JD Liu</title>
      <link>https://dev.to/liujd6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/liujd6"/>
    <language>en</language>
    <item>
      <title>Building an Accessible Visual Scaling Game with Astro and React Islands</title>
      <dc:creator>JD Liu</dc:creator>
      <pubDate>Thu, 17 Sep 2026 04:00:21 +0000</pubDate>
      <link>https://dev.to/liujd6/building-an-accessible-visual-scaling-game-with-astro-and-react-islands-4jae</link>
      <guid>https://dev.to/liujd6/building-an-accessible-visual-scaling-game-with-astro-and-react-islands-4jae</guid>
      <description>&lt;p&gt;I recently built a browser game where the player's answer is a visual ratio rather than a typed number. The static pages use Astro, while the playable area is a focused React island. That boundary made the site easier to keep fast, crawlable, and accessible.&lt;/p&gt;

&lt;p&gt;The game is available at &lt;a href="https://sizeitupparty.com/" rel="noopener noreferrer"&gt;Size It Up Party&lt;/a&gt;. A round shows a fixed reference silhouette and an adjustable target. The player changes the target scale, locks the estimate, and receives a reveal with the actual ratio and score.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the rules outside the component
&lt;/h2&gt;

&lt;p&gt;Normalization, validation, error calculation, and scoring live in a pure TypeScript package. React owns interaction state and rendering, but it does not own the mathematical definition of a valid answer. The same scoring behavior is reusable across Daily and Unlimited modes, and tests remain independent from the DOM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat pointer input as one interface, not the interface
&lt;/h2&gt;

&lt;p&gt;Dragging a scale handle is useful, but it is not sufficient. The game also exposes Smaller, Larger, and Reset controls with visible labels. Keyboard users can reach the same actions, and touch users do not need precise pointer movement.&lt;/p&gt;

&lt;p&gt;The important value is the normalized scale ratio. Pointer gestures, buttons, and keyboard shortcuts are different ways of updating that same value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate object movement from the answer
&lt;/h2&gt;

&lt;p&gt;Players may reposition silhouettes or change the view to inspect them. Those actions must not alter the submitted estimate. The answer is derived only from the target's scale along the named measurement axis.&lt;/p&gt;

&lt;p&gt;Keeping camera state, object position, and answer state separate prevents subtle bugs and makes the reveal deterministic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preserve static HTML
&lt;/h2&gt;

&lt;p&gt;The game island is interactive, but the rest of the page is ordinary Astro output. The heading, instructions, explanation, FAQ, legal links, and metadata are present in the initial HTML. The site does not need to turn an entire landing page into a client-rendered application just because one section is interactive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design the reveal as a stable state
&lt;/h2&gt;

&lt;p&gt;The reveal reuses the same canvas area instead of mounting a second interface below it. This avoids a large layout shift. Text feedback explains direction and error, so color is supportive rather than the only signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test rules and controls separately
&lt;/h2&gt;

&lt;p&gt;Pure scoring tests cover exact answers, symmetric overestimation and underestimation, invalid values, and boundaries. UI tests focus on whether every input method updates the same scale state and whether locking prevents later edits.&lt;/p&gt;

&lt;p&gt;The broader lesson is that a custom visual interaction does not require a custom architecture everywhere. A small interactive island, pure shared rules, and ordinary static content can coexist cleanly.&lt;/p&gt;

</description>
      <category>a11y</category>
    </item>
    <item>
      <title>Designing a Fair Reveal Sequence for a Multiplayer Voice Game</title>
      <dc:creator>JD Liu</dc:creator>
      <pubDate>Tue, 08 Sep 2026 13:24:02 +0000</pubDate>
      <link>https://dev.to/liujd6/designing-a-fair-reveal-sequence-for-a-multiplayer-voice-game-27m3</link>
      <guid>https://dev.to/liujd6/designing-a-fair-reveal-sequence-for-a-multiplayer-voice-game-27m3</guid>
      <description>&lt;p&gt;A voting screen is only the final step of a multiplayer voice game. Fairness begins earlier: before players hear the first recording, while they are working out whose turn it is and whether there are more performances to come.&lt;/p&gt;

&lt;p&gt;This design note comes from the ChoicerVoicer project and uses our independent &lt;a href="https://choicervoicer.games/mimic-party/" rel="noopener noreferrer"&gt;Mimic Party experience&lt;/a&gt; as the context. The product is a private browser game for three to five players: hear a reference, record an impression, listen to the group, and vote. The points below are a review framework, not a claim that we have experimentally measured a particular voting bias.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate the jobs of each phase
&lt;/h2&gt;

&lt;p&gt;A player has a different question in every phase:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Player question&lt;/th&gt;
&lt;th&gt;Useful interface answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reference&lt;/td&gt;
&lt;td&gt;What am I imitating?&lt;/td&gt;
&lt;td&gt;A clear sound and a visible listening state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preparation&lt;/td&gt;
&lt;td&gt;Should I start yet?&lt;/td&gt;
&lt;td&gt;A countdown with an explicit transition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recording&lt;/td&gt;
&lt;td&gt;Is my take being captured?&lt;/td&gt;
&lt;td&gt;A recording interval with progress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reveal&lt;/td&gt;
&lt;td&gt;Whose attempt is this?&lt;/td&gt;
&lt;td&gt;The performer’s name and playback progress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Voting&lt;/td&gt;
&lt;td&gt;Have I heard everyone?&lt;/td&gt;
&lt;td&gt;Voting after the reveal sequence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Results&lt;/td&gt;
&lt;td&gt;What happened to my vote?&lt;/td&gt;
&lt;td&gt;A visible result before the next round&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Trying to answer all six questions on one permanently interactive screen makes the interface harder to read. The primary action should follow the current phase. Controls can remain spatially predictable without implying that every action is available at every moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not make voting race the last recording
&lt;/h2&gt;

&lt;p&gt;If voting becomes available while the final take is still playing, the interface invites users to make a choice before listening is complete. Even without a formal fairness study, that is a clear mismatch between the stated rule and the available action.&lt;/p&gt;

&lt;p&gt;In a review, ask whether an impatient user can cast a vote while another performer is still waiting to be heard. Also inspect the transition between tracks: a brief gap should not look like the end of the whole sequence. A performer label plus a count such as “3 of 5” provides different information from the progress bar within a single recording.&lt;/p&gt;

&lt;h2&gt;
  
  
  Names should remain useful when avatars repeat
&lt;/h2&gt;

&lt;p&gt;People may choose the same character because it is funny or because they like it. A shared avatar is therefore a weak identifier. Keep readable nicknames attached to recordings and voting choices; do not rely on color alone to distinguish players.&lt;/p&gt;

&lt;p&gt;Review a deliberately awkward set of names: two short names, two similar names, and one longer nickname. The test is whether players can still connect the take they heard with the person they mean to select. There is no need to expose account details to solve that problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  A vote result is not a voice-quality assessment
&lt;/h2&gt;

&lt;p&gt;A group may reward similarity, timing, or the attempt that made everybody laugh. Those are different preferences. Interface copy should describe the votes that were cast rather than imply an objective measurement of a person’s voice.&lt;/p&gt;

&lt;p&gt;For example, “Three players voted for this take” is supported by the interaction. “Your voice is 92% accurate” would require a separate measurement method and an explanation of what it measures. If that method does not exist, do not invent precision in the presentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review the experience with an interrupted participant
&lt;/h2&gt;

&lt;p&gt;Useful acceptance questions include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can a late-loading player tell which phase the room is in?&lt;/li&gt;
&lt;li&gt;Does the end of one recording clearly differ from the end of all recordings?&lt;/li&gt;
&lt;li&gt;Can keyboard users identify the current choice and move between candidates?&lt;/li&gt;
&lt;li&gt;Is the current performer still identifiable without color or animation?&lt;/li&gt;
&lt;li&gt;Does a disabled action explain what must happen next?&lt;/li&gt;
&lt;li&gt;After the standings, is another game an explicit host decision?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions can guide a usability review before a team adds more animations or scoring options. They are proposed checks, not a report that every browser and assistive technology combination has passed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep entry conditions as clear as the round rules
&lt;/h2&gt;

&lt;p&gt;In the current Mimic Party flow, hosting requires active membership; creating a room has no credit cost and starting a game costs the host 15 credits. Guests need no subscription. Those conditions belong before the start decision, not after players have already committed to a countdown.&lt;/p&gt;

&lt;p&gt;A good reveal sequence gives everyone a clear opportunity to be heard and everyone else a clear moment to choose. That is a concrete design target even when the performances themselves are happily unpredictable.&lt;/p&gt;

</description>
      <category>design</category>
      <category>gamedev</category>
      <category>software</category>
    </item>
    <item>
      <title>Design Recording Errors Around the Next Safe Action</title>
      <dc:creator>JD Liu</dc:creator>
      <pubDate>Tue, 08 Sep 2026 07:27:17 +0000</pubDate>
      <link>https://dev.to/liujd6/design-recording-errors-around-the-next-safe-action-4pmo</link>
      <guid>https://dev.to/liujd6/design-recording-errors-around-the-next-safe-action-4pmo</guid>
      <description>&lt;p&gt;A recording error is not just a technical status. It is a decision point for someone who may have just delivered a take they do not want to repeat.&lt;/p&gt;

&lt;p&gt;The most useful question for an error message is: &lt;strong&gt;what can this person safely do next?&lt;/strong&gt; Here is a product-design checklist for answering it without promising recovery that the application cannot actually provide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate the failure from the recording
&lt;/h2&gt;

&lt;p&gt;“Something went wrong” leaves two questions unanswered: did capture fail, or did a later step fail? A person needs to know whether their performance still exists before deciding to retry.&lt;/p&gt;

&lt;p&gt;Treat these as separate states in the interface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No recording was captured.&lt;/li&gt;
&lt;li&gt;A take exists locally, but a later operation did not finish.&lt;/li&gt;
&lt;li&gt;A saved take exists and can be reopened.&lt;/li&gt;
&lt;li&gt;The application cannot confirm whether a take is recoverable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are proposed UX categories, not claims about every browser or recording library. Your implementation must establish which category is true before displaying it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write the recovery contract first
&lt;/h2&gt;

&lt;p&gt;For each state, write a short contract: what remains available, what the button will do, and what the user might lose. Then make the message match that contract.&lt;/p&gt;

&lt;p&gt;For example, if a take is still playable, a message could say: “Your take is available below. The video export did not finish. Listen to it before trying export again.” That copy is appropriate only if the player really works and retrying export does not overwrite the take.&lt;/p&gt;

&lt;p&gt;If nothing was captured, be equally direct: “No take was recorded. Check your microphone selection, then record this line again.” Do not use “restore” or “resume” when the next action is actually a fresh recording.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give buttons precise scopes
&lt;/h2&gt;

&lt;p&gt;“Try again” can mean reacquire microphone access, repeat processing, resend an upload, or discard the current take. Those are not interchangeable actions.&lt;/p&gt;

&lt;p&gt;Prefer scoped labels such as “Record this line again,” “Retry export,” or “Choose another microphone.” Put destructive actions apart from safe recovery actions. If replacing a take is unavoidable, explain that before the replacement starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not make reassurance outrun evidence
&lt;/h2&gt;

&lt;p&gt;Avoid “Your work is safe” unless the application can substantiate that promise. A local preview may disappear if the tab closes. A completed upload may not mean the final output exists. A success animation is not a persistence guarantee.&lt;/p&gt;

&lt;p&gt;A narrower statement is often more useful: “This take is still available in this tab.” Pair it with an actual next step, not an instruction to refresh that could remove the only accessible copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the message with a small scenario table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Question the UI must answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Microphone unavailable before capture&lt;/td&gt;
&lt;td&gt;Was anything recorded?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interruption midway through a line&lt;/td&gt;
&lt;td&gt;Is there a usable partial take?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Processing fails after capture&lt;/td&gt;
&lt;td&gt;Can I listen before retrying?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User presses retry twice&lt;/td&gt;
&lt;td&gt;Does another action start or is one already running?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User wants to leave&lt;/td&gt;
&lt;td&gt;What remains available afterward?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Run these checks with the actual product behavior. If the message and behavior disagree, fix the contract rather than adding more reassuring words.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review copy alongside the interaction
&lt;/h2&gt;

&lt;p&gt;I work on &lt;a href="https://choicervoicer.games/" rel="noopener noreferrer"&gt;ChoicerVoicer&lt;/a&gt;, a browser-based voice-acting and dubbing project. This checklist is a general design exercise, not a claim that a particular recovery guarantee exists there.&lt;/p&gt;

&lt;p&gt;The broader lesson is simple: error copy belongs in the same review as state transitions and destructive actions. A beautiful message is still misleading if its button performs the wrong kind of retry.&lt;/p&gt;

</description>
      <category>ux</category>
    </item>
    <item>
      <title>Five UX Lessons from Building a Browser-Based Dubbing Game</title>
      <dc:creator>JD Liu</dc:creator>
      <pubDate>Thu, 27 Aug 2026 13:58:30 +0000</pubDate>
      <link>https://dev.to/liujd6/five-ux-lessons-from-building-a-browser-based-dubbing-game-4lp6</link>
      <guid>https://dev.to/liujd6/five-ux-lessons-from-building-a-browser-based-dubbing-game-4lp6</guid>
      <description>&lt;p&gt;Building a browser-based dubbing game sounds straightforward: play a scene, open the microphone, record a line, and export the result.&lt;/p&gt;

&lt;p&gt;The difficult part is not getting audio into the browser. It is helping someone move from “I want to try this” to a finished performance without making the experience feel like audio-editing software.&lt;/p&gt;

&lt;p&gt;While building ChoicerVoicer.games, I kept running into UX problems that were specific to voice recording. Here are five lessons that shaped the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Ask for microphone access at the moment of intent
&lt;/h2&gt;

&lt;p&gt;A permission prompt shown during page load has no context. The visitor has not chosen a scene, read a line, or decided to perform yet, so the request feels suspicious.&lt;/p&gt;

&lt;p&gt;A better sequence is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Let the visitor browse scenes first.&lt;/li&gt;
&lt;li&gt;Show exactly what the recording step will do.&lt;/li&gt;
&lt;li&gt;Request microphone access only after the visitor presses a clear recording action.&lt;/li&gt;
&lt;li&gt;Explain how to recover if permission is denied.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This does not remove browser friction, but it gives the prompt a reason. The user understands why the browser is asking.&lt;/p&gt;

&lt;p&gt;The denial state also needs to be a real product state. “Microphone unavailable” is not enough. It should explain whether the user needs to change a browser permission, select another input device, or reload after granting access.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Treat every line as a small, reversible task
&lt;/h2&gt;

&lt;p&gt;Recording an entire scene in one take creates pressure. One mistake near the end can make the user feel that all earlier work was wasted.&lt;/p&gt;

&lt;p&gt;Line-by-line recording changes the mental model. Each line becomes a small task with a clear beginning and end:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;listen to the reference,&lt;/li&gt;
&lt;li&gt;prepare,&lt;/li&gt;
&lt;li&gt;record,&lt;/li&gt;
&lt;li&gt;review,&lt;/li&gt;
&lt;li&gt;keep or retry,&lt;/li&gt;
&lt;li&gt;continue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part is reversibility. A retry should replace only the current take, not reset the rest of the performance. Completed lines should remain visibly completed.&lt;/p&gt;

&lt;p&gt;This pattern is useful beyond dubbing. Any creative workflow involving performance, narration, language practice, or repeated capture benefits from dividing a large commitment into recoverable steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Make review part of recording, not a separate editing mode
&lt;/h2&gt;

&lt;p&gt;Creators often want to hear a take immediately. Moving them into a separate editor after every line interrupts the flow, but skipping review removes confidence.&lt;/p&gt;

&lt;p&gt;The compromise is a lightweight review loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;play the recorded take immediately,&lt;/li&gt;
&lt;li&gt;keep the retry action close,&lt;/li&gt;
&lt;li&gt;show which take is currently selected,&lt;/li&gt;
&lt;li&gt;avoid presenting a full timeline unless the task really needs one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to recreate professional audio software. It is to answer one simple question quickly: “Do I want to keep this take?”&lt;/p&gt;

&lt;p&gt;A focused review loop also works better on mobile, where dense editing controls quickly become difficult to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Design recovery before designing the happy path
&lt;/h2&gt;

&lt;p&gt;Browser media workflows fail in more ways than a normal form:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;permission is denied,&lt;/li&gt;
&lt;li&gt;no input device is available,&lt;/li&gt;
&lt;li&gt;the active microphone changes,&lt;/li&gt;
&lt;li&gt;a recording is empty,&lt;/li&gt;
&lt;li&gt;the tab loses focus,&lt;/li&gt;
&lt;li&gt;a mobile browser interrupts capture,&lt;/li&gt;
&lt;li&gt;a user refreshes halfway through a scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These cases should not all collapse into one generic error.&lt;/p&gt;

&lt;p&gt;It helps to classify failures by what the user can do next. Can they retry the current line? Change a permission? Select another device? Continue with previous takes? Start the scene again?&lt;/p&gt;

&lt;p&gt;Recovery copy should describe the next useful action instead of exposing implementation details. Users do not need to know which internal stage failed. They need to know whether their work is safe and how to continue.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. A finished result is part of the onboarding
&lt;/h2&gt;

&lt;p&gt;In a creative tool, the first finished artifact teaches the product better than a long tutorial.&lt;/p&gt;

&lt;p&gt;That changes what “onboarding” means. The product should minimize the distance between selecting a scene and seeing a playable result. Optional settings, accounts, advanced editing, and export choices can wait until they are relevant.&lt;/p&gt;

&lt;p&gt;A useful first-session path is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;choose a short scene,&lt;/li&gt;
&lt;li&gt;record a small number of lines,&lt;/li&gt;
&lt;li&gt;review the combined performance,&lt;/li&gt;
&lt;li&gt;download or share the result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once someone has completed that loop, more advanced features make sense because the user understands the reward.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would do differently
&lt;/h2&gt;

&lt;p&gt;If I were starting the interaction design again, I would prototype denial, retry, refresh, and mobile interruption states at the same time as the main recording flow.&lt;/p&gt;

&lt;p&gt;Media products often look complete in a happy-path demo while still feeling fragile in real use. The recovery states are not polish added at the end; they are part of the core experience.&lt;/p&gt;

&lt;p&gt;You can try the current browser experience at &lt;a href="https://choicervoicer.games" rel="noopener noreferrer"&gt;ChoicerVoicer.games&lt;/a&gt;. It is an independently developed web project, separate from the similarly named downloadable itch.io game.&lt;/p&gt;

&lt;p&gt;I would be interested to hear how other developers handle microphone permissions, retakes, and interrupted recording sessions in browser-based creative tools.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
