Fablebloom: inga dolda kort, ingen klocka, inga paket

Ett stillsamt strategiskt kortspel i webbläsaren. Åttiofyra kort, fyra familjer, tre gläntor, och regler som vägrar dold information, dragklocka och slumpade kortpaket.

Kund
Nuits
År
2026
Status
Före lansering
Roll
Ensam grundare, Speldesign, Produktdesign, Utveckling
Teknik
TanStack Start, TanStack Router, Vite, Cloudflare Workers, PWA, Umami
Fablebloom: inga dolda kort, ingen klocka, inga paket

Bakgrund

Fablebloom är ett strategiskt kortspel som körs i webbläsaren. Två Keepers tävlar om att väcka en sovande trädgård: du placerar små varelser, Fablings, på tre gläntor (Glades), och den Keeper som först återställer två av dem avslutar säsongen på stället. En säsong varar högst åtta Moons, alltså ungefär tio minuter.

Åttiofyra kort, fyra familjer, tre Glades. Gratis att spela, bara kosmetik i butiken, och inget konto behövs för att börja.

Det är en Nuits-produkt, så den är min hela vägen, och den är inte färdig. Namnet och illustrationerna är platshållare i väntan på varumärkes- och domänkontroll, och de juridiska sidorna är strukturella utkast. Det står på sajten själv, eftersom en sida som heter Our Promise och döljer sitt eget läge inte är ett löfte.

Problemet

Digitala kortspel griper efter tre verktyg som ett pappersspel knappt kan använda, och alla tre bär något. Dold information tillverkar spänning gratis. En dragklocka håller matchen i rörelse utan att be någon av spelarna vara hänsynsfull. Slumpade kortpaket gör en kortsamling till en intäktsrad som ett kalkylark kan modellera.

Var och en gör också spelet sämre att sitta med. Dold information betyder att det intressanta beslutet fattades medan du tittade bort. En klocka bestraffar eftertanke, alltså precis det spelet påstår sig handla om. Och en paketekonomi gör den starkaste leken till ett köp, så en jämn match är aldrig riktigt en komplimang.

Det jag ville ha var takten hos ett brädspel på ett bord, spelat av två personer som tycker om varandra, på tio minuter, i en flik.

Min roll

Allt, ensam. Nuits har aldrig anställt någon.

Speldesignen och kortsamlingen, gränssnittet, frontenden, driftsättningen, marknadssajten och texterna på den, inklusive stycket som erkänner att namnet är en platshållare.

Angreppssätt

Tre vägranden, inskrivna i reglerna snarare än på en värdegrundssida: ingen dold information som en pappersspelare inte kunde hålla i handen, inga klockor inuti reglerna, och ingen slump utöver blandning och dragning.

Allt annat fick byggas för att överleva dem. Utan klocka behöver matchen ett naturligt tidtagande, så en säsong är åtta Moons och varje Moon tar slut när båda Keepers vilar i rad. Utan paketekonomi måste kortsamlingen vara ändlig och möjlig att känna till, så det finns åttiofyra kort, alla intjänade genom att spela, och Trading Post säljer ramar och brädteman och ingenting som rör en regel.

Spänningen flyttade in i resursen istället. Dew fylls på till numret på pågående Moon och sparas inte, så första Moon är ett enda beslut och sjunde är en plan. Ingen kan spara sig fram till en utklassning, och den som ligger under får en större budget precis där matchen fortfarande går att vinna.

Var och en av de tre Glades bär en blomtröskel och en egen regel. Sunny Meadow ger ett kort till den Keeper som placerar sig där först. Ember Clearing tröttar allt som står där i slutet av varje Moon. Firefly Hollow betalar ett kort första gången under varje Moon som en av dina Fablings blir utmattad. Att återställa två Glades avslutar säsongen, så brädet ställer frågan om vilka två, inte en kapplöpning om poäng.

De fyra familjerna skiljs åt av hur de spelar, inte av vilken färg de har, även om de har färger. Grove slår rot och överlever brådskan. Ember rusar till en tidig ledning och tröttar ut dig innan du hunnit sätta dig. Pond samlar de trötta, så att svara den en gång är inte att svara den. Sky driver omkring och schasar hem dig, och du kommer att tro att du vet var den står.

