<?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: sgamer宇</title>
    <description>The latest articles on DEV Community by sgamer宇 (@sgamer_560ef5490592e4dc9).</description>
    <link>https://dev.to/sgamer_560ef5490592e4dc9</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%2F3660227%2F98cdb0fb-c816-4431-af46-84319f1d98b7.png</url>
      <title>DEV Community: sgamer宇</title>
      <link>https://dev.to/sgamer_560ef5490592e4dc9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sgamer_560ef5490592e4dc9"/>
    <language>en</language>
    <item>
      <title>Building a Privacy-Friendly AI Music Tool That Runs Entirely in the Browser</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Sun, 25 Oct 2026 09:59:19 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/building-a-privacy-friendly-ai-music-tool-that-runs-entirely-in-the-browser-1gd2</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/building-a-privacy-friendly-ai-music-tool-that-runs-entirely-in-the-browser-1gd2</guid>
      <description>&lt;h1&gt;
  
  
  Building a Privacy-Friendly AI Music Tool That Runs Entirely in the Browser
&lt;/h1&gt;

&lt;p&gt;When people think about AI-powered web applications, they usually imagine a familiar architecture:&lt;/p&gt;

&lt;p&gt;The user uploads a file, a backend sends it to an AI service, and the server returns the result.&lt;/p&gt;

&lt;p&gt;That approach works, but it isn't the only option.&lt;/p&gt;

&lt;p&gt;Modern browsers can perform surprisingly complex machine learning tasks locally.&lt;/p&gt;

&lt;p&gt;For certain workloads, this makes it possible to build useful AI applications without sending a user's private file to a processing server.&lt;/p&gt;

&lt;p&gt;Music chord recognition is an interesting example.&lt;/p&gt;

&lt;p&gt;Let's look at the architecture, technical trade-offs, and user experience challenges involved in running audio analysis directly in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Why Run AI Locally?
&lt;/h2&gt;

&lt;p&gt;Consider an application that detects chord progressions from uploaded audio.&lt;/p&gt;

&lt;p&gt;A conventional implementation might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User selects audio
        ↓
Upload to server
        ↓
Server preprocesses audio
        ↓
AI model runs
        ↓
Return chord predictions
        ↓
Display results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This introduces several challenges.&lt;/p&gt;

&lt;p&gt;Large audio uploads consume bandwidth.&lt;/p&gt;

&lt;p&gt;Server-side inference requires compute resources.&lt;/p&gt;

&lt;p&gt;Users may be uncomfortable uploading private recordings.&lt;/p&gt;

&lt;p&gt;And as usage increases, inference costs can become difficult to predict.&lt;/p&gt;

&lt;p&gt;An alternative is to move the audio processing and model inference into the browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User selects audio
        ↓
Browser decodes audio
        ↓
Extract audio features locally
        ↓
Run downloaded AI model
        ↓
Post-process predictions
        ↓
Display chord timeline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file doesn't need to leave the user's device for processing.&lt;/p&gt;

&lt;p&gt;This changes both the privacy model and the infrastructure economics.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Browsers Can Decode Audio Locally
&lt;/h2&gt;

&lt;p&gt;The Web Audio API provides browser-native audio processing capabilities.&lt;/p&gt;

&lt;p&gt;For example, you can decode a user-selected audio file into an &lt;code&gt;AudioBuffer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decodeAudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&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;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AudioContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;try&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;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&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;audioBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decodeAudioData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;audioBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;sampleRate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;audioBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sampleRate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;channels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;audioBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;numberOfChannels&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;audioBuffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&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 example assumes the selected file uses an audio format supported by the browser.&lt;/p&gt;

&lt;p&gt;It doesn't upload the file.&lt;/p&gt;

&lt;p&gt;Instead, the browser decodes it locally into audio samples that can be used for further processing.&lt;/p&gt;

&lt;p&gt;But decoding is just the first step.&lt;/p&gt;

&lt;p&gt;The next challenge is converting the audio into information that a machine learning model can understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Turning Sound into Musical Features
&lt;/h2&gt;

&lt;p&gt;A raw audio waveform contains changes in sound pressure over time.&lt;/p&gt;

&lt;p&gt;A chord recognition system needs to estimate harmonic relationships from those samples.&lt;/p&gt;

&lt;p&gt;One common technique is the Constant-Q Transform (CQT).&lt;/p&gt;

&lt;p&gt;Unlike a conventional FFT with equally spaced frequency bins, CQT uses logarithmically spaced frequency bins.&lt;/p&gt;

&lt;p&gt;This is useful for many musical tasks because musical pitch relationships are logarithmic.&lt;/p&gt;

&lt;p&gt;For example, moving up one octave doubles the frequency.&lt;/p&gt;

&lt;p&gt;A feature extraction stage can transform the audio into a time-frequency representation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audio samples
      ↓
Resampling / preprocessing
      ↓
CQT feature extraction
      ↓
Time-frequency matrix
      ↓
Chord recognition model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact preprocessing steps must match what the model expects.&lt;/p&gt;

&lt;p&gt;A mismatch in sample rate, normalization, frequency bins, or tensor layout can seriously reduce prediction quality.&lt;/p&gt;

&lt;p&gt;This is an important engineering lesson:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A good model is only one part of a good inference pipeline.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Running ONNX Models in a Browser
&lt;/h2&gt;

&lt;p&gt;ONNX provides a portable format for representing machine learning models.&lt;/p&gt;

&lt;p&gt;With ONNX Runtime Web, a compatible model can execute in the browser using supported backends such as WebAssembly.&lt;/p&gt;

&lt;p&gt;A simplified inference flow might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ort&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;onnxruntime-web&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The model URL and tensor shapes are examples.&lt;/span&gt;
&lt;span class="c1"&gt;// Real applications must match the model's inputs.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;InferenceSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/models/chord-model.onnx&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="na"&gt;executionProviders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wasm&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="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Input preparation depends on the model.&lt;/span&gt;
&lt;span class="c1"&gt;// The feature matrix must be converted&lt;/span&gt;
&lt;span class="c1"&gt;// into the expected tensor representation.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difficult part isn't simply loading the ONNX file.&lt;/p&gt;

&lt;p&gt;You also need to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model download and initialization&lt;/li&gt;
&lt;li&gt;Audio preprocessing&lt;/li&gt;
&lt;li&gt;Tensor creation&lt;/li&gt;
&lt;li&gt;Memory usage&lt;/li&gt;
&lt;li&gt;Inference execution&lt;/li&gt;
&lt;li&gt;Chord label decoding&lt;/li&gt;
&lt;li&gt;Prediction smoothing&lt;/li&gt;
&lt;li&gt;Timeline generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And because this work runs on the user's device, performance characteristics vary.&lt;/p&gt;

&lt;p&gt;A powerful desktop may handle a model comfortably, while a low-memory mobile device may struggle.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Designing the First Model Download
&lt;/h2&gt;

&lt;p&gt;Local AI introduces a user experience problem that traditional web applications don't always have.&lt;/p&gt;

&lt;p&gt;The model needs to be downloaded before inference.&lt;/p&gt;

&lt;p&gt;Depending on its size and the user's internet connection, this may take noticeable time.&lt;/p&gt;

&lt;p&gt;A good interface should make the process understandable.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1] Audio selected
      ↓
[2] Model download required
      ↓
[3] Downloading model
      ↓
[4] Initializing AI runtime
      ↓
[5] Preparing audio features
      ↓
[6] Analyzing chords
      ↓
[7] Displaying results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These stages communicate different kinds of work.&lt;/p&gt;

&lt;p&gt;A download progress indicator should represent actual network progress when measurable.&lt;/p&gt;

&lt;p&gt;An analysis progress indicator should not pretend to provide exact percentages unless the application can calculate them.&lt;/p&gt;

&lt;p&gt;And if the model can be cached, the interface should explain that subsequent use may not require downloading the same resources again.&lt;/p&gt;

&lt;p&gt;Good feedback matters because users don't know what the browser is doing behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. A Real Example: ChordFold
&lt;/h2&gt;

&lt;p&gt;One example of a browser-based approach is &lt;a href="https://chordfold.com/" rel="noopener noreferrer"&gt;ChordFold&lt;/a&gt;, an AI chord finder for analyzing music recordings.&lt;/p&gt;

&lt;p&gt;It uses a BTC-based chord recognition model with ONNX Runtime.&lt;/p&gt;

&lt;p&gt;Users can select MP3, WAV, or other browser-supported audio files within the site's size and duration limits.&lt;/p&gt;

&lt;p&gt;The audio is decoded and analyzed locally on their device, rather than being uploaded to a remote inference server.&lt;/p&gt;

&lt;p&gt;The interface allows users to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explore estimated chord progressions&lt;/li&gt;
&lt;li&gt;Follow chord changes over time&lt;/li&gt;
&lt;li&gt;Replay sections of the recording&lt;/li&gt;
&lt;li&gt;View supported guitar chord diagrams&lt;/li&gt;
&lt;li&gt;Inspect corresponding piano notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is particularly interesting because the output isn't just a static prediction.&lt;/p&gt;

&lt;p&gt;The chord labels are connected to the original audio, creating a practical tool for listening and musical exploration.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Why Chord Recognition Isn't Perfect
&lt;/h2&gt;

&lt;p&gt;Automatic chord recognition is a difficult problem even with deep learning.&lt;/p&gt;

&lt;p&gt;An audio recording might contain several instruments playing simultaneously.&lt;/p&gt;

&lt;p&gt;Guitar distortion introduces additional harmonics.&lt;/p&gt;

