Why I’m Betting on ProtoSpec: Designing Software Before It Designs You

We’ve all tried to architect complex systems in a chat window or a scratch repo. It works… until it doesn’t. Context gets lost, “final” decisions drift, and your first runnable thing is already coupled to a framework choice you made on a Tuesday night.

ProtoSpec is my antidote: a tiny language + a lightweight web IDE that lets me design in prose and pseudocode, generate runnable skeletons on demand, and keep the spec itself as the single source of truth. It’s simple on purpose.

Here’s what you get and why it matters.


The pain ProtoSpec fixes

  • Design by vibes: Ideas get buried in threads. Later, no one remembers the trade-offs.
  • Premature coupling: You commit to a stack before you’ve nailed the seams.
  • LLM thrash: Long chats blow context. Copy/paste becomes the “API”.
  • Spec rot: Diagrams and docs drift from the code (or never existed).

ProtoSpec turns that chaos into a loop you can run all day: spec → preview → generate → test → repeat.


What is ProtoSpec (in one screen)

  • A human-friendly proto language (“ProtoScript”) that reads like clean pseudocode.
  • A web IDE that stores specs locally, visualizes flows, and generates runnable projects.
  • A versioned canon: grammar, AST, and mapping tables are SemVer’d and baked into a Help panel.
  • A pluggable assistant (ChatGPT or Ollama) scoped to your current spec—no more context soup.

A tiny ProtoScript snippet:

record Order { id, items[], total=0, status="new" }
map<string, Order> orders

http POST /orders -> create_order
http GET  /health -> health

fn create_order(req): {
  let o = { id: req.id, items: req.items, total: sum(req.items), status:"new" }
  orders[o.id] = o
  emit order.created { id:o.id, total:o.total }
  return o
}

fn health(req): { return { ok:true } }

Click Generate and you get a TypeScript/Express app with handlers, routes, a tiny event bus, and tests.


Why this beats starting in a framework

1) Boundaries first, code second

You model records, maps, and events up front. HTTP, queue, and cron bindings are declarations—not commitments.

2) One spec → many targets

The emitter maps ProtoScript to Node/TS today (PHP or game/3D targets are easy to add). Your spec survives platform changes.

3) Always-runnable scaffolds

Every iteration can end in a runnable artifact. That kills analysis paralysis and flushes edge cases early.

4) LLMs that actually help

The IDE can send just the relevant slice of the spec to your assistant (ChatGPT or local Ollama). Short prompts. Better answers.

5) Versioned language, predictable upgrades

Grammar and mappings live under /canon. The IDE warns when your specVersion drifts and links you to the exact rule or changelog. If you need it, a compat flag keeps old projects unblocked while you migrate.

6) Specs that double as tests

“Examples” go straight to test stubs. Your spec isn’t a PDF; it’s executable intent.


How the loop feels in practice

  1. Sketch the shape
    Write the problem, context, and a few examples. Declare your records, maps, and IO bindings.
  2. Add just enough behavior
    Use fn, emit, expect. Keep bodies short. Push accidental complexity into later passes.
  3. Generate
    Get a runnable project with routes and handler stubs; run smoke tests; wire real integrations only when needed.
  4. Refine
    Tweak the spec. The emitter re-generates, preserving any custom code behind clearly marked regions.
  5. Ship
    When the skeleton is stable, deepen the implementation. The spec continues to serve as your contract.

Show me the benefits (the blunt version)

  • Speed: Faster to a running thing with the right boundaries.
  • Clarity: The contract is explicit and short. No “hidden” decisions.
  • Swapability: Change frameworks without rewriting the spec.
  • Onboarding: New devs can read one file and understand the system.
  • Testability: Examples compile into tests; events/handlers are first-class.
  • LLM leverage: Assistants can work against a stable schema instead of noise.
  • Governance: SemVer’d language + Help panel = fewer “what does this mean?” pings.

A tiny example, end to end

Spec (abridged):

record User { id, email, tags[]=[] }
map<string, User> users

http POST /users -> create_user

fn create_user(req): {
  let u = { id: req.id, email: req.email, tags: [] }
  users[u.id] = u
  emit user.created { id:u.id, email:u.email }
  return u
}

Generate → Run:

npm run dev
# POST /users {"id":"1","email":"[email protected]"} -> 201 {"id":"1","email":"[email protected]","tags":[]}
# event: user.created emitted

You didn’t pick a DB, auth, or queue yet. That’s the point. Boundaries first.


What ProtoSpec is not

  • Not a framework. It won’t pick your ORM or queue. It declares seams.
  • Not a silver bullet. If your spec lies, your code will too—faster.
  • Not a lock-in. Specs are plain text. Generators are replaceable.

