<?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: Ride A Pet Guide</title>
    <description>The latest articles on DEV Community by Ride A Pet Guide (@rideapetguide).</description>
    <link>https://dev.to/rideapetguide</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%2F4197188%2F91e88701-50af-4683-80a1-12b7924274ff.png</url>
      <title>DEV Community: Ride A Pet Guide</title>
      <link>https://dev.to/rideapetguide</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rideapetguide"/>
    <language>en</language>
    <item>
      <title>Unknown Is Not Zero: Modeling Evidence in a Fan-Made Game Wiki</title>
      <dc:creator>Ride A Pet Guide</dc:creator>
      <pubDate>Wed, 21 Oct 2026 02:47:44 +0000</pubDate>
      <link>https://dev.to/rideapetguide/unknown-is-not-zero-modeling-evidence-in-a-fan-made-game-wiki-5bil</link>
      <guid>https://dev.to/rideapetguide/unknown-is-not-zero-modeling-evidence-in-a-fan-made-game-wiki-5bil</guid>
      <description>&lt;p&gt;Most game wikis I've used have the same failure mode: every cell is filled. Drop rate? A precise percentage. Pet speed? A precise number. Codes? A long list, all "working". Half of those numbers came from one video, a Discord screenshot, or a guess that got copied enough times to look like a fact.&lt;/p&gt;

&lt;p&gt;While working on a fan guide for the Roblox game Ride A Pet, we took the opposite approach: &lt;strong&gt;a value is only shown if we can say where it came from and when&lt;/strong&gt;. That sounds like an editorial rule, but it turned out to be mostly a data-modeling problem. Here's what that looks like in practice and what we'd do the same way again.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Give every fact an evidence status, not just a value
&lt;/h3&gt;

&lt;p&gt;The eggs reference doesn't have one "source" column. Each row carries a label for &lt;em&gt;how&lt;/em&gt; we know it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recorded screen&lt;/strong&gt;: the name is visible in gameplay footage we can rewatch (e.g. an Aurora Egg growing at a ranch nest).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reported&lt;/strong&gt;: a dated third-party source says it (e.g. Blackhole and Cherub Eggs being searched for around the Giant Tree and a waterfall cave).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Official artwork&lt;/strong&gt;: the name appears in promotional art (Flame Egg, Dragon Egg). That proves the name exists, not that it's buyable today.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The UI consequence is small but important: a "Reported" row reads differently from a "Recorded" row, and a reader can see why the page is hedging.&lt;/p&gt;

&lt;p&gt;A sketch of the shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Evidence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;recorded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// e.g. "SpaceQT", "2:57"&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reported&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;checkedOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// ISO date&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;official-art&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Fact&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// null when unknown, never 0&lt;/span&gt;
  &lt;span class="nl"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// "$/s", "stock", ...&lt;/span&gt;
  &lt;span class="nl"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Evidence&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;h3&gt;
  
  
  2. &lt;code&gt;null&lt;/code&gt; is not &lt;code&gt;0&lt;/code&gt;, and the UI should say so
&lt;/h3&gt;

&lt;p&gt;The pets page has a line I like a lot: &lt;em&gt;an unmeasured stat remains unknown; it should not be entered as zero.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's a classic data bug wearing a game costume. If a comparison tool defaults an empty field to &lt;code&gt;0&lt;/code&gt;, every pet nobody measured looks terrible, and readers draw conclusions from your defaults. So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing values render as "Unknown", not as &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;-&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A number is always shown with its unit. The game shows a lightning label, a clover label, and a dollar-per-second label next to pets; a big number alone doesn't tell you whether it's movement, luck, or income.&lt;/li&gt;
&lt;li&gt;Comparisons only happen between the &lt;em&gt;same&lt;/em&gt; field on two pets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same idea shows up in the game-pass table. Four passes (Instant Hatch, Infinite Radar, Infinite Backpack, Auto Collect) have a known &lt;em&gt;purpose&lt;/em&gt; from published guides, but the exact rules and prices aren't confirmed. Instead of guessing, the table has a column literally called "function detail still needed for a purchase decision". Writing down what you don't know is more useful than a confident row that's wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Snapshots get a date and a source timestamp
&lt;/h3&gt;