&lt;p&gt;The melody may contain notes outside the underlying chord.&lt;/p&gt;

&lt;p&gt;Extended chords and inversions create further ambiguity.&lt;/p&gt;

&lt;p&gt;For example, a simple progression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C → G → Am → F
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;might be relatively straightforward in a clean piano recording.&lt;/p&gt;

&lt;p&gt;But a dense arrangement with vocals, bass, electric guitars, and effects can produce much more ambiguous features.&lt;/p&gt;

&lt;p&gt;There's also a timing problem.&lt;/p&gt;

&lt;p&gt;The model may identify the correct chord but place the transition slightly too early or late.&lt;/p&gt;

&lt;p&gt;This is why a useful interface should let people inspect the results rather than treating the model's predictions as unquestionable facts.&lt;/p&gt;

&lt;p&gt;For music learning, a partially correct chord timeline can still be valuable.&lt;/p&gt;

&lt;p&gt;It gives users a starting point for listening, checking, and practicing.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. The Trade-Offs of Local Inference
&lt;/h2&gt;

&lt;p&gt;Browser-based AI isn't automatically better for every application.&lt;/p&gt;

&lt;p&gt;It has meaningful advantages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Selected user files can remain on the device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Predictable server inference costs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The server doesn't need to process every uploaded recording.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lower dependency on remote inference availability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the application and model resources are loaded, inference can happen locally.&lt;/p&gt;

&lt;p&gt;But the disadvantages matter too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initial download&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Models may require a significant download.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Device limitations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Memory and CPU performance vary dramatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browser compatibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not every browser supports the same acceleration backends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Large audio files and intermediate feature arrays can use substantial memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Changing the model requires managing new resources and potentially invalidating cached versions.&lt;/p&gt;

&lt;p&gt;A robust product must handle these trade-offs carefully.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. When Should You Consider This Architecture?
&lt;/h2&gt;

&lt;p&gt;Local inference makes sense when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The model fits reasonably within client-device limits.&lt;/li&gt;
&lt;li&gt;Data privacy is important.&lt;/li&gt;
&lt;li&gt;Inference doesn't require extremely large hardware resources.&lt;/li&gt;
&lt;li&gt;The application can tolerate device-dependent performance.&lt;/li&gt;
&lt;li&gt;You want to avoid a server inference request for every user action.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Audio analysis, image classification, certain text-processing tasks, and other specialized workloads may fit this pattern.&lt;/p&gt;

&lt;p&gt;However, large generative models or applications requiring powerful GPUs may still benefit from server-side infrastructure.&lt;/p&gt;

&lt;p&gt;The correct choice depends on the workload, user devices, and product requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Browser-based AI has become a practical architecture for more than simple demonstrations.&lt;/p&gt;

&lt;p&gt;With the Web Audio API, machine learning runtimes, and efficient preprocessing, web applications can perform meaningful analysis locally.&lt;/p&gt;

&lt;p&gt;A music chord finder is a useful example because it combines several engineering challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Audio decoding&lt;/li&gt;
&lt;li&gt;Musical feature extraction&lt;/li&gt;
&lt;li&gt;Model inference&lt;/li&gt;
&lt;li&gt;Temporal prediction processing&lt;/li&gt;
&lt;li&gt;Interactive visualization&lt;/li&gt;
&lt;li&gt;Privacy and memory management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result can be an application that doesn't require users to upload personal recordings to a processing server.&lt;/p&gt;

&lt;p&gt;If you're interested in seeing this approach from the user's perspective, you can explore &lt;a href="https://chordfold.com/" rel="noopener noreferrer"&gt;ChordFold's browser-based chord finder&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It demonstrates how local AI can turn an ordinary audio file into an interactive musical learning tool.&lt;/p&gt;

&lt;p&gt;For developers, the larger opportunity is clear: not every AI feature needs a cloud inference endpoint.&lt;/p&gt;

&lt;p&gt;Sometimes, the browser itself is enough.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>privacy</category>
      <category>webdev</category>
    </item>
    <item>
      <title># Your Browser Says 60 FPS — But Is Your GPU Actually Fast?</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Sun, 25 Oct 2026 09:58:19 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/-your-browser-says-60-fps-but-is-your-gpu-actually-fast-1hbb</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/-your-browser-says-60-fps-but-is-your-gpu-actually-fast-1hbb</guid>
      <description>&lt;h1&gt;
  
  
  Your Browser Says 60 FPS — But Is Your GPU Actually Fast?
&lt;/h1&gt;

&lt;p&gt;You open a browser performance test and see a steady 60 FPS.&lt;/p&gt;

&lt;p&gt;Does that mean your graphics card is powerful?&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;This is a surprisingly common misunderstanding when evaluating browser graphics performance.&lt;/p&gt;

&lt;p&gt;A smooth animation, a GPU stress benchmark, and a WebGPU compatibility check all measure different things.&lt;/p&gt;

&lt;p&gt;Let's explore the differences and build a small frame-timing experiment using JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What Does Browser FPS Actually Measure?
&lt;/h2&gt;

&lt;p&gt;Browsers expose &lt;code&gt;requestAnimationFrame()&lt;/code&gt;, an API that schedules callbacks before visual updates.&lt;/p&gt;

&lt;p&gt;Here's a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&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;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastTime&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;delta&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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;fps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`FPS: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;lastTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This measures the interval between animation callbacks.&lt;/p&gt;

&lt;p&gt;It can help you investigate animation timing.&lt;/p&gt;

&lt;p&gt;But it doesn't directly measure the maximum rendering capability of your GPU.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;requestAnimationFrame()&lt;/code&gt; is influenced by the browser's rendering schedule and the display's refresh rate.&lt;/p&gt;

&lt;p&gt;On a typical 60 Hz display, a lightweight animation may produce approximately 60 callbacks per second.&lt;/p&gt;

&lt;p&gt;That doesn't mean the GPU couldn't render a much heavier or lighter workload at a different rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Build a More Useful Frame-Timing Test
&lt;/h2&gt;

&lt;p&gt;Instead of only displaying an instantaneous FPS value, collect multiple frame intervals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intervals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;previousTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;measureFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&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;startTime&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;previousTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;measureFrame&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;intervals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;previousTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;previousTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&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;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;measureFrame&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;intervals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;0&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;averageFPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;total&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;sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;intervals&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;a&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;slowCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.01&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;slowIntervals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;slowCount&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;slowMean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;slowIntervals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;slowIntervals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;onePercentLow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;slowMean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;averageFPS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;onePercentLow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;frameCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;intervals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;measureFrame&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This collects roughly five seconds of animation intervals.&lt;/p&gt;

&lt;p&gt;It then calculates two useful metrics:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Average FPS:&lt;/strong&gt; The number of completed intervals divided by total measurement time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1% Low FPS:&lt;/strong&gt; An estimate based on the slowest 1% of recorded intervals.&lt;/p&gt;

&lt;p&gt;Be careful with short measurements. Tail metrics are especially noisy when the sample contains relatively few frames.&lt;/p&gt;

&lt;p&gt;This example is an educational timing experiment, not a calibrated GPU benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Why Frame Time Matters More Than You Think
&lt;/h2&gt;

&lt;p&gt;Consider two hypothetical rendering sessions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session A&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average FPS: 60&lt;/li&gt;
&lt;li&gt;Most frames: 16–17 ms&lt;/li&gt;
&lt;li&gt;Few large spikes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Session B&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average FPS: 60&lt;/li&gt;
&lt;li&gt;Frequent irregular intervals&lt;/li&gt;
&lt;li&gt;Occasional 50–100 ms delays&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both report the same average FPS, but Session B may feel much less responsive.&lt;/p&gt;

&lt;p&gt;This is why frame-time consistency is important.&lt;/p&gt;

&lt;p&gt;A 16.7 ms interval corresponds to approximately 60 FPS.&lt;/p&gt;

&lt;p&gt;A 33.3 ms interval corresponds to approximately 30 FPS.&lt;/p&gt;

&lt;p&gt;And a 100 ms interruption can create a noticeable pause.&lt;/p&gt;

&lt;p&gt;When investigating stuttering, don't focus only on average frame rate.&lt;/p&gt;

&lt;p&gt;Inspect the distribution of frame intervals and repeat your measurements under similar conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. A Lightweight FPS Test Is Not a GPU Stress Test
&lt;/h2&gt;

&lt;p&gt;This is the most important distinction.&lt;/p&gt;

&lt;p&gt;A simple animation loop might barely use the GPU.&lt;/p&gt;

&lt;p&gt;Even if the browser updates smoothly at 60 FPS, the test may not be generating enough rendering work to meaningfully challenge the graphics hardware.&lt;/p&gt;

&lt;p&gt;A proper graphics stress workload needs to perform sustained rendering operations.&lt;/p&gt;

&lt;p&gt;Depending on the implementation, this can involve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shader execution&lt;/li&gt;
&lt;li&gt;Procedural geometry&lt;/li&gt;
&lt;li&gt;Fragment processing&lt;/li&gt;
&lt;li&gt;High-resolution rendering&lt;/li&gt;
&lt;li&gt;Repeated frame submission&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workload should remain consistent enough that results can be compared.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://webgpustress.com/" rel="noopener noreferrer"&gt;WebGPUStress&lt;/a&gt; provides a browser-based WebGL stress test with configurable resolution, quality, duration, and target FPS.&lt;/p&gt;

&lt;p&gt;It reports metrics including average FPS, 1% low FPS, dropped frames, and frame-time consistency.&lt;/p&gt;