Migration & versioning (without the drama)

We keep a canonical spec registry under /canon. The IDE:

  • reads your specVersion,
  • warns on mismatch,
  • offers a compat pack toggle (so old specs still run),
  • links you to the exact grammar rule or mapping that changed.

You can upgrade when you’re ready, not when the tool says so.


How to start

  1. Write a problem section in plain English.
  2. Add records and maps to capture state.
  3. Bind HTTP (and later queue/cron) to handlers.
  4. Add 1–2 examples as lightweight tests.
  5. Click Generate. Run it. Iterate.

If you need a nudge, the IDE’s Help panel has the grammar, AST typings, mapping tables, and changelog—all versioned.


Final take

ProtoSpec keeps me honest. I still move fast—but I don’t skip the part where we decide what the system is. And when I want help, my assistant isn’t guessing; it’s reading the spec I’m reading.

If you’ve been feeling that your codebase is designing you instead of the other way around, try a week with ProtoSpec. Worst case, you’ll ship a better skeleton. Best case, you’ll ship the right thing on purpose.

Screeps LLM Agent

✅ Architecture Plan

Architecture Plan

  1. Data Flow Overview
Official Screeps Server  <--->  Screeps API (HTTPS)
                                    |
                                    v
                        Local "Brain" (Node.js + LLM)
                                    |
                  ------------------+---------------------
                  |                                    |
        Live Commands via API                 Code Edits on Disk
    (Memory updates, spawn orders)     (LLM rewrites / optimizes JS files)

  1. Core Components

A. Screeps API Integration

Use the screeps-api NPM package.

Install:

npm install screeps-api node-fetch

Basic Setup:

const { ScreepsAPI } = require(‘screeps-api’);
const api = new ScreepsAPI({
email: ‘[email protected]’,
password: ‘yourPassword’,
serverUrl: ‘https://screeps.com’ // official server
});

(async () => {
await api.auth();
const memory = await api.memory.get(‘brainInput’);
console.log(‘Current Memory:’, memory.data);
})();

You’ll use:

api.memory.set() to push game state snapshots to the LLM or receive commands back.

api.rawSegment for larger data packets if needed.

B. Local LLM Processing

Your local model (Ollama/DeepSeek) runs continuously:

Polls Screeps API every X ticks (say every 10 seconds).

Reads game state (brainInput).

Generates:

    Immediate orders (e.g., {spawn: [{role:'miner',room:'W1N1'}]}).

    Suggestions for code changes (e.g., "optimize miner.js to use path caching").

Example prompt snippet:

const prompt = Game state: ${JSON.stringify(memory.data)} 1) Suggest immediate orders in JSON (no text). 2) Suggest code optimizations if needed (which file, what to change). ;

C. Writing Commands Back

Push orders directly:

await api.memory.set(‘brainOutput’, JSON.stringify(orders));

Then, in your Screeps code:

if (Memory.brainOutput) {
executeOrders(JSON.parse(Memory.brainOutput));
delete Memory.brainOutput;
}

D. Local Code Editing

Since you’re syncing code with the official server:

The LLM generates code patches (JS diffs or full file replacements).

Node.js applies changes to the local /scripts folder.

Screeps’ official client auto-syncs these changes.

Example:

const fs = require(‘fs’);
function updateFile(file, newCode) {
fs.writeFileSync(./screeps/scripts/${file}, newCode, ‘utf8’);
console.log(${file} updated, syncing with Screeps...);
}

You can even have the LLM generate diffs:

File: miner.js

Replace function runMiner with:

function runMiner(creep) {
if(!creep.memory.path) {creep.memory.path = creep.pos.findPathTo(Game.sources[0]);}
if(creep.harvest(Game.sources[0]) == ERR_NOT_IN_RANGE) {
creep.moveByPath(creep.memory.path);
}
}

Your Node.js script parses this and rewrites the file.

  1. Recommended Flow Every 10–20 ticks: Pull game state via API → LLM → push back orders (brainOutput). Every few hours or on trigger: Ask the LLM for code refactors. Save changed files locally → Screeps client auto-syncs. Optional Safety: Auto-commit changes to Git after each edit, in case the LLM breaks something.

Building Emergent Ant Intelligence with Babylon.js and a Local LLM

View the source code on GitHub https://github.com/doctarock/AntBrain

Introduction In this project, I set out to build the foundational components of artificial cognition using lightweight agents in a Babylon.js environment. The goal wasn’t to simulate a human brain, but something simpler and more achievable: a virtual “ant brain.” Through step-by-step iterations, I introduced perception, memory, and decision-making powered by a local large language model (LLM) running via Ollama.


