building 360sona: the xbox 360 avatar editor, rebuilt in a browser tab a crowd of xbox 360 avatars in costumes, drawn by 360sona
every one of these is drawn live by the site's own renderer

360sona is the xbox 360 avatar editor running in a browser. you make an avatar, dress it from the whole marketplace (every item, free), take its picture in a photo booth, export it as a 3d model, or put it on your own website, where it idles, blinks and plays with its props. as i write this it has a little over a thousand accounts, 265 display cases living on other people's sites, and somehow a windows central article. the first commit was august 11th. it went public on september 1st.

this post is how it works and how it got made. it is also deliberately vague in a few places, and i would rather say so up front: anything that would let someone rebuild the site from a blog post stays off the page. what is left is still most of the interesting stuff.

it started as something else

in july i was poking at a much smaller idea, a browser tool for people with modded 360s to browse avatar items and get them onto a console. the research for that turned up a lot of surviving avatar data, and the longer i looked at it the less i cared about consoles. by august the idea was mii creator, but for 360 avatars: a web page where anyone can build one from scratch, keep a library of them, and make stuff with them. not a store. a community toy.

the one rule

the avatar editor is not a vibe, it is a very specific memory. gold has a particular sheen. heads sit a particular way. the camera swoops in a particular way when you open the hats menu. if a recreation is 90% right, people's brains flag the other 10% instantly and it reads as a knockoff. so early on the project got one rule, which i ended up typing in all caps more than once: never guess. every question about how something should look or move gets answered by microsoft's own software, not by eyeballing it and nudging numbers until it looks close.

in practice that meant side by side comparisons, constantly. my render on one side, the real thing on the other, same avatar, same pose, same camera, then a diff. the best example was skin. for a couple of days my avatars read slightly too tan next to the reference and a shadow under the chin refused to show up. every fix made it a little worse. eventually i called it: i was chasing ghosts. i threw out the last few changes, went back to the closest version, and only changed things i could actually point to in the original. the skin tone was right within the hour. the chin shadow took longer.

why this matters: a renderer is hundreds of small decisions. how bright the light is, what color a shadow is, how shiny metal is, how a texture gets filtered when it is small on screen. tune any of them by eye and you can make one screenshot match while quietly breaking a hundred others. matching the original's decisions one at a time is slower at first, and then it stops breaking.

what the renderer actually does

360sona is javascript and webgl with a small node server. no game engine, no 3d framework doing the drawing. the editor itself is about fifty thousand lines of it.

an avatar is a body plus a stack of parts. the body has a shape (the height and weight sliders really reshape it), a skeleton and a skin color. every shirt, hat, pair of glasses or costume is its own piece of geometry with its own textures and its own idea of which bones move it. some items replace parts of the body (a full costume swaps out nearly everything), some sit on top, some come in a male and a female version, and getting those rules right is most of the reason early renders had people with no trousers.

the face is the fun part. it is not a model with a face painted on, it is assembled. eyes, brows, mouth, nose, facial hair, freckles and the rest are separate layers, each with its own colors, composited into a single texture and drawn onto the head. expressions are more layers. so a blink or a smile means rebuilding part of that texture live, many times a second. which is great right up until it is not, more on that below.

a close-up of an avatar's face mid expression an avatar holding a guitar, drawn as a wireframe
a face, assembled live, and an avatar as plain geometry (this is what the 3d export gives you)

then the lighting, which is where the "that is the real one" feeling comes from: the soft studio light, the glow on bright things, reflections on metal items, the way skin and cloth take light differently. and the cameras. the editor has all seventeen of the original's camera framings, so when you open a menu it frames the avatar exactly the way the console did.

props were the final boss

props (the carryable items: a guitar, a sword, a t-rex you ride) were the hardest part of the whole project and they stayed broken the longest. a prop is basically a second little character, with its own geometry, its own skeleton and its own animation. the avatar plays a matching animation at the same moment, and the two have to line up exactly: hands on the handle, seat under the rider. get the alignment slightly wrong and the mech pilot sits next to his mech. i spent one entire night looking at a knight whose armor had been assembled by someone who had only heard of knights.

an avatar in a deadpool costume holding a captain america shield
props line up now. it took a while

it got solved the same way as everything else, frame by frame against microsoft's own renders of the same props. by the end, 129 of 160 test frames matched pixel for pixel, and the median overlap was perfect. on the site, props play every so often during the idle like they did on the console, and right away when you put one on.

twenty thousand items, then some

the launch catalogue was a bit over 21,000 items, and every one of them has a preview drawn by the real renderer, at the original camera framing, at full resolution. props get an animated preview too.

a wall of thousands of avatar item previews
a small corner of the catalogue

then people asked about the things that were never in the store: avatar awards, the items you earned by playing games. those were scattered everywhere and never collected in one place, so it turned into a long hunt, game by game. 835 awards are in now. same story with names: 2,123 items had no name at all, just an id, and they got their real names back from old store data and from the games themselves. 99.61% of the catalogue is named, and the rule on the site is that anything without a name simply is not listed. on top of that there are 912 collections, 11,866 gamerpics from 488 games for your profile, and 313 pets.

the display case