&lt;p&gt;The test is useful for observing how a browser handles sustained graphics work.&lt;/p&gt;

&lt;p&gt;However, it cannot directly measure GPU temperature or certify hardware stability.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. WebGPU Compatibility Is Another Separate Question
&lt;/h2&gt;

&lt;p&gt;WebGPU is a modern browser API for graphics and compute workloads.&lt;/p&gt;

&lt;p&gt;You can check whether the API exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gpu&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But API availability is not the same as successful execution.&lt;/p&gt;

&lt;p&gt;A more useful compatibility test needs to verify several operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Request a GPU adapter.&lt;/li&gt;
&lt;li&gt;Create a GPU device.&lt;/li&gt;
&lt;li&gt;Compile a WGSL shader.&lt;/li&gt;
&lt;li&gt;Execute a rendering pipeline.&lt;/li&gt;
&lt;li&gt;Run a compute workload.&lt;/li&gt;
&lt;li&gt;Verify the resulting output.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href="https://webgpustress.com/webgpu-test" rel="noopener noreferrer"&gt;WebGPU compatibility checker&lt;/a&gt; performs these kinds of checks directly in the browser.&lt;/p&gt;

&lt;p&gt;That helps distinguish a missing API from a failure during device creation, shader compilation, or pipeline execution.&lt;/p&gt;

&lt;p&gt;But passing the test doesn't prove that your GPU is faster than another GPU.&lt;/p&gt;

&lt;p&gt;Compatibility and performance are separate measurements.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. How to Run a Meaningful Comparison
&lt;/h2&gt;

&lt;p&gt;Suppose you've just updated your graphics driver and want to know whether browser GPU performance changed.&lt;/p&gt;

&lt;p&gt;A reasonable approach is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before updating:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a fixed browser version.&lt;/li&gt;
&lt;li&gt;Choose a benchmark profile.&lt;/li&gt;
&lt;li&gt;Close unnecessary GPU-intensive applications.&lt;/li&gt;
&lt;li&gt;Run the test several times.&lt;/li&gt;
&lt;li&gt;Save the results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After updating:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep the same hardware and power mode.&lt;/li&gt;
&lt;li&gt;Use the same benchmark profile.&lt;/li&gt;
&lt;li&gt;Repeat the runs.&lt;/li&gt;
&lt;li&gt;Compare both averages and frame-time consistency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try to change only the variable you want to evaluate.&lt;/p&gt;

&lt;p&gt;For laptop testing, keep the device plugged in and use a consistent power profile.&lt;/p&gt;

&lt;p&gt;For sustained tests, pay attention to whether performance remains steady or gradually declines.&lt;/p&gt;

&lt;p&gt;And if you suspect thermal throttling, use separate monitoring software to check temperatures and clock speeds.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Common Benchmarking Traps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Background tabs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Browsers can throttle or pause background animation callbacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Display refresh limits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A frame-timing test may reflect display scheduling rather than maximum GPU throughput.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different rendering APIs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WebGL, WebGPU, and Canvas 2D workloads should not be treated as interchangeable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short measurement windows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A few seconds of data may not capture meaningful sustained performance behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different browsers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Browser implementations and graphics backends can affect results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No consistent workload&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Comparing FPS values from two unrelated animations doesn't establish which GPU is faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;When someone says their browser runs at 60 FPS, the first question should be:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What exactly was being measured?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A lightweight JavaScript animation can help measure callback timing.&lt;/p&gt;

&lt;p&gt;A WebGL stress benchmark can investigate rendering performance under a defined load.&lt;/p&gt;

&lt;p&gt;A WebGPU compatibility test can verify whether modern graphics and compute operations actually work.&lt;/p&gt;

&lt;p&gt;These tools answer different questions.&lt;/p&gt;

&lt;p&gt;Understanding those differences makes browser performance testing much more useful, whether you're debugging a graphics application, comparing driver changes, or investigating inconsistent rendering performance.&lt;/p&gt;

&lt;p&gt;If you want to experiment with sustained browser graphics workloads, you can try &lt;a href="https://webgpustress.com/" rel="noopener noreferrer"&gt;WebGPUStress&lt;/a&gt; without installing a separate benchmarking application.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why Your Website Prints Incorrectly: 6 CSS Print Problems and How to Debug Them</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Sun, 25 Oct 2026 09:57:42 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/why-your-website-prints-incorrectly-6-css-print-problems-and-how-to-debug-them-mnk</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/why-your-website-prints-incorrectly-6-css-print-problems-and-how-to-debug-them-mnk</guid>
      <description>&lt;p&gt;You build a beautiful invoice page. It looks perfect in Chrome.&lt;/p&gt;

&lt;p&gt;Then someone presses &lt;code&gt;Ctrl + P&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Suddenly, the table breaks across pages, background colors disappear, and the right edge of the document gets cut off.&lt;/p&gt;

&lt;p&gt;Sound familiar?&lt;/p&gt;

&lt;p&gt;Printing is one of the most overlooked parts of frontend development. Browsers are optimized for screens, but printed documents have fixed dimensions, physical margins, and very different layout constraints.&lt;/p&gt;

&lt;p&gt;Here are six common problems I've encountered when working with printable web pages, along with practical ways to debug them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Your Screen Layout Is Not Your Print Layout
&lt;/h2&gt;

&lt;p&gt;The browser doesn't automatically convert a responsive screen layout into a well-designed printed document.&lt;/p&gt;

&lt;p&gt;A layout that fits a 1440px monitor might be completely unsuitable for A4 paper.&lt;/p&gt;

&lt;p&gt;The first step is to create print-specific styles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.navigation&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nc"&gt;.sidebar&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nc"&gt;.no-print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.document&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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 removes interface elements that make sense on a screen but not on paper.&lt;/p&gt;

&lt;p&gt;It also prevents decorative shadows and fixed-width containers from creating unexpected printed layouts.&lt;/p&gt;

&lt;p&gt;The important thing is to treat the printable document as its own output format.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A4 and US Letter Are Not Interchangeable
&lt;/h2&gt;

&lt;p&gt;One of the easiest mistakes is designing for one paper size and printing on another.&lt;/p&gt;

&lt;p&gt;A4 measures 210 × 297 mm.&lt;/p&gt;

&lt;p&gt;US Letter measures 8.5 × 11 inches, approximately 216 × 279 mm.&lt;/p&gt;

&lt;p&gt;The difference may seem small, but it becomes significant when you're printing invoices, forms, or documents with precise page boundaries.&lt;/p&gt;

&lt;p&gt;You can control page margins with the CSS &lt;code&gt;@page&lt;/code&gt; rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@page&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12mm&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;You can also request a specific paper size when that is appropriate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@page&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;A4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12mm&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;However, the browser and printer settings can still affect the final output.&lt;/p&gt;

&lt;p&gt;Don't assume that specifying &lt;code&gt;size: A4&lt;/code&gt; guarantees the user's physical printer contains A4 paper.&lt;/p&gt;

&lt;p&gt;For applications serving international audiences, letting users select the intended paper size is usually a better approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Browser Print Scaling Can Break Your Layout
&lt;/h2&gt;

&lt;p&gt;Suppose your CSS is correct, but the printed document still looks smaller than expected.&lt;/p&gt;

&lt;p&gt;The problem might not be your code.&lt;/p&gt;

&lt;p&gt;Browser print dialogs often provide scaling options such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default&lt;/li&gt;
&lt;li&gt;Fit to page&lt;/li&gt;
&lt;li&gt;Actual size&lt;/li&gt;
&lt;li&gt;Custom percentage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These settings can change the dimensions of the resulting document.&lt;/p&gt;

&lt;p&gt;A useful debugging technique is to compare a known reference sheet against the same printer settings.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://printpagecheck.com/" rel="noopener noreferrer"&gt;PrintPageCheck&lt;/a&gt; provides free printable test pages for checking paper margins, scaling, text, and fine lines.&lt;/p&gt;

&lt;p&gt;It supports A4 and US Letter with both browser printing and downloadable PDFs.&lt;/p&gt;

&lt;p&gt;I find this kind of reference useful because it separates two possible problems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem A:&lt;/strong&gt; The printer or print dialog is applying unexpected scaling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem B:&lt;/strong&gt; The application's CSS layout is incorrect.&lt;/p&gt;

&lt;p&gt;If even a reference sheet prints at the wrong size, changing your application's CSS probably isn't the first thing to investigate.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Background Colors Disappear
&lt;/h2&gt;

&lt;p&gt;This issue is particularly common with dashboards, charts, and invoices that use colored table headers.&lt;/p&gt;

&lt;p&gt;Your website displays a colored section correctly, but the printed document has a white background.&lt;/p&gt;

&lt;p&gt;Browsers may omit background graphics depending on print settings.&lt;/p&gt;

&lt;p&gt;You can request more faithful color reproduction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.invoice-header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#e8eef5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;print-color-adjust&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-print-color-adjust&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;exact&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;But here's the catch:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;print-color-adjust: exact&lt;/code&gt; is not a guarantee.&lt;/p&gt;

&lt;p&gt;Browser settings, printer drivers, and device limitations may still affect the output.&lt;/p&gt;

&lt;p&gt;For important documents, avoid relying exclusively on background colors to communicate essential information.&lt;/p&gt;

&lt;p&gt;Use borders, labels, text, and sufficient contrast so the document remains understandable in black and white.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Tables Break Across Pages
&lt;/h2&gt;

&lt;p&gt;A long HTML table may look fine on a screen but become difficult to read when printed.&lt;/p&gt;

