🧬 SteemBiota — A No-Backend Life Simulation Built Entirely on Steem

in Steem Devlast month

1000091223.jpg

Hey Steem devs! 👋

I've just released SteemBiota: Immutable Evolution — a fully on-chain life simulation game — and I wanted to share it here with a proper technical write-up, because a lot of the architectural decisions I made along the way might be interesting (or at least relatable) to anyone building on Steem.

🌐 Live app: https://puncakbukit.github.io/steembiota
📄 White paper: (attached / linked below)

The Core Premise

The question I started with: can a non-trivial game live entirely on a public blockchain with zero backend?

The answer turned out to be yes — with some interesting trade-offs.

Every creature is a Steem post. Every interaction (feed, play, walk, breed, transfer) is a Steem reply. Every rule (anti-spam, kinship checks, ownership resolution) is enforced client-side by reading the same chain data. No smart contracts. No database. No server. Just getContent, getContentReplies, and Keychain.

Stack

LayerChoiceReason
BlockchainSteemSocial post/reply model maps naturally to creature/event model
SigningSteem KeychainNo private key exposure to the app
UIVue 3 + Vue Router 4 (CDN)Zero build toolchain; ships as four plain files
HostingGitHub PagesStatic only — consistent with the no-backend constraint

No npm, no webpack, no CI pipeline. The entire app is index.html, blockchain.js, components.js, and app.js. Anyone can read the source directly in the browser.

On-Chain Data Model

All game state is stored in json_metadata.steembiota on posts and replies. A few examples:

Founder creature (top-level post):

{
  "version": "1.0",
  "type": "founder",
  "genome": { "GEN": 42, "SX": 0, "MOR": 1234, "APP": 5678,
              "ORN": 9012, "CLR": 180, "LIF": 100,
              "FRT_START": 30, "FRT_END": 70, "MUT": 1 },
  "name": "Vyrex Nymwhisper"
}

Feed reply (reply to creature post):

{
  "version": "1.0",
  "type": "feed",
  "creature": { "author": "alice", "permlink": "vyrex-nymwhisper-..." },
  "feeder": "carol",
  "food": "nectar",
  "ts": "2026-01-03T07:00:00Z"
}

Ownership transfer — a two-step handshake via transfer_offertransfer_accept replies. The effective owner is derived at read time by walking the reply tree with parseOwnershipChain(). The original post.author never changes.

Post tags are also generated dynamically from the genome — each creature post is tagged with steembiota, gaming, evolution, the genus name, the creature's first and last name, and its sex, making every creature discoverable through Steem's existing tag infrastructure.

The Interesting Engineering Problems

1. Client-side rule enforcement without smart contracts

Anti-spam (one feed/play/walk per feeder per UTC day), kinship checks (BFS ancestry walk up to 12 generations), and breed permit validation all run in the browser. A determined actor could bypass them by posting directly to the API — but any non-compliant post gets a provenance badge (⚠ Duplicate, ⚠ No Parents, etc.) that's visible to all clients reading the same data. Transparency enforces honesty rather than restriction.

2. Deterministic breeding

breedGenomes(a, b) uses a seeded PRNG (mulberry32) keyed on a hash of both parent genomes. This means the same two parents always produce the same child — verifiable by any client independently. No server needs to be trusted for the outcome.

1000091224.jpg

3. Ownership without on-chain state mutation

Since you can't mutate Steem posts, ownership is a derived concept. parseOwnershipChain() walks all replies on a creature post, finds the latest valid transfer_offer / transfer_accept handshake, and returns the effective owner. Permits issued before a completed transfer are automatically voided by comparing their timestamps against the transfer's permitsValidFrom value.

4. XP computation across six sources

XP covers founders (100), offspring (500), feeds given (10), upvotes cast on creature posts (5), unique genera contributed (25), and speciation events (75). For the leaderboard, this requires parallel per-user fetches of comment history (getDiscussionsByComments) and account vote history (getAccountVotes), cross-referenced against the corpus of known creature posts. All via Promise.allSettled to keep one slow node from blocking the whole render.