Step 1: Setting the Scene with Babylon.js I began by creating a minimal 3D world using Babylon.js. The environment included a simple ground plane and several spheres representing agents (ants). These spheres were animated to move around the space with basic logic, simulating movement across a terrain.

Technologies Used:

  • Babylon.js (UMD version for browser compatibility)
  • Node.js static server (Express)
  • Custom proxy middleware to handle CORS issues with Ollama

Step 2: Adding Cognition – Perception and Memory Once the world was in place, I gave each agent the ability to perceive its environment. This included checking for nearby agents within a perception radius and logging these encounters in memory.

Each agent maintained:

  • A list of recent positions
  • A memory of other agents it has seen
  • A log of its own thoughts

This memory would serve as the context for decision-making.


Step 3: Integrating the Local LLM With cognition in place, I hooked up each agent to a local LLM hosted by Ollama. I chose OpenHermes for its conversational tone and ability to stay in character. Each agent constructs a prompt based on its memory and current perception, then sends that prompt to the LLM.

Example prompt:

You are an autonomous agent exploring a virtual world.
You remember: Saw agent 2 nearby.
You currently perceive: Agent 3 at (x, z).
What will you do next and why? Format your answer as:
Action: <...>
Reason: <...>

The LLM’s response determines the agent’s next direction of movement.


Step 4: Preventing Overload – Throttling LLM Requests Running LLM inference every animation frame quickly overwhelmed the system. To fix this, we throttled each agent to only send a request every 3 seconds. This kept Ollama stable while allowing agents to reflect and act periodically.


Emergent Behavior Observed Once throttling was in place and OpenHermes was responding correctly, we started seeing surprisingly organic outputs:

Agent 1 thought: Action: Move forward. Reason: To explore the environment and gather information.
Agent 2 thought: Action: Explore the environment. Reason: To gather information and potentially find new resources.

These responses, while simple, represent the foundation of autonomous behavior: perceiving, remembering, and acting with purpose.


At this stage, the agents demonstrate:

  • Local perception
  • Memory of encounters
  • LLM-driven decision-making
  • Individual internal logic and reflection
  • Co-operation
  • Shared memory or communication between agents
  • Goal-setting and prioritization
  • Emotional or philosophical traits
  • Planning and resource seeking

Conclusion With very little direction, these little characters started talking, working together, sharing and forming their own little (emulated) personalities based off the input gained from the environment. I am very impressed with OpenHermes, it was a lot easier to train than deep-seek and other local llms I have tested.

Stay tuned for the next evolution.


Tags: Babylon.js, Ollama, LLM, AI Agents, Ant Simulation, Emergent Behavior, OpenHermes, Cognitive Architecture

Modding Games is Easier Than Ever – Thanks to AI

Let’s be real—game modding used to be a bit of a black art. Between cryptic file formats, scattered community docs, and figuring out what the hell a normal map is, just adding a glowing sword to Skyrim could feel like building a nuclear reactor with duct tape.

But that’s changing fast. Thanks to large language models (LLMs) like ChatGPT, DeepSeek, and their open-source cousins, modding is suddenly… approachable. Like, you don’t need to be a programmer approachable. You just need curiosity and a decent prompt.


AI Makes Modding Stupidly Accessible

Modding used to start with hours of Googling and forum-diving. Now it starts with:
“Hey, how do I add a new weapon to [game name]?”

And you’ll actually get an answer. Step-by-step. Maybe even with example files. Want to know what each parameter in a config file does? LLMs can explain that too. Want to convert a .png into the right texture format? Ask. It’s like having a modding mentor on speed dial—minus the “RTFM” attitude.


A Simple Example: Minecraft

Let’s take Minecraft, because it’s wildly popular and heavily modded. Let’s say you want to add a new food item—something absurd like a “Spicy Pickle” that gives you fire resistance.

Instead of trawling through outdated YouTube tutorials, you can literally type this:

Prompt:
“Can you generate the code and assets needed to add a new food item to Minecraft using Fabric, called ‘Spicy Pickle’? It should restore 3 hunger, give 10 seconds of fire resistance, and have a funny tooltip. Make it compatible with Minecraft 1.20.”

Boom—LLM gives you the item JSON, the class definition in Java, the en_us.json localization, and sometimes even the folder structure. Paste, tweak, test. Done.

Want the pickle to glow green in the hotbar? Ask. Want to add crafting recipes? Ask. You’re no longer at the mercy of modding forums from 2014.


It’s Not Just Minecraft