&lt;p&gt;For example, a row might be split between two pages.&lt;/p&gt;

&lt;p&gt;You can request better pagination behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;thead&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;table-header-group&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;tr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;break-inside&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;avoid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;page-break-inside&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;avoid&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 encourages browsers to keep rows together and repeat table headers where supported.&lt;/p&gt;

&lt;p&gt;However, page-break behavior varies by browser and content structure.&lt;/p&gt;

&lt;p&gt;If a single row is taller than the available page space, the browser may still need to split or overflow content.&lt;/p&gt;

&lt;p&gt;Always test realistic datasets rather than only a short example table.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Printed Text Looks Blurry or Thin
&lt;/h2&gt;

&lt;p&gt;Not every printing problem comes from CSS.&lt;/p&gt;

&lt;p&gt;Sometimes the page structure is correct, but the physical output contains broken letters, inconsistent lines, or faint text.&lt;/p&gt;

&lt;p&gt;Possible causes include printer quality settings, paper, consumables, or hardware-related issues.&lt;/p&gt;

&lt;p&gt;A useful way to investigate is to print a page containing several font sizes and line thicknesses.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small characters that lose detail&lt;/li&gt;
&lt;li&gt;Horizontal lines with unexpected gaps&lt;/li&gt;
&lt;li&gt;Vertical strokes that appear faint&lt;/li&gt;
&lt;li&gt;Irregular text darkness&lt;/li&gt;
&lt;li&gt;Differences between regular and bold text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If these problems also appear on a dedicated text and fine-line test sheet, the issue may be outside your web application.&lt;/p&gt;

&lt;p&gt;Use the printer manufacturer's diagnostic procedures to investigate further.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Print Debugging Workflow
&lt;/h2&gt;

&lt;p&gt;Instead of randomly changing CSS properties, I recommend this process:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Verify the HTML layout&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make sure the content is structured correctly before applying print-specific styling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Test print media rules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use your browser's developer tools to inspect styles under print media where supported.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Check the paper size&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Confirm that the CSS, print dialog, and physical paper are consistent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Check scaling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Compare Actual Size against automatic fitting when investigating dimension problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Print a reference page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use a dedicated printer test page to distinguish a browser layout issue from a physical output issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Test multiple browsers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Chrome, Firefox, and Safari can differ in their print rendering behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7: Test the actual printer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A PDF preview is useful, but it cannot guarantee what a physical printer will produce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Printing from the web is more complicated than displaying content on a screen.&lt;/p&gt;

&lt;p&gt;There are several layers involved:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;HTML structure&lt;/li&gt;
&lt;li&gt;CSS print styles&lt;/li&gt;
&lt;li&gt;Browser print rendering&lt;/li&gt;
&lt;li&gt;Print dialog configuration&lt;/li&gt;
&lt;li&gt;Printer driver behavior&lt;/li&gt;
&lt;li&gt;Physical printer output&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Debugging becomes much easier when you investigate each layer separately.&lt;/p&gt;

&lt;p&gt;If you're building printable web applications, use controlled test documents and consistent printer settings rather than guessing.&lt;/p&gt;

&lt;p&gt;A reference tool such as &lt;a href="https://printpagecheck.com/" rel="noopener noreferrer"&gt;PrintPageCheck&lt;/a&gt; can help you check the physical output, while your browser's developer tools help you investigate the CSS.&lt;/p&gt;

&lt;p&gt;Good print design isn't just about making the preview look right.&lt;/p&gt;

&lt;p&gt;It's about making the final document reliable.&lt;/p&gt;

</description>
      <category>css</category>
      <category>debugging</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>PondMath</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Wed, 30 Sep 2026 08:21:56 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/pondmath-5ffm</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/pondmath-5ffm</guid>
      <description>&lt;p&gt;I recently built &lt;strong&gt;PondMath&lt;/strong&gt;, a free browser game that turns mental math practice into a small frog adventure.&lt;/p&gt;

&lt;p&gt;The basic idea is simple:&lt;/p&gt;

&lt;p&gt;Solve a math problem correctly, and the frog moves forward across the pond.&lt;/p&gt;

&lt;p&gt;Instead of presenting arithmetic as another worksheet or calculator-style interface, I wanted the practice itself to feel more like a lightweight web game.&lt;/p&gt;

&lt;p&gt;PondMath currently includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Addition&lt;/li&gt;
&lt;li&gt;Subtraction&lt;/li&gt;
&lt;li&gt;Multiplication&lt;/li&gt;
&lt;li&gt;Division&lt;/li&gt;
&lt;li&gt;Mixed arithmetic&lt;/li&gt;
&lt;li&gt;Endless Challenge&lt;/li&gt;
&lt;li&gt;A new Daily Challenge&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s no signup and nothing to install — you can just open it in the browser and start playing.&lt;/p&gt;

&lt;p&gt;A surprisingly interesting design problem was figuring out how much “game” to add.&lt;/p&gt;

&lt;p&gt;Too little, and it feels like a normal math worksheet with a frog pasted on top.&lt;/p&gt;

&lt;p&gt;Too much, and the game starts distracting from the actual mental math practice.&lt;/p&gt;

&lt;p&gt;I ended up keeping the core loop very simple: &lt;strong&gt;solve → jump → progress&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’m continuing to experiment with level design, difficulty progression, animations, and ways to make repeated practice feel less repetitive.&lt;/p&gt;

&lt;p&gt;If you’d like to try it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pondmath.com/" rel="noopener noreferrer"&gt;https://pondmath.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback on the game loop or difficulty progression would be really useful.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>DeskRoster</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Wed, 30 Sep 2026 08:21:44 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/deskroster-29io</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/deskroster-29io</guid>
      <description>&lt;p&gt;I’ve been working on &lt;strong&gt;DeskRoster&lt;/strong&gt;, a free browser-based classroom seating chart maker designed for teachers.&lt;/p&gt;

&lt;p&gt;The idea came from a pretty simple problem: creating a classroom seating plan often means moving names around manually, rebuilding desk layouts, or working with tools that are much more complicated than the task itself.&lt;/p&gt;

&lt;p&gt;So I wanted to make something lightweight.&lt;/p&gt;

&lt;p&gt;With DeskRoster, teachers can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add or paste a student list&lt;/li&gt;
&lt;li&gt;Arrange desks to match the classroom&lt;/li&gt;
&lt;li&gt;Generate seating assignments&lt;/li&gt;
&lt;li&gt;Add seating preferences and constraints&lt;/li&gt;
&lt;li&gt;Drag students around to fine-tune the result&lt;/li&gt;
&lt;li&gt;Print or save the finished seating chart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tool runs directly in the browser, and there’s no account required.&lt;/p&gt;

&lt;p&gt;One of the more interesting parts to build was balancing &lt;strong&gt;automatic seat generation&lt;/strong&gt; with &lt;strong&gt;manual control&lt;/strong&gt;. A fully random seating chart is easy to generate, but real classrooms have constraints: some students need to sit apart, some should stay in the same group, and teachers often want to lock certain seats before generating the rest.&lt;/p&gt;

&lt;p&gt;I’m still improving the workflow and would especially love feedback from anyone who has built tools involving drag-and-drop layouts or constraint-based assignment.&lt;/p&gt;

&lt;p&gt;You can try it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deskroster.com/" rel="noopener noreferrer"&gt;https://deskroster.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Built a Free Collection of Focus Games That Runs Entirely in the Browser</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Wed, 16 Sep 2026 10:03:11 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-free-collection-of-focus-games-that-runs-entirely-in-the-browser-57bd</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-free-collection-of-focus-games-that-runs-entirely-in-the-browser-57bd</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Free Collection of Focus Games That Runs Entirely in the Browser
&lt;/h1&gt;

&lt;p&gt;I recently built &lt;a href="https://dailyfocusgames.com/" rel="noopener noreferrer"&gt;DailyFocus Games&lt;/a&gt;, a free collection of short browser-based games for practicing attention, memory, reaction speed, and cognitive control.&lt;/p&gt;

&lt;p&gt;The idea started from a very simple question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can focus practice feel more like playing a quick game than starting a complicated training program?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I wanted something you could open in a browser, play for a few minutes, and leave.&lt;/p&gt;

&lt;p&gt;No account.&lt;/p&gt;

&lt;p&gt;No installation.&lt;/p&gt;

&lt;p&gt;No onboarding flow.&lt;/p&gt;

&lt;p&gt;Just choose a game and start.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is DailyFocus Games?
&lt;/h2&gt;

&lt;p&gt;DailyFocus Games currently includes short interactive exercises such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stroop Test&lt;/li&gt;
&lt;li&gt;Schulte Table&lt;/li&gt;
&lt;li&gt;Visual Search&lt;/li&gt;
&lt;li&gt;Reaction Time&lt;/li&gt;
&lt;li&gt;Go / No-Go&lt;/li&gt;
&lt;li&gt;N-Back&lt;/li&gt;
&lt;li&gt;Visual Memory&lt;/li&gt;
&lt;li&gt;Sequence Memory&lt;/li&gt;
&lt;li&gt;Number Memory&lt;/li&gt;
&lt;li&gt;Task Switching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users can practice any game individually or start a Daily Challenge made up of several different games.&lt;/p&gt;

&lt;p&gt;The project is available here:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://dailyfocusgames.com/" rel="noopener noreferrer"&gt;DailyFocus Games&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why browser-based?
&lt;/h2&gt;