5. RPC node resilience

All API calls use a fallback chain across four public nodes (api.steemit.com, api.justyy.com, steemd.steemworld.org, api.steem.fans). A single callWithFallbackAsync wrapper handles retry logic transparently.

What I'd Do Differently

A few honest lessons from building this:

  • getDiscussionsByTag caps at 100 per call. Cursor-based pagination with start_author/start_permlink works, but it's verbose and requires careful off-by-one handling (the first result of page 2 overlaps with the last of page 1).
  • getRebloggedBy is not available on all nodes. I handle this with a .catch(() => []) but it means resteem counts silently fail on some nodes.
  • Client-side XP is eventually consistent. If a user has more than 100 recent comments or 1000 recent votes, their XP is slightly under-counted. Good enough for a game; not suitable for anything financial.

1000091225.jpg

White Paper

I've written a full white paper covering the genome system, lifecycle model, breeding mechanics, kinship rules, provenance system, ownership transfer protocol, and the full XP/rank structure. Happy to share it — drop a comment if you'd like a copy, or find it linked from the app's About page.

https://github.com/puncakbukit/steembiota/blob/main/SteemBiota_WhitePaper.pdf

Code

The full source is on GitHub: https://github.com/puncakbukit/steembiota

Happy to answer questions about any of the implementation details — the on-chain data model, the deterministic rendering pipeline, the client-side rule enforcement approach, or anything else. Always good to talk to other devs building on Steem! 🙌

@puncakbukit

Assisted by:

See also:

Sort:  

Nice idea, I like it. Besides, I never thought I’d have another child. But the urge was too strong :-)

Thanks.. :-)

I'm guessing that newly created creatures don't have ancestors. In other words, the user who creates the creature isn't considered a parent.

For example, I could create two creatures (male and female) of a genus, and when they have offspring, I simply create a counterpart to the offspring, and so the story goes on...

Am I right?

Yes, you're right. The same user can create two creatures in the same genus with different sex, then breed them after puberty to have an offspring.

Great, thanks!

Upvoted! Thank you for supporting witness @jswit.

Loading...
Loading...
Loading...

✨ SteemBiota Update: On-Chain Fashion has arrived! 🎩

Hey everyone! The ecosystem is evolving fast. I've just pushed a major update to the dApp: The Accessory System is officially live!

Your creatures no longer have to roam the blockchain "naked." You can now spruce them up with procedurally generated gear that is just as immutable and deterministic as the creatures themselves.

What’s new?

You’ll see a new ✨ Accessories tab in the navigation. From there, you can:

  • Craft Gear: Generate unique Hats, Crowns, Necklaces, and Wings.
  • Unique Genomes: Every accessory has its own 10-parameter genome. The color, size, and "shininess" are all baked into the blockchain record.
  • Procedural Styling: The tech is pretty cool—the accessories actually scale with your creature! A hat will look tiny on a "Baby" and grow as the creature reaches "Young Adult." Plus, necklaces actually wrap around the creature's neck using some clever canvas layering.

The "Permission" Meta 🔑

This is where it gets interesting for the community. Accessories have their own ownership and permission rules:

  1. The Handshake: Just like creatures, accessories can be transferred to other users using the two-sided handshake.
  2. Public vs. Private: If you craft a legendary Gilded Crown, you can keep it private, grant specific friends permission to wear it, or declare it Public Domain so the whole community can use it!
  3. The Closet: Once you have permission, just head to your creature's page, open the "Equip" panel, and pick your favorite items from your digital closet.

On-Chain History 📜

Every time you put a hat on or take wings off, a record is written to the Steem blockchain as a reply. The creature's "Equip State" is 100% decentralized.

Go try it out at the live link: https://puncakbukit.github.io/steembiota

Can't wait to see some stylish 🧬 Vyrex or 🧪 Aeral variants walking around! Let me know what you think of the new procedural art!

#steembiota #gaming #evolution #nfts #proceduralart

Loading...