the feature i am proudest of. you design a little card (skins in the style of different xbox eras, colors, your gamertag, a row of links) and paste one line into your own website. visitors see your avatar live, not a picture: it idles, looks around, blinks and plays with its prop. you get ten per account, and you can edit one after it is live. the copy on your site notices and repaints itself without anyone reloading. since september 15th a case can also be a pet. visitors can feed it, play with it and put it to bed, and it gets hungry and bored on a real clock whether anyone is watching or not.

a 1998-style personal homepage with a live 360sona display case in the sidebar
a display case on a (made up) homepage, from the reveal video
a display case in pet mode, the avatar asking to play again
pet mode. it wants to play again

making that paste-and-play on every kind of website is harder than it sounds. the page around it might be a neocities site, a github pages portfolio, or a site builder that does strange things to embeds. it has to load fast on someone else's page, never stutter, and never break their layout.

the stutter was a good one. the case looked smooth, but every few seconds there was a tiny freeze. it turned out that some changes which only moved the avatar (a new pose, a camera move, the next animation) were rebuilding the whole avatar from scratch, parts and textures and all, instead of just moving its bones. on top of that, a facial expression it had never shown before got baked on the same thread that draws the frames, so the first blink of each new kind hitched. now changes that only move the avatar only move the avatar, and new faces are baked in a background worker and swapped in when they are ready.

a browser draws a frame about sixty times a second, so it gets roughly 16 milliseconds per frame. anything heavier than that, done on the same thread, is a hitch you can see. the cure is nearly always the same: do less per frame, and move the heavy work somewhere else.

since october, cases also count which websites they are shown on, by site name only, nothing about the visitor. so now i know one lives on a gaming site in the czech republic, and that the most viewed case of all is the one in windows central's article.

keeping it mine

the obvious problem with a project like this: everything a browser runs, a browser can see. so a lot of thought went into making sure what you can see does not add up to a recipe. i am not going to describe how that works, for obvious reasons, but the outline is this. the item data lives behind a gate i wrote called millrace, which hands the editor what it needs as it needs it and makes bulk copying slow and pointless. and the code your browser downloads is the machine's version, not mine: no comments, no notes, nothing that explains itself.

the gate works well enough that it kept catching me. during launch week the site sometimes took nine seconds to load, and i spent a long evening ruling out everything else before realizing it was the gate seeing my own test runs and treating my household like a scraper. real visitors never saw it. i saw it a lot.

launch week

it went up on september 1st, running on my nas at home through a cloudflare tunnel. the first days were mostly about load times. the homepage has a lot of live 3d on it, and making all of it show up fast without cheating (no frozen screenshots pretending to be the live thing) took more rounds than i would like to admit. the lesson i keep relearning: when it is good and working, stop. at least one "optimization" that week broke the homepage outright.

a week in, before posting it anywhere big, i moved it off the nas onto a small cloud server, because a home nas and a reddit post do not mix. by mid september windows central and yahoo tech had written about it, which i am still a little stunned by.

bugs from real people

launching means bug reports from hardware you do not own. my favorite: on firefox, and only firefox, on every platform, finishing character creation turned the whole page grey and froze it.

here is what happens when you press finish. the editor draws your new avatar a few times to make your profile pictures, copies each one out of the 3d canvas, and then releases the 3d context to free the memory. firefox does not actually do that copy when you ask. it makes a note to do it later, when somebody needs the pixels. by the time somebody did, the 3d context the pixels came from was gone, and the page sat forever waiting on a copy that could never finish. it never happened in automated testing, only in a real window, which is why it took the browser's profiler to see it. the fix is one line: read a single pixel back right after the copy, which forces firefox to do it then and there.

ctx.drawImage(webglCanvas, 0, 0);
ctx.getImageData(0, 0, 1, 1);   // makes firefox actually do the copy, now
gl.getExtension('WEBGL_lose_context').loseContext();

runner up: someone's spongebob item showed up as nothing until they reloaded the page. one download had failed on a network hiccup, and the editor remembered that failure as "this item does not exist" for the rest of the visit. now only a real "does not exist" is remembered. a failed download quietly tries again a few times on its own.

the trailers are code too

for the announcement video i did not want stock footage or ai video, so it is built as code: remotion (react, but for video) and react three fiber, assembling real screen captures of the site with scenes drawn by the site's own renderer, rendered out at 4k and 60fps and set to steve burke's avatar editor music. the september update video is a sequel built the same way. the best part of a video made of code is that when something is wrong in one shot, i fix a line and render again instead of redoing an edit.

what i took away

the original is the spec. every time the project went in circles it was because i had started guessing, and every time it got unstuck it was because i went back and looked at what the real thing does.

your own eyes are the best test. nearly every real bug was found by looking at a render and saying what was off: the gold is washed out, the trousers are missing, why does the knight look like that. the automated checks came after, to keep those bugs fixed.

and stop when it is good.

if you had a 360 and remember dressing up your avatar, go make one. it is free, there is no email, and the whole marketplace is unlocked. if you put it on your site, i will probably see it in the counts.

the 360sona robot mascot playing with a dog, next to the 360sona.com wordmark
the end card of the update video. the robot has a dog now

last updated 10/11/26, e. kruger