&lt;p&gt;A lot of cognitive and focus apps immediately ask users to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download an app&lt;/li&gt;
&lt;li&gt;Create an account&lt;/li&gt;
&lt;li&gt;Start a subscription&lt;/li&gt;
&lt;li&gt;Complete onboarding&lt;/li&gt;
&lt;li&gt;Track a long-term program&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That can make sense for some products, but I wanted DailyFocus to feel more lightweight.&lt;/p&gt;

&lt;p&gt;The core workflow is simply:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open → Choose a game → Play&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This also means the games work across desktop and mobile devices without installing anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing very short games
&lt;/h2&gt;

&lt;p&gt;One interesting part of the project has been deciding how long each game should last.&lt;/p&gt;

&lt;p&gt;A focus game doesn't necessarily become better just because it lasts longer.&lt;/p&gt;

&lt;p&gt;In fact, some exercises work better as short challenges.&lt;/p&gt;

&lt;p&gt;For example, a reaction-time game can give useful feedback in seconds.&lt;/p&gt;

&lt;p&gt;A Stroop task can become repetitive if a session is too long.&lt;/p&gt;

&lt;p&gt;A visual-search game needs enough rounds to feel challenging without turning into a chore.&lt;/p&gt;

&lt;p&gt;So instead of forcing every game into the same session length, each game has its own natural rhythm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different games practice different things
&lt;/h2&gt;

&lt;p&gt;I also didn't want the site to become a collection of games that all feel identical.&lt;/p&gt;

&lt;p&gt;Different tasks emphasize different skills.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Stroop
&lt;/h3&gt;

&lt;p&gt;You need to respond to the color while ignoring the written word.&lt;/p&gt;

&lt;p&gt;This creates interference between two competing signals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schulte Table
&lt;/h3&gt;

&lt;p&gt;You visually search for numbers in sequence across a grid.&lt;/p&gt;

&lt;p&gt;The challenge is scanning efficiently without losing your place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go / No-Go
&lt;/h3&gt;

&lt;p&gt;You respond to some signals while withholding your response to others.&lt;/p&gt;

&lt;h3&gt;
  
  
  N-Back
&lt;/h3&gt;

&lt;p&gt;You compare the current stimulus with something shown several steps earlier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Search
&lt;/h3&gt;

&lt;p&gt;You find a target among distracting items.&lt;/p&gt;

&lt;p&gt;The mechanics are simple, but each game creates a different kind of mental challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Daily Challenge instead of a fixed routine
&lt;/h2&gt;

&lt;p&gt;Another feature I wanted was a Daily Challenge.&lt;/p&gt;

&lt;p&gt;Rather than asking users to repeat exactly the same sequence every day, DailyFocus can combine several short games into one session.&lt;/p&gt;

&lt;p&gt;This makes the experience feel less repetitive while still keeping it simple.&lt;/p&gt;

&lt;p&gt;You can also ignore the Daily Challenge completely and practice any individual game whenever you want.&lt;/p&gt;

&lt;p&gt;I think that balance is important.&lt;/p&gt;

&lt;p&gt;The site suggests a starting point, but it doesn't force users into a rigid program.&lt;/p&gt;

&lt;h2&gt;
  
  
  No account required
&lt;/h2&gt;

&lt;p&gt;DailyFocus currently doesn't require an account.&lt;/p&gt;

&lt;p&gt;This is intentional.&lt;/p&gt;

&lt;p&gt;For a lightweight browser game, I think requiring registration before someone can play adds unnecessary friction.&lt;/p&gt;

&lt;p&gt;Users don't need to provide an email address just to try a Stroop test or reaction-time game.&lt;/p&gt;

&lt;p&gt;If the product eventually needs cross-device history or deeper progress tracking, accounts might make sense.&lt;/p&gt;

&lt;p&gt;For now, the priority is making the games immediately playable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the claims realistic
&lt;/h2&gt;

&lt;p&gt;Another important decision was how to describe the project.&lt;/p&gt;

&lt;p&gt;DailyFocus is not a medical treatment or diagnostic tool.&lt;/p&gt;

&lt;p&gt;I don't want to claim that playing a browser game will treat ADHD, dramatically increase intelligence, or produce guaranteed cognitive improvements.&lt;/p&gt;

&lt;p&gt;The site is better described as a collection of short focus and cognitive exercises.&lt;/p&gt;

&lt;p&gt;Users can play, challenge themselves, and practice different types of attention-related tasks.&lt;/p&gt;

&lt;p&gt;That's enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building small games as web products
&lt;/h2&gt;

&lt;p&gt;This project has also reminded me why I like browser-based tools.&lt;/p&gt;

&lt;p&gt;A user can discover a page from search, open it, understand the interaction, and start using it immediately.&lt;/p&gt;

&lt;p&gt;There is something nice about software that doesn't require commitment.&lt;/p&gt;

&lt;p&gt;No installation.&lt;/p&gt;

&lt;p&gt;No account.&lt;/p&gt;

&lt;p&gt;No setup.&lt;/p&gt;

&lt;p&gt;A game can simply exist at a URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I'm continuing to add and improve games while trying to keep the overall experience simple.&lt;/p&gt;

&lt;p&gt;The main things I'm currently thinking about are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Making individual games more enjoyable&lt;/li&gt;
&lt;li&gt;Improving mobile interactions&lt;/li&gt;
&lt;li&gt;Better difficulty progression&lt;/li&gt;
&lt;li&gt;More variety in Daily Challenges&lt;/li&gt;
&lt;li&gt;Adding new game mechanics without making the site feel cluttered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to try the project:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://dailyfocusgames.com/" rel="noopener noreferrer"&gt;DailyFocus Games — Free Focus Games&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd especially be interested in feedback on which game feels the most engaging and which one you'd improve first.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Built a Free Browser-Based Eye Test Toolkit</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Mon, 07 Sep 2026 08:37:30 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-free-browser-based-eye-test-toolkit-1p07</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-free-browser-based-eye-test-toolkit-1p07</guid>
      <description>&lt;p&gt;I recently built &lt;a href="https://eyetestonline.org/" rel="noopener noreferrer"&gt;EyeTest Online&lt;/a&gt;, a free browser-based toolkit for basic vision screening.&lt;/p&gt;

&lt;p&gt;The idea was simple: many common eye checks can be presented as lightweight interactive web tools without requiring an app, account, or installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's included
&lt;/h2&gt;

&lt;p&gt;EyeTest Online currently includes several types of vision screening tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual acuity tests&lt;/li&gt;
&lt;li&gt;Color blindness tests&lt;/li&gt;
&lt;li&gt;Astigmatism tests&lt;/li&gt;
&lt;li&gt;Contrast sensitivity tests&lt;/li&gt;
&lt;li&gt;Amsler grid tests&lt;/li&gt;
&lt;li&gt;Peripheral vision checks&lt;/li&gt;
&lt;li&gt;Near vision tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything runs directly in the browser and works on both desktop and mobile devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why build it as a web app?
&lt;/h2&gt;

&lt;p&gt;I wanted the experience to be as simple as possible:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the website&lt;/li&gt;
&lt;li&gt;Choose a test&lt;/li&gt;
&lt;li&gt;Follow the calibration instructions&lt;/li&gt;
&lt;li&gt;Start immediately&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No account creation and no installation.&lt;/p&gt;

&lt;p&gt;For tools like this, reducing friction matters a lot. Someone who just wants to do a quick vision check shouldn't need to download an app first.&lt;/p&gt;

&lt;h2&gt;
  
  
  An important limitation
&lt;/h2&gt;

&lt;p&gt;These tools are designed for screening and general awareness only.&lt;/p&gt;

&lt;p&gt;They are not medical diagnoses and should not replace an examination by an optometrist or ophthalmologist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;You can try the tests here:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://eyetestonline.org/" rel="noopener noreferrer"&gt;EyeTest Online&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm continuing to improve the calibration, mobile experience, and accessibility of the tests.&lt;/p&gt;

&lt;p&gt;Feedback is welcome, especially from people interested in accessibility, health tools, or browser-based utilities.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Built a Tiny Decision Tool for People Who Overthink Small Choices</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Tue, 04 Aug 2026 10:41:45 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-tiny-decision-tool-for-people-who-overthink-small-choices-3p9b</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-tiny-decision-tool-for-people-who-overthink-small-choices-3p9b</guid>
      <description>&lt;p&gt;Sometimes the hardest decisions are not the important ones.&lt;/p&gt;

&lt;p&gt;They are things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should I order takeout?&lt;/li&gt;
&lt;li&gt;Should I go for a walk?&lt;/li&gt;
&lt;li&gt;Should I text them?&lt;/li&gt;
&lt;li&gt;Should I start working now?&lt;/li&gt;
&lt;li&gt;Should I buy another coffee?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these decisions deserves a spreadsheet, a productivity framework, or a 30-minute discussion with an AI assistant.&lt;/p&gt;

&lt;p&gt;But somehow, we still get stuck.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://tinyfatetools.com/" rel="noopener noreferrer"&gt;Tiny Fate Toolbox&lt;/a&gt;, a small collection of playful tools for everyday decisions.&lt;/p&gt;

&lt;p&gt;The first tool is a simple &lt;strong&gt;Yes or No Wheel&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You think of a question, spin the wheel, and it lands on YES or NO.&lt;/p&gt;

&lt;p&gt;That is basically it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal was not to make decisions for people
&lt;/h2&gt;

&lt;p&gt;A random wheel obviously does not know which choice is best.&lt;/p&gt;

&lt;p&gt;It cannot predict the future, understand your relationships, or decide whether you should change jobs.&lt;/p&gt;

