DEV Community

visiohex
visiohex

Posted on • Originally published at anime-expeditions-wiki.org

How I Built a Source-Tracked Roblox Wiki with Astro and No Database

I built Anime Expeditions Wiki as an independent guide for the Roblox experience Anime Expeditions.

The site helps players find current codes, compare units, plan early progression, and verify that they are joining the correct Roblox experience. It now contains 47 indexable routes across seven languages.

The technical stack is small:

  • Astro and TypeScript
  • Static deployment on Cloudflare Pages
  • No database
  • No CMS
  • No server functions
  • No public API

The harder part was handling information that changes faster than the pages around it.

The maintenance problem: uncertainty

Game guides become outdated fast. Codes expire, updates change upgrade requirements, and community tier lists often disagree.

A page can show a recent publication date while its tables still describe an older game version. Copying the newest value into a database would not solve that problem. I needed to record where each claim came from and the conditions under which it was useful.

I treated changing gameplay claims as dated evidence records.

interface EvidenceRecord {
  sourceIds: readonly string[];
  evidenceLevel: EvidenceLevel;
  verifiedAt: string;
  status: "confirmed" | "reported" | "disputed" | "unknown";
  applicableVersion: string;
}
Enter fullscreen mode Exit fullscreen mode

Each record answers five questions:

  1. Which sources support this claim?
  2. What kind of source supplied it?
  3. When did someone check it?
  4. Do current sources agree?
  5. Which game version does it describe?

The public page displays this information beside the value. Readers do not have to search a general sources page to learn whether a code or recipe comes from an official record, a community guide, or conflicting reports.

Keeping disagreements visible

The code list shows why the status field matters.

At the July 21 snapshot, the wiki tracked 15 codes. Eight had matching reports that they were active. Seven had conflicting reports.

I kept the disputed codes visible and added notes describing which sources disagreed. Choosing one answer would hide useful information. Combining several reports into a new answer would create a claim that no source published.

Tier lists have the same problem. The wiki compares three public rankings side by side instead of calculating a new score.

If one publisher does not list a unit, the table displays “Not listed.” It does not convert the missing entry into the lowest grade.

The data model allows disagreement to remain a valid state. Editors can update a record later when stronger evidence appears.

One dataset for 47 routes

Gameplay records live in TypeScript data modules. Astro components decide how to present them.

The current dataset includes:

  • 15 tracked codes
  • 33 units
  • 17 traits
  • Evolution recipes
  • Five story maps
  • Equipment and resource records
  • 35 source entries

The static build produces 47 indexable routes. English has 17 pages. Spanish, Brazilian Portuguese, German, French, Japanese, and Korean each have five core pages:

  • Homepage
  • Codes
  • Beginner guide
  • Tier list
  • Official links

All seven languages share the same gameplay records. Only interface text and explanatory copy vary by locale.

When a code changes status, I update one record instead of editing seven tables. This also prevents a translated page from keeping an older reward after the English page changes.

Astro generates canonical URLs, hreflang links, metadata, and the sitemap from the route definitions. A missing locale route fails during verification instead of producing an orphaned page.

Verifying the correct Roblox experience

Roblox uses several identifiers for one experience. Anime Expeditions has a Place ID, Universe ID, and creator Group ID.

A title search cannot prove that a result belongs to the expected creator, especially when several experiences use similar names.

The project fixes these identifiers in its configuration:

  • Place ID: 84515722934860
  • Universe ID: 7613921865
  • Creator: Expeditions Entertainment
  • Group ID: 35929511

A synchronization script checks the Place-to-Universe relationship through Roblox. It finds the matching search record, verifies the creator, and confirms that approved promotional images belong to the expected universe.

The script stops without writing when an identity field does not match.

A changed title may be a legitimate update. A different creator or Universe ID means the automation may have found the wrong experience.

The site also keeps a small whitelist of official Roblox and YouTube destinations. A data update cannot introduce an unreviewed game, group, or media URL.

Automating stable facts

A daily GitHub Actions workflow checks official Roblox metadata.

It compares stable fields with a stored snapshot:

  • Name
  • Description
  • Canonical path
  • Content maturity
  • Age recommendation
  • Creator
  • Place and Universe IDs

The workflow ignores player counts, vote totals, promotion state, and thumbnail URLs. Those values change often and do not justify a content update.

The identity check passes its verified search result to the snapshot step. Reusing that result avoids calling Roblox’s rate-limited search endpoint twice during one workflow run.

When stable official metadata changes, the workflow can update the snapshot and deploy the static site.

It does not rewrite tier lists, code statuses, evolution recipes, or gameplay advice.

Community information still needs review. Two guides may disagree because one tested an older server version, one misunderstood a requirement, or both copied the same incorrect source. A script cannot settle that question from the published values alone.

Automation handles identity and stable platform metadata. A human reviews gameplay claims.

Why the site stays static

Astro is the project’s only application dependency. Cloudflare Pages serves the generated files.

A database would add another moving part without improving the evidence behind the content. The dataset remains small enough to review in Git, and the site rebuilds when a record changes.

Static output also makes verification easier. The build process can inspect the HTML that will reach production.

The validator checks:

  • Page titles and descriptions
  • Canonical URLs
  • Alternate language links
  • Internal links
  • Source references
  • Structured data
  • Local media
  • Security requirements

Browser JavaScript handles a short list of enhancements, including table search, filters, code copying, mobile navigation, and analytics consent.

Readers can still access the main content when those enhancements fail.

The official trailer uses a click-to-load YouTube embed. The browser does not contact YouTube until the visitor starts the video. Google Analytics also stays unloaded until a visitor opts in.

Testing content relationships

The test suite checks content assumptions that TypeScript cannot protect on its own.

It verifies that every source ID is unique and that every citation points to an existing source. It also checks that tier comparisons cover the known unit roster without inventing grades for omitted units.

Other tests protect the update and publishing workflow:

  • The official Roblox identity must remain fixed.
  • The update check must reuse verified records.
  • Roblox requests must back off after rate limits.
  • Failed identity checks must stop without writing.
  • Media must stay local and attributed.
  • YouTube and analytics must remain inactive until requested.

The current suite contains 13 tests. The Astro build generates 48 pages, including the 404 page, and the validator checks all 47 indexable routes.

A valid TypeScript object can still cite a missing source, publish the wrong canonical domain, or send a translated page to an English URL. These checks catch those mistakes before deployment.

Limits of this approach

The static workflow makes editorial changes slower than editing a database through an admin panel. Each change passes through the repository, tests, and deployment.

That cost fits the current project. A review step helps when one incorrect value could cause players to waste limited resources.

Only five core pages have complete translations. Translating all 17 English pages would add substantial review work. Shared gameplay data prevents values from drifting, but translated explanations still need language-specific review.

The evidence model also stays small. It records the source, status, date, and applicable version without calculating a confidence percentage.

A confidence score would suggest more precision than the source material supports. Showing that two current guides disagree gives readers clearer information than assigning the claim a score of 62 percent.

What I learned

Dates and versions belong beside changing claims. A site-wide “last updated” date says little about an individual code or recipe.

Source disagreement deserves its own state. Treating conflict as an error encourages maintainers to choose an answer before they have enough evidence.

Automation works best on facts with stable identifiers and clear failure conditions. Editorial judgment needs a review boundary.

The project remains a static Astro site because its current scale does not need more infrastructure. The useful part of the system is deciding what the build should refuse to publish.

You can explore the finished project at Anime Expeditions Wiki.

Anime Expeditions Wiki is an independent fan project and is not affiliated with Roblox, Expeditions Entertainment, or any anime rights holder.

Top comments (0)