&lt;p&gt;Shop data in a live game is volatile. A recorded Gears shop frame shows Royal Radar marked Legendary at $20K with x3 stock, and Magic Radar out of stock. That's useful for recognizing the row, and useless as a price list a week later.&lt;/p&gt;

&lt;p&gt;So every snapshot keeps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the creator and video timestamp it came from (SpaceQT at 3:07, ItzVexo at 5:45),&lt;/li&gt;
&lt;li&gt;a note that "$" is the game's own price display, not US dollars,&lt;/li&gt;
&lt;li&gt;and a page-level "Checked" date plus a separate "last substantive edit" date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two dates sound redundant until you need them. "Checked" means "we re-read the sources on this day." "Edited" means "the content actually changed." Mixing them hides whether a page is stale or just stable.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The best page on the site is an empty list
&lt;/h3&gt;

&lt;p&gt;Codes pages are where game wikis lose the most trust. The fan guide's answer is a page whose main content is: &lt;em&gt;no verified codes&lt;/em&gt;, with a timestamp (24 September 2026, 03:07 UTC), the official page that was checked, and two dated third-party reports that also found none.&lt;/p&gt;

&lt;p&gt;What makes it work as a data page is that "verified" has a definition. A code record needs four fields before it's published:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the exact string,&lt;/li&gt;
&lt;li&gt;the announced reward,&lt;/li&gt;
&lt;li&gt;a redemption control that actually exists in the current game,&lt;/li&gt;
&lt;li&gt;a successful redemption check.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any one is missing, the record doesn't exist yet. A failed attempt can't tell you whether a code expired, was mistyped or never existed, so on its own it doesn't move a row anywhere. You can see the whole structure on the &lt;a href="https://rideapet.com/codes" rel="noopener noreferrer"&gt;Ride A Pet codes checklist&lt;/a&gt;; it's a nice reference if you're designing any "status" page where the honest answer is often "nothing yet".&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Separate states that look the same
&lt;/h3&gt;

&lt;p&gt;Another modeling lesson from the eggs page: a world listing, a radar target, and an egg in your basket are three different states, even though a player might call all of them "my egg". The page maps each screen to the one question it answers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Screen&lt;/th&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Track&lt;/td&gt;
&lt;td&gt;What is listed in the world?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Radar marker&lt;/td&gt;
&lt;td&gt;Where is this search's target?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Egg Basket&lt;/td&gt;
&lt;td&gt;What am I carrying?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hatch screen&lt;/td&gt;
&lt;td&gt;What stage is this egg at?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Index: Eggs&lt;/td&gt;
&lt;td&gt;What have I collected?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you've ever debugged an order system where "in cart", "paid" and "shipped" got collapsed into one boolean, this will feel familiar.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Keep personal state on the client, and say so
&lt;/h3&gt;

&lt;p&gt;The egg-locations page has a small run-notes checklist: an optional target name (up to 60 characters) and seven checks, from "prepare a rideable pet" to "place it in a nest and confirm hatching". It's one checklist per browser, not synced to a game account, and the page states that the component doesn't send notes to analytics.&lt;/p&gt;

&lt;p&gt;The "report a problem" form is similarly scoped: it sends the page address and a category (outdated, unclear, video problem, missing info), and nothing else. Writing the data boundary next to the control costs one sentence and removes a whole class of "what are you collecting?" questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I'd take to any reference site
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Model evidence explicitly. A value without a source is a draft.&lt;/li&gt;
&lt;li&gt;Default to &lt;code&gt;null&lt;/code&gt;, render "Unknown", keep units attached.&lt;/li&gt;
&lt;li&gt;Store "checked" and "edited" dates separately.&lt;/li&gt;
&lt;li&gt;Define what "verified" means as required fields, and let the empty state be a real, dated page.&lt;/li&gt;
&lt;li&gt;Put the privacy boundary of a widget right next to the widget.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this needs a fancy stack. It's mostly refusing to let a table cell be filled just because the layout has room for it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>gamedev</category>
      <category>ux</category>
      <category>writing</category>
    </item>
  </channel>
</rss>