&lt;p&gt;What it can do is interrupt an overthinking loop.&lt;/p&gt;

&lt;p&gt;There is also a small psychological trick hidden inside the experience.&lt;/p&gt;

&lt;p&gt;Imagine asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Should I go out tonight?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The wheel lands on YES.&lt;/p&gt;

&lt;p&gt;Perhaps you immediately feel tired and wish it had landed on NO.&lt;/p&gt;

&lt;p&gt;That reaction may be more useful than the result itself. The wheel did not discover the answer. It helped you notice the answer you were already hoping for.&lt;/p&gt;

&lt;p&gt;That became the main idea behind the product:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The random answer starts the reaction. Your reaction helps reveal your preference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Keeping the interaction deliberately simple
&lt;/h2&gt;

&lt;p&gt;My first design rule was to remove unnecessary steps.&lt;/p&gt;

&lt;p&gt;You can type a question, but you do not have to. You can keep it completely private, think about it for a moment, and press &lt;strong&gt;Spin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The wheel has two YES sections and two NO sections, giving both answers an equal chance.&lt;/p&gt;

&lt;p&gt;I also wanted the animation to feel playful without making the user wait forever. Many wheel tools turn a tiny interaction into a miniature casino experience, with long animations, loud effects, pop-ups, and confetti everywhere.&lt;/p&gt;

&lt;p&gt;For this project, the interaction needed to feel lighter:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask one clear question.&lt;/li&gt;
&lt;li&gt;Spin once.&lt;/li&gt;
&lt;li&gt;See the result.&lt;/li&gt;
&lt;li&gt;Notice your first reaction.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No account is required, and recent results can remain locally on the current device rather than being attached to a user profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Randomness is more confusing than it looks
&lt;/h2&gt;

&lt;p&gt;Building a random wheel also reminded me that people have strong expectations about what “random” should look like.&lt;/p&gt;

&lt;p&gt;For example, a user might spin the wheel five times and receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YES
YES
YES
NO
YES
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is easy to look at that sequence and assume something is wrong.&lt;/p&gt;

&lt;p&gt;But fair randomness does not promise that results will alternate neatly. A 50/50 process can still produce several identical results in a row.&lt;/p&gt;

&lt;p&gt;The browser generates a fresh random value for each spin. That value determines the selected result, and the animation then lands on the corresponding section.&lt;/p&gt;

&lt;p&gt;Previous spins do not make the next YES or NO more likely.&lt;/p&gt;

&lt;p&gt;I added guides explaining this process because transparency felt more useful than simply writing “100% random” in large marketing text.&lt;/p&gt;

&lt;p&gt;A simple tool can still explain how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expanding beyond YES or NO
&lt;/h2&gt;

&lt;p&gt;A binary answer works well for some decisions, but not every decision has only two options.&lt;/p&gt;

&lt;p&gt;So Tiny Fate Toolbox is growing into a small set of focused tools:&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Wheel
&lt;/h3&gt;

&lt;p&gt;Create a wheel with several choices, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pizza&lt;/li&gt;
&lt;li&gt;Tacos&lt;/li&gt;
&lt;li&gt;Pasta&lt;/li&gt;
&lt;li&gt;Sushi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is useful when the options matter more than YES or NO.&lt;/p&gt;

&lt;h3&gt;
  
  
  Random Name Picker
&lt;/h3&gt;

&lt;p&gt;Choose someone from a class, team, giveaway, meeting, or group of friends.&lt;/p&gt;

&lt;p&gt;The goal is to make the selection visible and easy to understand rather than returning a mysterious name from a black box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Weighted Wheel
&lt;/h3&gt;

&lt;p&gt;Sometimes choices should not have equal probabilities.&lt;/p&gt;

&lt;p&gt;Perhaps tonight’s options are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go for a walk: 60%&lt;/li&gt;
&lt;li&gt;Watch a movie: 30%&lt;/li&gt;
&lt;li&gt;Take a nap: 10%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A weighted wheel lets the user represent that preference while still leaving the final result to chance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing for harmless decisions
&lt;/h2&gt;

&lt;p&gt;One important part of the project was deciding what the tool should &lt;strong&gt;not&lt;/strong&gt; encourage.&lt;/p&gt;

&lt;p&gt;A random wheel is fine for choosing dinner, selecting a game, breaking a friendly tie, or escaping a low-stakes overthinking loop.&lt;/p&gt;

&lt;p&gt;It should not be used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Medical treatment&lt;/li&gt;
&lt;li&gt;Financial investments&lt;/li&gt;
&lt;li&gt;Legal decisions&lt;/li&gt;
&lt;li&gt;Personal safety&lt;/li&gt;
&lt;li&gt;Emergencies&lt;/li&gt;
&lt;li&gt;Serious choices affecting another person&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This might seem obvious, but product copy shapes how a tool is used.&lt;/p&gt;

&lt;p&gt;I did not want to present randomness as wisdom or package a spinner as an artificial fortune teller. The product is intentionally framed as entertainment and a playful decision prompt.&lt;/p&gt;

&lt;p&gt;For important decisions, the boring answer is still the correct one: gather information, think carefully, and speak to someone qualified when necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small tools can still deserve thoughtful design
&lt;/h2&gt;

&lt;p&gt;Tiny web tools are easy to underestimate.&lt;/p&gt;

&lt;p&gt;The core feature might take only a few seconds to understand, but the surrounding details still matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it work well on mobile?&lt;/li&gt;
&lt;li&gt;Is the main interaction immediately visible?&lt;/li&gt;
&lt;li&gt;Does the animation match the result?&lt;/li&gt;
&lt;li&gt;Can users understand the probability?&lt;/li&gt;
&lt;li&gt;Is the interface usable without creating an account?&lt;/li&gt;
&lt;li&gt;Does the page explain when the tool is useful?&lt;/li&gt;
&lt;li&gt;Does it avoid pretending to solve problems it cannot solve?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A product does not need hundreds of features to be useful.&lt;/p&gt;

&lt;p&gt;Sometimes it only needs to do one small thing clearly, quickly, and pleasantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;You can try the project here:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://tinyfatetools.com/" rel="noopener noreferrer"&gt;Tiny Fate Toolbox — Yes or No Wheel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ask it something harmless, spin once, and pay attention to your reaction.&lt;/p&gt;

&lt;p&gt;And yes, repeatedly spinning until you get the answer you wanted is also an answer.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Suggested DEV Community tags:&lt;/strong&gt; &lt;code&gt;webdev&lt;/code&gt;, &lt;code&gt;javascript&lt;/code&gt;, &lt;code&gt;indiehackers&lt;/code&gt;, &lt;code&gt;productivity&lt;/code&gt;&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>showdev</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Built a Free Drawing Grid Maker for Artists</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Tue, 23 Jun 2026 09:52:52 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-free-drawing-grid-maker-for-artists-3bld</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-free-drawing-grid-maker-for-artists-3bld</guid>
      <description>&lt;p&gt;Drawing from a reference photo looks simple until you actually try it.&lt;/p&gt;

&lt;p&gt;A face can be slightly too wide.&lt;br&gt;
The eyes can sit too high.&lt;br&gt;
The angle of an object can feel wrong even when you cannot explain why.&lt;/p&gt;

&lt;p&gt;For beginners, these small proportion errors can make an entire drawing feel inaccurate.&lt;/p&gt;

&lt;p&gt;One of the oldest solutions is the &lt;strong&gt;grid drawing method&lt;/strong&gt;: divide the reference image into smaller sections, then reproduce each section one at a time.&lt;/p&gt;

&lt;p&gt;The method is simple, but preparing the grid is often more annoying than the drawing itself.&lt;/p&gt;

&lt;p&gt;That is why I built &lt;strong&gt;DrawGrid&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://drawgrid.org/" rel="noopener noreferrer"&gt;Try DrawGrid&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is DrawGrid?
&lt;/h2&gt;

&lt;p&gt;DrawGrid is a free browser-based grid maker for artists.&lt;/p&gt;

&lt;p&gt;You can upload a reference image, place a customizable grid over it, and export the result for drawing practice.&lt;/p&gt;

&lt;p&gt;There is no account required, and the tool works directly in the browser.&lt;/p&gt;

&lt;p&gt;The basic workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload a reference photo&lt;/li&gt;
&lt;li&gt;Choose a grid style&lt;/li&gt;
&lt;li&gt;Adjust the rows, columns, color, opacity, and line thickness&lt;/li&gt;
&lt;li&gt;Add labels or subdivisions&lt;/li&gt;
&lt;li&gt;Export the gridded reference image&lt;/li&gt;
&lt;li&gt;Create a matching blank practice sheet&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is to make the grid drawing method fast enough that artists can start practicing immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  More than a basic grid overlay
&lt;/h2&gt;

&lt;p&gt;While building DrawGrid, I realized that artists do not always need the same type of guide.&lt;/p&gt;

&lt;p&gt;A portrait artist may need facial proportion lines.&lt;/p&gt;

&lt;p&gt;A landscape artist may need composition guides.&lt;/p&gt;

&lt;p&gt;A beginner studying light may need a simplified value reference.&lt;/p&gt;