This works with tons of games—7 Days to Die, Skyrim, Baldur’s Gate 3, even Stardew Valley. Anything with an open modding API or a scripting layer can be reverse-engineered with the help of an LLM. You don’t need to memorize every ModLoader quirk—just describe what you want.


The Prompt is the New Skill

Modding now feels like a blend of creativity and prompting. You imagine something cool, then describe it clearly. The better you prompt, the better your result. Want a haunted tree that drops screaming apples in Valheim? You don’t need to code it from scratch—you just need to ask.

Here’s a good prompt template to get started:

“I want to create a [object/item/event/NPC] in [game] using [modding framework]. It should [describe features]. Can you generate the code, config files, and any assets or folder structure needed?”

It doesn’t need to be perfect. You can always follow up with:

“Add a sound effect.”
“Make it rarer.”
“Give it particle effects when picked up.”


Final Thought

Modding with AI doesn’t remove the joy of tinkering—it amplifies it. You still get to tweak, break things, and learn. You just skip the part where you have to reverse-engineer someone’s 2012 blog post.

So if you’ve ever wanted to make your mark on a game you love, there’s no better time. Dream up something weird, throw it at an LLM, and see what happens. Your Spicy Pickle Army awaits.

Building a Sci-Fi Web Experience in Babylon.js + WordPress

Role: UX Designer / Frontend Dev
Tech Stack: Babylon.js, WordPress (AJAX), Custom Theme (CSS + JS)
Goal: Create a seamless, immersive sci-fi themed site where page navigation feels like moving through space, not loading a new page.


📐 Concept & UX Goals

From the outset, the experience had to feel like operating a sci-fi viewscreen. Every interaction, click, scroll and transition, should feel spatial and connected. We weren’t building a site, we were building a starship UI.

Our core UX goals:

  • Pages = Places: navigating to a new page would “move” the camera to a new area of the space scene
  • Minimal UI: reduce visual clutter to improve immersion
  • Asynchronous Loading: no full reloads, just transitions
  • Scene-Integrated Navigation: content and environment exist in the same universe

🌌 Babylon.js Scene

I started by crafting a Babylon.js space environment:

  • A static camera at (0,0,0)
  • Distant stars, planets, nebulae
  • A configurable offset vector allowed us to simulate movement through the universe by shifting the rendered positions of celestial bodies

Rather than move the camera itself (which could break large-scale visual fidelity), I updated each object’s render position based on the current offset, simulating “traveling” to content.

jsCopyEditlet renderPosition = originPosition.subtract(offset);
mesh.position.copyFrom(renderPosition);

🚀 Navigating with Offset

Each WordPress page was mapped to a specific position in space. Navigating to /about might move the scene’s offset to (5000, 0, -10000). I added smooth interpolation with easing so it felt like flying:

jsCopyEditoffset = BABYLON.Vector3.Lerp(offset, targetOffset, speed);

🔁 Asynchronous Content Loading

Using AJAX (wp_ajax in PHP), I loaded pages dynamically without reloading the scene:

  • All links intercepted via JavaScript
  • Pages loaded via jQuery.ajax
  • The HTML content (usually .entry-content) was swapped into the DOM
  • Babylon’s update loop persisted across transitions

Each request returned HTML fragments from WordPress templates (get_template_part()), not full pages.

if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
get_template_part('template-parts/content', 'page');
}
}

🧠 UX Considerations

  • Minimal layout: No bulky header or footer. Just a soft HUD-styled logo and a subtle menu tucked in the corner.
  • Focus on content: Each page block hovered in the scene like a projected panel, with thin neon borders and glowing text.
  • Consistent frame: Scene stayed loaded at all times, which made transitions feel native, not like switching pages.

💫 Design System

I defined reusable styles that mirrored Star Trek and Mass Effect interfaces:

  • Typography: Orbitron, VT323, and glowing letter shadows
  • Menu: A semi-transparent, floating “command stack” with expanding tree-like submenus
  • Page container: 3D-transformed <article> blocks that could rotate slightly with scroll to simulate perspective
  • Animations: Fade-ins, pulse highlights on hover, glint effects on logos

🔧 Challenges

  • Camera vs. Offset: Avoiding actual camera movement helped prevent precision issues at astronomical scales.
  • Dynamic Element Bindings: We had to re-bind event listeners and re-init transitions after each AJAX load.
  • Performance: Particle systems (like nebulae) required LOD toggling and distance culling to keep the experience smooth.

🧩 Tying It All Together

Every piece, navigation, animation, styling, and spatial layout feeds into one consistent UX metaphor:

You’re not browsing a website. You’re navigating a ship’s digital log interface.


✅ What’s Next

Building My First AI WordPress Agent: A Developer’s First Experiment with Local LLMs