Eftersom ingen regel innehåller en klocka kom asynkront spel nästan gratis. En match kan spelas ett drag om dagen över en privat länk skickad till en enda person, och ingenting i spelet märker skillnaden.

Så byggde jag det

Det började med Next.js, driftsatt till Cloudflare Workers via OpenNext, så att spelet och marknadssajten framför det är en kodbas istället för två. Det installeras som en app om du vill och förblir en sida om du inte vill.

Nu kör det på TanStack Start, alltså ett Vite-bygge som lämnas till Cloudflares Vite-plugin och blir en Worker utan något däremellan. Skälet till bytet var att ramverket besvarade en fråga som spelet inte ställer. Fablebloom är en klientapplikation utklädd till marknadssajt: ett bräde utan dold information är ett tillstånd som webbläsaren kan hålla i sin helhet, så när matchen väl börjat finns det ingenting på servern värt att vänta på.

Tre symtom, i den ordning de blev irriterande.

Kallstarter. OpenNext lade själva Next.js-servern i Workern tillsammans med ett Node-kompatibilitetslager, så den första förfrågan till ett färskt isolat betalade för att starta ett ramverk innan den kunde besvaras. Ett varmt svar gick iväg på ungefär 200 ms och ett kallt närmare 800, och den som betalade var den som öppnade fliken först.

Navigeringar som gick till nätet efter sådant klienten redan visste. Svarshuvudena bar vary: rsc, next-router-state-tree, next-router-prefetch, alltså App Router som talade om för varje cache att ett ruttbyte är en tur och retur till servern. Att gå mellan reglerna, en Glade och kortlistan kostade en varje gång, på sidor vars innehåll inte ändrats sedan bygget.

Vikt som anlände före spelet. Marknadssajtens startsida skickade omkring 220 kB komprimerad JavaScript i tolv delar innan ett enda kort dragits, mestadels ramverk, och hydrerade sedan ett serverrenderat träd som klienten tog över omedelbart ändå.

TanStack Start är samma idé i mindre format. Marknadssidorna förrenderas, routern löser ut i klienten, och serverfunktioner täcker de två eller tre saker som verkligen behöver en server: en matchlänk, ett sparande och inloggningen bakom spelsidan. Gränsen mellan klient och server är dragen där applikationen faktiskt har en, inte där ramverket antog att den skulle ligga.

Statistiken går genom Umami, självhostat istället för överlämnat till ett analysföretag, samma upplägg som varje annan Nuits-produkt.

Den intressanta begränsningen är den första vägran. Ett spel utan dold information har ingenstans att förvara ett misstag: båda spelarna ser hela brädet hela tiden, så varje avvikelse mellan vad reglerna säger och vad skärmen visar syns för dem båda samtidigt. Det pressar regelverket mot att vara litet nog att återges i sin helhet. Åtta Moons, en handling per drag, fyra korttyper, tre Glade-regler, och en Dew som nollställs. En spelare som misstänker att spelet räknat fel kan kontrollera saken, vilket bara är möjligt för att det finns lite att kontrollera.

Resultat

Spelbart och inte lanserat. Sajten är uppe, reglerna är skrivna, kortsamlingen är komplett, och namnet ovanpå alltihop är tillfälligt. Varumärkes- och domänkontroll kommer före en lansering, inte efter, och tills den är klar finns det ingen poäng med att låtsas att ytterdörren är färdig.

Vad jag skulle göra annorlunda

Jag designade åttiofyra kort och fyra familjer innan namnet var kontrollerat. Om kontrollen går illa går ingenting av kortdesignen förlorad och all illustration gör det, och den ordningen gick att undvika. Den tråkiga juridiska kontrollen kostar lite tidigt och mycket sent.

Jag valde också ramverket innan jag visste vilken form appen skulle ta. Next.js är ett bra svar på en fråga om sidor, och Fablebloom visade sig vara en fråga om ett bräde. Att välja renderingsmodell först och månader senare upptäcka att det man byggt är en klientapplikation är ett misstag som bara visar sig som latens, och migreringen var notan för det.

Jag publicerade också de juridiska sidorna som strukturella utkast med platshållartext. Jag tycker fortfarande att det är bättre att visa skelettet med en synlig notis om att det inte är bindande än att inte visa något alls, men det är en märklig sak att ha uppe bredvid en sida som beskriver en butik. Den ärliga versionen av den meningen är att butiken skrevs före pappersarbetet.