&lt;p&gt;So DrawGrid includes a growing library of drawing guides, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Square drawing grids&lt;/li&gt;
&lt;li&gt;Numbered grids&lt;/li&gt;
&lt;li&gt;Subdivided grids&lt;/li&gt;
&lt;li&gt;Portrait proportion guides&lt;/li&gt;
&lt;li&gt;Composition guides&lt;/li&gt;
&lt;li&gt;Perspective guides&lt;/li&gt;
&lt;li&gt;Value and shadow studies&lt;/li&gt;
&lt;li&gt;Outline and contour references&lt;/li&gt;
&lt;li&gt;Color study guides&lt;/li&gt;
&lt;li&gt;Printable practice sheets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of being only an image grid generator, I want DrawGrid to become a practical reference preparation tool for different drawing exercises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizable grid settings
&lt;/h2&gt;

&lt;p&gt;Different drawings require different grids.&lt;/p&gt;

&lt;p&gt;A detailed portrait may need many small cells, while a simple sketch may only need a few large sections.&lt;/p&gt;

&lt;p&gt;DrawGrid lets you adjust settings such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Number of rows&lt;/li&gt;
&lt;li&gt;Number of columns&lt;/li&gt;
&lt;li&gt;Grid line thickness&lt;/li&gt;
&lt;li&gt;Grid line color&lt;/li&gt;
&lt;li&gt;Grid opacity&lt;/li&gt;
&lt;li&gt;Cell numbering&lt;/li&gt;
&lt;li&gt;Subdivision lines&lt;/li&gt;
&lt;li&gt;Grid rotation&lt;/li&gt;
&lt;li&gt;Labels and guides&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The preview updates directly in the editor, so you can experiment before exporting the final image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Printable practice sheets
&lt;/h2&gt;

&lt;p&gt;One feature I especially wanted was the ability to create a matching blank grid.&lt;/p&gt;

&lt;p&gt;Many grid tools only place lines over the original photo. The artist then has to manually recreate the same grid on paper or in another application.&lt;/p&gt;

&lt;p&gt;DrawGrid can generate both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A gridded reference image&lt;/li&gt;
&lt;li&gt;A corresponding blank practice grid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it easier to print both pages and start drawing without additional setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy-friendly image processing
&lt;/h2&gt;

&lt;p&gt;Reference photos can sometimes be personal.&lt;/p&gt;

&lt;p&gt;Because of that, DrawGrid processes images locally in the browser. The image does not need to be uploaded to a remote server just to add grid lines.&lt;/p&gt;

&lt;p&gt;This also makes the editing experience faster because users can immediately preview changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is it for?
&lt;/h2&gt;

&lt;p&gt;DrawGrid can be useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Beginner artists learning proportions&lt;/li&gt;
&lt;li&gt;Portrait artists working from photographs&lt;/li&gt;
&lt;li&gt;Art students practicing observation&lt;/li&gt;
&lt;li&gt;Teachers preparing drawing exercises&lt;/li&gt;
&lt;li&gt;Mural artists enlarging designs&lt;/li&gt;
&lt;li&gt;Illustrators studying composition&lt;/li&gt;
&lt;li&gt;Craft creators transferring patterns&lt;/li&gt;
&lt;li&gt;Anyone learning the grid drawing method&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even experienced artists sometimes use grids when accuracy or scale is especially important.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;There are already grid overlay tools online, but many of them feel limited.&lt;/p&gt;

&lt;p&gt;Some only provide a basic grid.&lt;/p&gt;

&lt;p&gt;Some have difficult controls.&lt;/p&gt;

&lt;p&gt;Others require sign-up, upload images to a server, or place the useful settings across several different pages.&lt;/p&gt;

&lt;p&gt;I wanted to create something that feels more like a lightweight artist workspace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the website&lt;/li&gt;
&lt;li&gt;Upload an image&lt;/li&gt;
&lt;li&gt;Select a guide&lt;/li&gt;
&lt;li&gt;Adjust the result&lt;/li&gt;
&lt;li&gt;Export it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No complicated workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I am working on next
&lt;/h2&gt;

&lt;p&gt;DrawGrid is still evolving.&lt;/p&gt;

&lt;p&gt;Some ideas I am exploring include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More portrait construction guides&lt;/li&gt;
&lt;li&gt;Better perspective overlays&lt;/li&gt;
&lt;li&gt;Custom paper sizes&lt;/li&gt;
&lt;li&gt;Improved mobile controls&lt;/li&gt;
&lt;li&gt;Additional printable worksheets&lt;/li&gt;
&lt;li&gt;Presets for common drawing exercises&lt;/li&gt;
&lt;li&gt;More composition guide templates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback from artists will help decide which features should be built first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;You can use DrawGrid for free here:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://drawgrid.org/" rel="noopener noreferrer"&gt;https://drawgrid.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would love to hear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What type of grid do you usually use?&lt;/li&gt;
&lt;li&gt;Which drawing guides would be most useful?&lt;/li&gt;
&lt;li&gt;Do you prefer drawing digitally or on printed paper?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for checking it out.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Built a Browser-Based GPU Stress Test That Runs Without Downloads</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Mon, 15 Jun 2026 13:57:46 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-browser-based-gpu-stress-test-that-runs-without-downloads-4km8</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-browser-based-gpu-stress-test-that-runs-without-downloads-4km8</guid>
      <description>&lt;p&gt;Most GPU stress-testing tools require users to download and install a desktop application.&lt;/p&gt;

&lt;p&gt;That makes sense for detailed hardware diagnostics, but sometimes you only need a quick answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is hardware acceleration working?&lt;/li&gt;
&lt;li&gt;Does performance drop after the GPU heats up?&lt;/li&gt;
&lt;li&gt;Is an overclock obviously unstable?&lt;/li&gt;
&lt;li&gt;Are frame-time spikes causing visible stutter?&lt;/li&gt;
&lt;li&gt;Is a laptop slowing down under sustained load?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built &lt;strong&gt;WebGPUStress&lt;/strong&gt;, a browser-based GPU stress test powered by WebGL.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;The tool runs a sustained shader workload directly inside the browser and records several performance signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average FPS&lt;/li&gt;
&lt;li&gt;1% Low FPS&lt;/li&gt;
&lt;li&gt;Frame-time stability&lt;/li&gt;
&lt;li&gt;Dropped-frame ratio&lt;/li&gt;
&lt;li&gt;Performance decay during longer runs&lt;/li&gt;
&lt;li&gt;An overall stability score&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can choose the duration, resolution, quality level, and target frame rate.&lt;/p&gt;

&lt;p&gt;There are also presets for common situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quick Health Check&lt;/strong&gt; — a short test for obvious problems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thermal Soak&lt;/strong&gt; — a longer workload for detecting performance loss after heat builds up&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FPS Drop Check&lt;/strong&gt; — useful when games feel less smooth than the average FPS suggests&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why not show only an FPS score?
&lt;/h2&gt;

&lt;p&gt;A high average FPS does not always mean the experience is stable.&lt;/p&gt;

&lt;p&gt;For example, a GPU might average 60 FPS while regularly dropping into the 30s. It may also perform well during the first minute and slow down once the cooling system becomes saturated.&lt;/p&gt;

&lt;p&gt;That is why the test also tracks 1% lows, frame-time consistency, and dropped frames.&lt;/p&gt;

&lt;p&gt;The goal is not to produce one impressive benchmark number. It is to show whether performance remains consistent over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful scenarios
&lt;/h2&gt;

&lt;p&gt;I designed the tool for quick checks such as:&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing an overclock
&lt;/h3&gt;

&lt;p&gt;A game might run normally for a few minutes while a longer sustained workload reveals artifacts, crashes, or unstable frame pacing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking laptop throttling
&lt;/h3&gt;

&lt;p&gt;Some laptops start fast but lose performance after several minutes. Comparing the beginning and end of a longer run can help reveal that pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnosing gaming stutter
&lt;/h3&gt;

&lt;p&gt;When average FPS looks normal but gameplay still feels uneven, 1% lows and frame-time stability can provide more useful clues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verifying GPU acceleration
&lt;/h3&gt;

&lt;p&gt;It can also provide a quick sanity check for virtual machines, remote desktop environments, and newly configured systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;Because this runs inside a browser, it is not a replacement for tools such as FurMark, MSI Afterburner, GPU-Z, or native hardware monitoring software.&lt;/p&gt;

&lt;p&gt;Browsers cannot directly expose GPU temperature, voltage, power consumption, or fan speed. Results can also be affected by the browser, graphics driver, power mode, background applications, and whether the tab remains active.&lt;/p&gt;

&lt;p&gt;I see it as a fast first-pass diagnostic tool rather than a complete hardware certification suite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;You can run the test here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="http://webgpustress.com/" rel="noopener noreferrer"&gt;online gpu test&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No download, account, plugin, or executable is required.&lt;/p&gt;

&lt;p&gt;I would especially appreciate feedback about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance on different browsers and GPUs&lt;/li&gt;
&lt;li&gt;Whether the result explanations are clear&lt;/li&gt;
&lt;li&gt;Additional benchmark profiles you would find useful&lt;/li&gt;
&lt;li&gt;Metrics that should be added or improved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is still evolving, so real-world testing and developer feedback would be genuinely useful.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Built a Simple Online Tone Generator That Runs Directly in the Browser</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Fri, 12 Jun 2026 14:11:23 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-simple-online-tone-generator-that-runs-directly-in-the-browser-15a1</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-simple-online-tone-generator-that-runs-directly-in-the-browser-15a1</guid>
      <description>&lt;p&gt;Recently I built a small browser-based audio tool called TonePanel:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://tonepanel.org" rel="noopener noreferrer"&gt;https://tonepanel.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is an online tone generator that lets you play steady tones from 20 Hz to 20 kHz directly in the browser. You can switch between common waveforms like sine, square, sawtooth, and triangle, without installing anything.&lt;/p&gt;