Tired of the same repetitive tasks? Could AI actually automate the boring stuff, or is it just another overhyped tool?

I decided to build an AI-powered agent that could help manage my WordPress sites. Something that could understand context, take actions, and automate tedious dev/admin tasks I’d normally do by hand.

I want it to:

  • Receive natural language instructions (e.g. “clear all caches” or “create a blog post with these specs”)
  • Interpret what I meant, not just what I said
  • Trigger real-world actions via WordPress CLI or REST API
  • Run locally (no cloud dependencies, no vendor lock-in)

Basically: an intelligent shell script with a brain.


🧰 Tools I Used

  • 🧠 DeepSeek Coder 6.7b – A locally hosted language model running through Ollama, fast and responsive
  • 🧩 Node.js backend – Simple REST interface for prompt sending and response parsing
  • ⚙️ WordPress CLI / REST API – Execution layer for real actions
  • 🛠️ Custom instruction layer – Wrapped the LLM output with a JSON validator/parser to ensure structured commands and retry if the model was off

🧪 The Architecture

  1. Input: I send a prompt like “Can you list the 10 latest draft posts and convert them to published?”
  2. LLM Response: DeepSeek parses that into a structured JSON plan: jsonCopy{ "action": "update_posts", "params": { "status": "publish", "filter": "draft", "limit": 10 } }
  3. Validator: My wrapper checks it, retries if needed, or rejects unsafe commands
  4. Executor: Runs wp post update or REST equivalent and returns success/failure

It’s modular, secure-ish (I’m still locking it down), and after a lot of trial and effort, it is beginning to feel like magic.


🧠 What Surprised Me

  • Local LLMs can be a useful tool : With the right prompting, even a local 6.7b model is incredibly capable, however, getting the prompt format and composition right by filtering the input is most of the battle.
  • They’re also fragile: Without strong validation, they’ll give you confident nonsense. Guardrails are critical.
  • JSON output wrapping is your best friend: Teach the model to respond as a tool, not a poet, and you’ll eventually get consistent responses.

🧱 What’s Next

  • Expand it to use the REST API, to increase capabilities
  • Integrate with server-side shell tasks (upgrades, backups, etc.)
  • Maybe even let it run scheduled audits and suggest updates before I need them

🚀 Final Thoughts

This project was my first dive into applying AI in a practical way right now, and learning how to develop LLM wrappers from the ground up, without relying on cloud services. Running an intelligent local agent that speaks my language and interfaces with my tools feels like the start of a new wave of devops automation.

If you’re a developer and haven’t played with local LLMs + CLI/API integration yet… it might be time to start.

Got questions or want to build something similar? Reach out on LinkedIn or check out the repo at github.com/doctarock.

Hey, I’m Derek – I Build Stuff

Welcome to my corner of the internet.

I’m Derek Robertson—developer, systems guy, occasional designer-wrangler, and all-around problem solver. I’ve been in the game for over 25 years, turning clunky, chaotic systems into smooth, scalable digital solutions. Right now, I’m part of the crew at Buildxact, working at the intersection of SaaS, construction tech, and real-world usability.

What I Actually Do

My background spans full-stack development, content platforms, e-commerce, CMS architecture, integrations, UX optimization, DevOps, and a healthy dose of “how do we make this thing talk to that thing?” I’ve worked on cross-platform apps, internal tools, customer portals, and websites that handle millions of requests a day.

I’ve worn many hats: developer, team lead, systems designer, tech translator, bug hunter, and mentor. If you need someone who can build it, fix it, streamline it, or make sense of it — I’m your guy.

Tools of the Trade

Tech-wise, I work mostly with:

  • PHP, C#
  • JavaScript / Node.js (React)
  • SQL, GraphQL, REST APIs
  • Azure, Git, Copilot
  • Photoshop, Krita, GIMP
  • Virtualmin, CPanel

But honestly? I care more about why we’re building it than what stack it’s on.

Why It Matters

I like working on things that help real people do real work. Whether it’s helping builders quote jobs faster, making internal systems suck less, or improving onboarding flows that reduce support calls—I’m all about meaningful improvements. If we can cut steps, reduce errors, and give users more confidence in their tools, that’s a win.

What You’ll Find Here

This blog is a place for the stuff I wish more people talked about:

  • Building smarter, not bigger
  • Lessons from the field (and the dev trenches)
  • Dev workflows that actually save time
  • UX decisions from a dev’s point of view
  • And probably a few war stories along the way

Thanks for stopping by—feel free to reach out if you want to chat code, ideas, or the weird bugs that keep you up at night.

Catch you in the next post.
– Derek