&lt;p&gt;The idea was simple: I wanted a clean tool for quick audio checks — something useful for testing speakers, headphones, frequency response, or just understanding how different Hz ranges sound.&lt;/p&gt;

&lt;p&gt;Why I made it&lt;/p&gt;

&lt;p&gt;A lot of tone generator tools work, but many of them feel either too old, too cluttered, or too technical for casual users.&lt;/p&gt;

&lt;p&gt;So I wanted to make something that feels more like a small control panel:&lt;/p&gt;

&lt;p&gt;choose a frequency&lt;br&gt;
press play&lt;br&gt;
adjust the sound&lt;br&gt;
switch waveform&lt;br&gt;
stop when done&lt;/p&gt;

&lt;p&gt;No account, no setup, no download.&lt;/p&gt;

&lt;p&gt;What it can be used for&lt;/p&gt;

&lt;p&gt;TonePanel can be useful for:&lt;/p&gt;

&lt;p&gt;speaker testing&lt;br&gt;
headphone checks&lt;br&gt;
comparing low / mid / high frequencies&lt;br&gt;
basic audio experiments&lt;br&gt;
instrument reference tones&lt;br&gt;
learning what different waveforms sound like&lt;/p&gt;

&lt;p&gt;For example, a sine wave is usually the best starting point if you want to hear one clean frequency. Square, sawtooth, and triangle waves sound more “textured” because they contain additional harmonics.&lt;/p&gt;

&lt;p&gt;Built for the browser&lt;/p&gt;

&lt;p&gt;The tool runs locally in the browser, which makes it lightweight and easy to use. You just open the page and play a tone.&lt;/p&gt;

&lt;p&gt;I’m also planning to expand it with more focused pages, such as:&lt;/p&gt;

&lt;p&gt;Frequency Generator&lt;br&gt;
Hz Generator&lt;br&gt;
speaker test tools&lt;br&gt;
sweep tone tools&lt;br&gt;
simple educational guides about sound frequencies&lt;br&gt;
A small safety note&lt;/p&gt;

&lt;p&gt;Always start with low volume, especially when using headphones. High or very low frequencies can feel uncomfortable quickly.&lt;/p&gt;

&lt;p&gt;Try it&lt;/p&gt;

&lt;p&gt;Here is the tool:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tonepanel.org" rel="noopener noreferrer"&gt;https://tonepanel.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love to hear feedback from anyone who works with audio, music, speakers, headphones, or browser-based tools.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Built a Simple Omegaverse Quiz Website</title>
      <dc:creator>sgamer宇</dc:creator>
      <pubDate>Tue, 12 May 2026 07:57:30 +0000</pubDate>
      <link>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-simple-omegaverse-quiz-website-1od8</link>
      <guid>https://dev.to/sgamer_560ef5490592e4dc9/i-built-a-simple-omegaverse-quiz-website-1od8</guid>
      <description>&lt;p&gt;I recently built a small web project called OmegaverseTypes.org.&lt;/p&gt;

&lt;p&gt;It is a simple Omegaverse Quiz that helps users discover whether they are closer to Alpha, Beta, Omega, or Hybrid based on a short set of personality-style questions.&lt;/p&gt;

&lt;p&gt;The site is live here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omegaversetypes.org/" rel="noopener noreferrer"&gt;https://omegaversetypes.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why I Built It&lt;/p&gt;

&lt;p&gt;I noticed that people search for terms like:&lt;/p&gt;

&lt;p&gt;Omegaverse Quiz&lt;br&gt;
ABO Test&lt;br&gt;
Alpha Beta Omega Quiz&lt;br&gt;
Omegaverse Type Test&lt;/p&gt;

&lt;p&gt;But many existing quiz-style pages feel a bit outdated, cluttered, or unclear.&lt;/p&gt;

&lt;p&gt;So I wanted to build something cleaner and easier to use.&lt;/p&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;p&gt;Let users open the page, start the quiz immediately, answer a few questions, and get a clear result without signing up.&lt;/p&gt;

&lt;p&gt;No login.&lt;br&gt;
No complicated onboarding.&lt;br&gt;
No unnecessary friction.&lt;/p&gt;

&lt;p&gt;Just a lightweight interactive quiz.&lt;/p&gt;

&lt;p&gt;What the Quiz Does&lt;/p&gt;

&lt;p&gt;The quiz asks users a short series of questions related to social energy, pressure, relationships, emotional patterns, and decision-making style.&lt;/p&gt;

&lt;p&gt;Based on the answers, the site gives one of four result types:&lt;/p&gt;

&lt;p&gt;Alpha&lt;/p&gt;

&lt;p&gt;Alpha is usually associated with confidence, presence, action, and protective energy.&lt;/p&gt;

&lt;p&gt;Beta&lt;/p&gt;

&lt;p&gt;Beta represents balance, stability, rationality, and adaptability.&lt;/p&gt;

&lt;p&gt;Omega&lt;/p&gt;

&lt;p&gt;Omega is connected with emotional sensitivity, intuition, relational awareness, and inner softness.&lt;/p&gt;

&lt;p&gt;Hybrid&lt;/p&gt;

&lt;p&gt;Hybrid is for users who do not fit neatly into one single type. It combines traits from multiple Omegaverse archetypes.&lt;/p&gt;

&lt;p&gt;This is not meant to be a scientific personality test.&lt;br&gt;
It is more of an entertainment-focused quiz for people who enjoy Omegaverse, ABO dynamics, character archetypes, and fandom-style personality tests.&lt;/p&gt;

&lt;p&gt;Design Direction&lt;/p&gt;

&lt;p&gt;For the design, I wanted the site to feel clean, bright, and modern.&lt;/p&gt;

&lt;p&gt;A lot of quiz websites use heavy colors, outdated UI, or overly dramatic visuals. I wanted something lighter.&lt;/p&gt;

&lt;p&gt;The direction was closer to:&lt;/p&gt;

&lt;p&gt;clean landing page&lt;br&gt;
simple quiz flow&lt;br&gt;
readable result page&lt;br&gt;
soft visual style&lt;br&gt;
mobile-friendly layout&lt;br&gt;
fast loading&lt;/p&gt;

&lt;p&gt;The homepage is designed around one main action: starting the quiz.&lt;/p&gt;

&lt;p&gt;I did not want users to scroll through a long explanation before understanding what the site does.&lt;/p&gt;

&lt;p&gt;The first screen should answer:&lt;/p&gt;

&lt;p&gt;“What is this?”&lt;br&gt;
“What will I get?”&lt;br&gt;
“How do I start?”&lt;/p&gt;

&lt;p&gt;SEO Considerations&lt;/p&gt;

&lt;p&gt;This project was also interesting from an SEO perspective.&lt;/p&gt;

&lt;p&gt;The main keyword is Omegaverse Quiz, but the site also naturally relates to:&lt;/p&gt;

&lt;p&gt;ABO Test&lt;br&gt;
Alpha Beta Omega Test&lt;br&gt;
Omegaverse Type&lt;br&gt;
Alpha Omega Hybrid Quiz&lt;br&gt;
Omegaverse personality quiz&lt;/p&gt;

&lt;p&gt;For this kind of small tool website, I think the most important SEO elements are:&lt;/p&gt;

&lt;p&gt;A clear H1 with the main search intent&lt;br&gt;
A short explanation of what the quiz does&lt;br&gt;
Immediate interaction above the fold&lt;br&gt;
Result pages that explain each type clearly&lt;br&gt;
FAQ content for users who are new to the topic&lt;br&gt;
Fast page loading and simple HTML structure&lt;/p&gt;

&lt;p&gt;The site is still small, but the goal is to make it useful and easy to understand from the first visit.&lt;/p&gt;

&lt;p&gt;What I Learned&lt;/p&gt;

&lt;p&gt;Building this project reminded me that small websites still need strong product thinking.&lt;/p&gt;

&lt;p&gt;Even a simple quiz has many UX questions:&lt;/p&gt;

&lt;p&gt;How many questions should the quiz have?&lt;br&gt;
Should the result feel playful or serious?&lt;br&gt;
How much explanation is enough?&lt;br&gt;
Should the homepage focus on SEO content or immediate interaction?&lt;br&gt;
How do you make the page feel fun without making it look messy?&lt;/p&gt;

&lt;p&gt;The hardest part was not the quiz logic itself.&lt;/p&gt;

&lt;p&gt;The harder part was making the experience feel clear, lightweight, and intentional.&lt;/p&gt;

&lt;p&gt;Who It Is For&lt;/p&gt;

&lt;p&gt;This quiz is mainly for people who enjoy:&lt;/p&gt;

&lt;p&gt;Omegaverse / ABO settings&lt;br&gt;
fandom personality quizzes&lt;br&gt;
character archetypes&lt;br&gt;
relationship dynamics&lt;br&gt;
roleplay or original character creation&lt;br&gt;
light entertainment quizzes&lt;/p&gt;

&lt;p&gt;It can also be useful as a small inspiration tool for writers or creators who are building fictional characters.&lt;/p&gt;

&lt;p&gt;Try It&lt;/p&gt;

&lt;p&gt;You can try the quiz here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omegaversetypes.org/" rel="noopener noreferrer"&gt;https://omegaversetypes.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It only takes a few minutes.&lt;/p&gt;

&lt;p&gt;You might get Alpha.&lt;br&gt;
You might get Beta.&lt;br&gt;
You might get Omega.&lt;br&gt;
Or maybe you are something more mixed — Hybrid.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>ux</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
