[{"data":1,"prerenderedAt":3681},["ShallowReactive",2],{"site-content":3,"readme-osmium":1959,"readme-clay":2300,"readme-forkcast":2598,"readme-backbone":2848,"readme-helix":3126,"post-slide-\u002Fposts\u002F2026-09-27-backbone-hot-reload":3484,"post-slide-\u002Fposts\u002F2026-09-27-osmium-credentials":3625},{"en":4,"de":1191},{"projects":5,"posts":672,"timeline":950,"skills":984,"profile":1164},[6,35,60,107,177,194,217,244,263,324,562],{"id":7,"title":8,"badge":9,"body":10,"built":9,"description":14,"extension":17,"links":18,"meta":22,"navigation":23,"order":24,"path":25,"seo":26,"stack":27,"stats":9,"stem":31,"tagline":32,"tier":33,"visuals":9,"why":9,"__hash__":34},"projects\u002Fprojects\u002Faether.md","Aether",null,{"type":11,"value":12,"toc":13},"minimark",[],{"title":14,"searchDepth":15,"depth":15,"links":16},"",2,[],"md",[19],{"label":20,"href":21},"Source","https:\u002F\u002Fgithub.com\u002Fe-reitbauer\u002Faether",{},true,1,"\u002Fprojects\u002Faether",{"title":8,"description":14},[28,29,30],"Kotlin","Coroutines","kotlinx.serialization","projects\u002Faether","Socket transport with a binary codec, kotlinx.serialization and coroutines.","more","yf_ZiZyr8qjMXl0v7gOeHZJ5lSH2VWtf7J-Xq4ixX2k",{"id":36,"title":37,"badge":9,"body":38,"built":9,"description":43,"extension":17,"links":46,"meta":49,"navigation":23,"order":24,"path":50,"seo":51,"stack":52,"stats":9,"stem":56,"tagline":57,"tier":58,"visuals":9,"why":9,"__hash__":59},"projects\u002Fprojects\u002Fgranum.md","Granum",{"type":11,"value":39,"toc":44},[40],[41,42,43],"p",{},"Stores decisions, preferences and constraints as typed chunks, retrieves them by similarity plus graph traversal, and keeps memory separate per git branch.",{"title":14,"searchDepth":15,"depth":15,"links":45},[],[47],{"label":20,"href":48},"https:\u002F\u002Fgithub.com\u002Fe-reitbauer\u002Fgranum",{},"\u002Fprojects\u002Fgranum",{"title":37,"description":43},[53,54,55],"Python","Kuzu","MCP","projects\u002Fgranum","Persistent memory for Claude Code, backed by a local vector and graph database.","featured","Ct1sZnesmJBWb0h8gFck3ozj0SCFkA1QGmCKfXins5A",{"id":61,"title":62,"badge":9,"body":63,"built":70,"description":67,"extension":17,"links":73,"meta":76,"navigation":23,"order":24,"path":77,"seo":78,"stack":79,"stats":85,"stem":97,"tagline":98,"tier":99,"visuals":100,"why":105,"__hash__":106},"projects\u002Fprojects\u002Fosmium.md","Osmium",{"type":11,"value":64,"toc":68},[65],[41,66,67],{},"Agents sign in through a host process, walk or fly to their segment and place it course by course. The dashboard shows live 3D views, a shared map the agents chart as they move, inventories, telemetry and an audit log. Configuration is stored centrally and replayed to hosts on every reconnect.",{"title":14,"searchDepth":15,"depth":15,"links":69},[],{"problem":71,"solution":72},"A dump of the database should never be enough to take over the Minecraft accounts the fleet plays with.","Osmium never holds the credentials and never performs the login. The backend only sends a host a setup command; the host signs the account in on a machine its owner controls and reports back the username and UUID. Hosts dial out to the backend instead of being connected to, and an unreachable host makes its agents' state unknown rather than offline.",[74],{"label":20,"href":75},"https:\u002F\u002Fgithub.com\u002Fintegr-dev\u002Fosmium",{},"\u002Fprojects\u002Fosmium",{"title":62,"description":67},[80,28,81,82,83,84],"TypeScript","Vue","Spring Boot","PostgreSQL","mineflayer",{"asOf":86,"source":75,"items":87},"2026-09-27",[88,91,94],{"label":89,"value":90},"commits","352",{"label":92,"value":93},"of them mine","341",{"label":95,"value":96},"first commit","2026-08","projects\u002Fosmium","Runs a fleet of headless Minecraft agents that build one large schematic together.","flagship",[101],{"kind":102,"label":103,"diagram":104},"diagram","Architecture","osmium","My largest system so far. One operator uploads a schematic, Osmium splits it into segments, hands each agent its slice, and a web dashboard follows every agent live.","xgvpWAldjJfE0_IPqT78l64x5xSomDNSuCkVQgF4-lE",{"id":108,"title":109,"badge":9,"body":110,"built":126,"description":129,"extension":17,"links":130,"meta":142,"navigation":23,"order":15,"path":143,"seo":144,"stack":145,"stats":149,"stem":160,"tagline":161,"tier":99,"visuals":162,"why":175,"__hash__":176},"projects\u002Fprojects\u002Fclay.md","Clay",{"type":11,"value":111,"toc":124},[112],[41,113,114,115,119,120,123],{},"Documentation lives in ",[116,117,118],"code",{},"docs\u002F"," as plain Markdown. Clay Oven scans it, writes the navigation structure and bundles it with a prebuilt Clay frontend. One ",[116,121,122],{},"clay.yaml"," sets title, navbar, languages and landing page.",{"title":14,"searchDepth":15,"depth":15,"links":125},[],{"problem":127,"solution":128},"Most documentation tools want a project to adopt a static site generator and its build.","The Clay frontend ships prebuilt and reads everything it needs at runtime from two files: clay.yaml, written by hand, and clay-structure.yaml, which Clay Oven, a Go CLI, generates by scanning docs\u002F. A repository only adds Markdown and a config file.","Documentation lives in docs\u002F as plain Markdown. Clay Oven scans it, writes the navigation structure and bundles it with a prebuilt Clay frontend. One clay.yaml sets title, navbar, languages and landing page.",[131,134,136,139],{"label":132,"href":133},"Live demo","https:\u002F\u002Fclay-doc.github.io\u002Fclay-example-repo\u002F",{"label":109,"href":135},"https:\u002F\u002Fgithub.com\u002Fclay-doc\u002Fclay",{"label":137,"href":138},"Clay Oven","https:\u002F\u002Fgithub.com\u002Fclay-doc\u002Fclay-oven",{"label":140,"href":141},"Example","https:\u002F\u002Fgithub.com\u002Fclay-doc\u002Fclay-example-repo",{},"\u002Fprojects\u002Fclay",{"title":109,"description":129},[81,146,80,147,148],"Nuxt","Go","Shiki",{"asOf":86,"source":150,"items":151},"https:\u002F\u002Fgithub.com\u002Fclay-doc",[152,155,157],{"label":153,"value":154},"repositories","3",{"label":89,"value":156},"51",{"label":158,"value":159},"stars","5","projects\u002Fclay","A documentation framework that drops into an existing repository.",[163,166],{"kind":102,"label":164,"diagram":165},"Diagram","clay",{"kind":167,"label":168,"images":169},"images","Screenshot",[170],{"src":171,"alt":172,"width":173,"height":174},"\u002Fimg\u002Fclay-demo.webp","The Clay example docs site showing the Advanced Features page with sidebar navigation and highlighted code",1600,910,"A complete toolchain I designed and maintain under its own organisation. A Vue and Nuxt frontend plus a Go CLI that turns a folder of Markdown into a deployable site.","V3FdDWffaBt1gq000icQsPjar_Om5RpeqgUuAIZ6snE",{"id":178,"title":179,"badge":9,"body":180,"built":9,"description":14,"extension":17,"links":184,"meta":187,"navigation":23,"order":15,"path":188,"seo":189,"stack":190,"stats":9,"stem":191,"tagline":192,"tier":33,"visuals":9,"why":9,"__hash__":193},"projects\u002Fprojects\u002Fkonvert.md","konvert",{"type":11,"value":181,"toc":182},[],{"title":14,"searchDepth":15,"depth":15,"links":183},[],[185],{"label":20,"href":186},"https:\u002F\u002Fgithub.com\u002Fe-reitbauer\u002Fkonvert",{},"\u002Fprojects\u002Fkonvert",{"title":179,"description":14},[28],"projects\u002Fkonvert","A small JSON parsing library.","GD_36_SML3_9VPEvMy7SZk_e46wO0a9epKW3JBLQ54A",{"id":195,"title":196,"badge":9,"body":197,"built":9,"description":201,"extension":17,"links":204,"meta":207,"navigation":23,"order":15,"path":208,"seo":209,"stack":210,"stats":9,"stem":214,"tagline":215,"tier":58,"visuals":9,"why":9,"__hash__":216},"projects\u002Fprojects\u002Fscry.md","Scry",{"type":11,"value":198,"toc":202},[199],[41,200,201],{},"Press Option Space anywhere, type, and the file opens at the matching line. The search on this page works the same way.",{"title":14,"searchDepth":15,"depth":15,"links":203},[],[205],{"label":20,"href":206},"https:\u002F\u002Fgithub.com\u002Fe-reitbauer\u002Fscry",{},"\u002Fprojects\u002Fscry",{"title":196,"description":201},[211,212,213],"Swift","SwiftUI","ripgrep","projects\u002Fscry","A search bar for macOS. Like grep, but for people.","jOFS-iD8lYQNu7NqjBgeJKVjpgnS7FCQkUR8liHxvXA",{"id":218,"title":219,"badge":9,"body":220,"built":9,"description":224,"extension":17,"links":227,"meta":234,"navigation":23,"order":235,"path":236,"seo":237,"stack":238,"stats":9,"stem":241,"tagline":242,"tier":58,"visuals":9,"why":9,"__hash__":243},"projects\u002Fprojects\u002Fcastl3d.md","Castl3d",{"type":11,"value":221,"toc":225},[222],[41,223,224],{},"Moves are validated on the client for speed and again on the server. Bots live on the backend behind one interface.",{"title":14,"searchDepth":15,"depth":15,"links":226},[],[228,231],{"label":229,"href":230},"Backend","https:\u002F\u002Fgithub.com\u002Fe-reitbauer\u002Fcastl3d-backend",{"label":232,"href":233},"Frontend","https:\u002F\u002Fgithub.com\u002Fe-reitbauer\u002Fcastl3d-frontend",{},3,"\u002Fprojects\u002Fcastl3d",{"title":219,"description":224},[28,239,80,240],"Spring","React","projects\u002Fcastl3d","Chess against bots you can write yourself.","TVCNVAwVyngQvDcb2lx49puPRS_q_48POpmUO3V5Zio",{"id":245,"title":246,"badge":9,"body":247,"built":9,"description":14,"extension":17,"links":251,"meta":254,"navigation":23,"order":235,"path":255,"seo":256,"stack":257,"stats":9,"stem":260,"tagline":261,"tier":33,"visuals":9,"why":9,"__hash__":262},"projects\u002Fprojects\u002Fcontent-automation.md","Content Automation",{"type":11,"value":248,"toc":249},[],{"title":14,"searchDepth":15,"depth":15,"links":250},[],[252],{"label":20,"href":253},"https:\u002F\u002Fgithub.com\u002Fe-reitbauer\u002Fcontent-automation",{},"\u002Fprojects\u002Fcontent-automation",{"title":246,"description":14},[28,53,258,259],"ffmpeg","Whisper","projects\u002Fcontent-automation","Generates short videos with text to speech and automatic subtitles.","7eu0SA808dSSfEBgsj6eSbniAUaoR5vl0B0hxmqvnnw",{"id":264,"title":265,"badge":9,"body":266,"built":273,"description":270,"extension":17,"links":276,"meta":281,"navigation":23,"order":235,"path":282,"seo":283,"stack":284,"stats":288,"stem":301,"tagline":302,"tier":99,"visuals":303,"why":322,"__hash__":323},"projects\u002Fprojects\u002Fforkcast.md","Forkcast",{"type":11,"value":267,"toc":271},[268],[41,269,270],{},"Recipes come from the Spoonacular API. Portions scale ingredient amounts, identical ingredients are summed across the week, and anything already at home can be ticked off.",{"title":14,"searchDepth":15,"depth":15,"links":272},[],{"problem":274,"solution":275},"A week of recipes lists the same ingredient many times over, in amounts for different numbers of people.","The shopping list is generated from the weekly plan: amounts are scaled to the portions of each meal, identical ingredients are merged and summed across the week, and anything already at home can be ticked off or reduced.",[277,279],{"label":132,"href":278},"https:\u002F\u002Fe-reitbauer.github.io\u002Fforkcast\u002F",{"label":20,"href":280},"https:\u002F\u002Fgithub.com\u002Fe-reitbauer\u002Fforkcast",{},"\u002Fprojects\u002Fforkcast",{"title":265,"description":270},[146,81,285,80,286,287],"Pinia","Express","SQLite",{"asOf":86,"source":289,"items":290},"https:\u002F\u002Fgithub.com\u002Fe-reitbauer\u002Fforkcast\u002Fgraphs\u002Fcontributors",[291,293,295,298],{"label":89,"value":292},"473",{"label":92,"value":294},"196",{"label":296,"value":297},"people","4",{"label":299,"value":300},"languages","9","projects\u002Fforkcast","Meal planning with a drag and drop week and a shopping list that writes itself.",[304,306],{"kind":102,"label":103,"diagram":305},"forkcast",{"kind":167,"label":307,"images":308},"Screenshots",[309,314,318],{"src":310,"alt":311,"width":312,"height":313},"\u002Fimg\u002Fforkcast-schedule.webp","Forkcast weekly schedule with recipes placed on days",1400,779,{"src":315,"alt":316,"width":312,"height":317},"\u002Fimg\u002Fforkcast-dashboard.webp","Forkcast dashboard",778,{"src":319,"alt":320,"width":312,"height":321},"\u002Fimg\u002Fforkcast-shopping.webp","Forkcast generated shopping list",770,"A team product with real interface work. Drag and drop planning, ingredient lists merged across recipes, friends, and nine languages including right to left.","fELTkL0iiyiWW-ag-tZXeEJqw3hq3LtfNhPYp2arFaw",{"id":325,"title":326,"badge":9,"body":327,"built":531,"description":14,"extension":17,"links":534,"meta":540,"navigation":23,"order":383,"path":541,"seo":542,"stack":543,"stats":546,"stem":555,"tagline":556,"tier":99,"visuals":557,"why":560,"__hash__":561},"projects\u002Fprojects\u002Fbackbone.md","Backbone",{"type":11,"value":328,"toc":529},[329,525],[330,331,335],"pre",{"className":332,"code":333,"language":334,"meta":14,"style":14},"language-kotlin shiki shiki-themes everforest-light everforest-dark","lifecycle {\n    \u002F\u002F survives script reloads\n    var counter by sustained(0)\n\n    onLoad {\n        println(\"Script loaded. Counter: $counter\")\n    }\n\n    listener\u003CTickEvent> {\n        counter++\n        if (counter % 20 == 0) {\n            Backbone.PLUGIN.server.onlinePlayers\n                .forEach { it.sendMessage(\"Count: $counter\") }\n        }\n    }\n}\n","kotlin",[116,336,337,349,355,381,387,395,415,421,426,442,451,475,481,508,514,519],{"__ignoreMap":14},[338,339,341,345],"span",{"class":340,"line":24},"line",[338,342,344],{"class":343},"s4IWU","lifecycle",[338,346,348],{"class":347},"sXf0S"," {\n",[338,350,351],{"class":340,"line":15},[338,352,354],{"class":353},"saOx9","    \u002F\u002F survives script reloads\n",[338,356,357,361,364,368,371,374,378],{"class":340,"line":235},[338,358,360],{"class":359},"spUxw","    var",[338,362,363],{"class":347}," counter ",[338,365,367],{"class":366},"sOk1_","by",[338,369,370],{"class":343}," sustained",[338,372,373],{"class":347},"(",[338,375,377],{"class":376},"sc47v","0",[338,379,380],{"class":347},")\n",[338,382,384],{"class":340,"line":383},4,[338,385,386],{"emptyLinePlaceholder":23},"\n",[338,388,390,393],{"class":340,"line":389},5,[338,391,392],{"class":343},"    onLoad",[338,394,348],{"class":347},[338,396,398,401,403,407,410,413],{"class":340,"line":397},6,[338,399,400],{"class":343},"        println",[338,402,373],{"class":347},[338,404,406],{"class":405},"spy5Z","\"Script loaded. Counter: ",[338,408,409],{"class":347},"$counter",[338,411,412],{"class":405},"\"",[338,414,380],{"class":347},[338,416,418],{"class":340,"line":417},7,[338,419,420],{"class":347},"    }\n",[338,422,424],{"class":340,"line":423},8,[338,425,386],{"emptyLinePlaceholder":23},[338,427,429,432,435,439],{"class":340,"line":428},9,[338,430,431],{"class":343},"    listener",[338,433,434],{"class":347},"\u003C",[338,436,438],{"class":437},"sUZPV","TickEvent",[338,440,441],{"class":347},"> {\n",[338,443,445,448],{"class":340,"line":444},10,[338,446,447],{"class":347},"        counter",[338,449,450],{"class":366},"++\n",[338,452,454,457,460,463,466,469,472],{"class":340,"line":453},11,[338,455,456],{"class":359},"        if",[338,458,459],{"class":347}," (counter ",[338,461,462],{"class":366},"%",[338,464,465],{"class":376}," 20",[338,467,468],{"class":366}," ==",[338,470,471],{"class":376}," 0",[338,473,474],{"class":347},") {\n",[338,476,478],{"class":340,"line":477},12,[338,479,480],{"class":347},"            Backbone.PLUGIN.server.onlinePlayers\n",[338,482,484,487,490,493,496,498,501,503,505],{"class":340,"line":483},13,[338,485,486],{"class":347},"                .",[338,488,489],{"class":343},"forEach",[338,491,492],{"class":347}," { it.",[338,494,495],{"class":343},"sendMessage",[338,497,373],{"class":347},[338,499,500],{"class":405},"\"Count: ",[338,502,409],{"class":347},[338,504,412],{"class":405},[338,506,507],{"class":347},") }\n",[338,509,511],{"class":340,"line":510},14,[338,512,513],{"class":347},"        }\n",[338,515,517],{"class":340,"line":516},15,[338,518,420],{"class":347},[338,520,522],{"class":340,"line":521},16,[338,523,524],{"class":347},"}\n",[526,527,528],"style",{},"html pre.shiki code .s4IWU, html code.shiki .s4IWU{--shiki-default:#8DA101;--shiki-dark:#A7C080}html pre.shiki code .sXf0S, html code.shiki .sXf0S{--shiki-default:#5C6A72;--shiki-dark:#D3C6AA}html pre.shiki code .saOx9, html code.shiki .saOx9{--shiki-default:#939F91;--shiki-default-font-style:italic;--shiki-dark:#859289;--shiki-dark-font-style:italic}html pre.shiki code .spUxw, html code.shiki .spUxw{--shiki-default:#F85552;--shiki-dark:#E67E80}html pre.shiki code .sOk1_, html code.shiki .sOk1_{--shiki-default:#F57D26;--shiki-dark:#E69875}html pre.shiki code .sc47v, html code.shiki .sc47v{--shiki-default:#DF69BA;--shiki-dark:#D699B6}html pre.shiki code .spy5Z, html code.shiki .spy5Z{--shiki-default:#DFA000;--shiki-dark:#DBBC7F}html pre.shiki code .sUZPV, html code.shiki .sUZPV{--shiki-default:#3A94C5;--shiki-dark:#7FBBB3}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":14,"searchDepth":15,"depth":15,"links":530},[],{"problem":532,"solution":533},"Every change to server logic meant restarting the Minecraft server.","Logic lives in Kotlin scripts that are compiled and reloaded in place with \u002Fbb scripting reload. Properties declared as sustained keep their value across reloads, so a script picks up where it left off.",[535,537],{"label":20,"href":536},"https:\u002F\u002Fgithub.com\u002Fintegr-dev\u002Fbackbone",{"label":538,"href":539},"Modrinth","https:\u002F\u002Fmodrinth.com\u002Fplugin\u002Fbackbone-lib",{},"\u002Fprojects\u002Fbackbone",{"title":326,"description":14},[28,544,29,545,287],"Kotlin Scripting","Spigot",{"asOf":86,"source":539,"items":547},[548,550,552],{"label":89,"value":549},"118",{"label":158,"value":551},"6",{"label":553,"value":554},"downloads","123","projects\u002Fbackbone","A framework for Spigot servers with Kotlin scripts you can reload while the server runs.",[558],{"kind":116,"label":559},"Script","Change server logic without a restart. Scripts get their own event bus, commands, inventory GUIs and storage, and reload in place.","Xm2hW_8_hD7UhpEfxhbQaMJ9dQODsMUrHlB3eXMTnSw",{"id":563,"title":564,"badge":565,"body":569,"built":576,"description":573,"extension":17,"links":579,"meta":583,"navigation":23,"order":389,"path":584,"seo":585,"stack":586,"stats":589,"stem":598,"tagline":599,"tier":99,"visuals":600,"why":670,"__hash__":671},"projects\u002Fprojects\u002Fhelix.md","Helix",{"value":566,"label":567,"href":568},"1,400+","downloads on Modrinth","https:\u002F\u002Fmodrinth.com\u002Fmod\u002Fhelix",{"type":11,"value":570,"toc":574},[571],[41,572,573],{},"Free and open source. Themes, accent colours and a set of small features that make the game nicer to play.",{"title":14,"searchDepth":15,"depth":15,"links":575},[],{"problem":577,"solution":578},"Server owners need a way to switch off modules they don't allow, without players changing their install.","The server sends a plugin message on the helix:config channel with a JSON list of module ids; Helix disables those modules until the player rejoins. Invalid JSON and unknown ids are ignored.",[580,582],{"label":20,"href":581},"https:\u002F\u002Fgithub.com\u002Fintegr-dev\u002Fhelix",{"label":538,"href":568},{},"\u002Fprojects\u002Fhelix",{"title":564,"description":573},[28,587,588],"Java","Fabric",{"asOf":86,"source":568,"items":590},[591,593,596],{"label":553,"value":592},"1,454",{"label":594,"value":595},"followers","16",{"label":89,"value":597},"25","projects\u002Fhelix","A quality of life mod for Fabric.",[601,639],{"kind":602,"label":603,"chart":604},"chart","Downloads",{"title":605,"note":606,"source":607,"bars":608},"Downloads per release","10 releases between 14 Apr and 31 May 2024, Fabric, Minecraft 1.20.4 and 1.20.5","https:\u002F\u002Fmodrinth.com\u002Fmod\u002Fhelix\u002Fversions",[609,612,615,618,621,624,627,630,633,636],{"label":610,"value":611},"1.2.1",155,{"label":613,"value":614},"1.2.2",78,{"label":616,"value":617},"1.2.3",92,{"label":619,"value":620},"1.2.4",81,{"label":622,"value":623},"1.2.5",242,{"label":625,"value":626},"1.2.6",66,{"label":628,"value":629},"1.2.7",96,{"label":631,"value":632},"1.2.8",82,{"label":634,"value":635},"1.2.9",255,{"label":637,"value":638},"1.3.0",307,{"kind":167,"label":307,"images":640},[641,646,651,656,660,665],{"src":642,"alt":643,"width":644,"height":645},"\u002Fimg\u002Fhelix-menu.webp","Helix main menu",1264,502,{"src":647,"alt":648,"width":649,"height":650},"\u002Fimg\u002Fhelix.webp","Helix settings menu in game",515,301,{"src":652,"alt":653,"width":654,"height":655},"\u002Fimg\u002Fhelix-config-2.webp","Helix module config screen",473,505,{"src":657,"alt":658,"width":659,"height":635},"\u002Fimg\u002Fhelix-ui.webp","Helix interface elements",602,{"src":661,"alt":662,"width":663,"height":664},"\u002Fimg\u002Fhelix-hotbar.webp","Helix custom hotbar",452,138,{"src":666,"alt":667,"width":668,"height":669},"\u002Fimg\u002Fhelix-discord.webp","Helix Discord presence",306,103,"Shipped to real players and still downloaded.","_j9aEqOE_6H2Y3Qr1h9QGH1tOGncCBIR09O8R4q1_S0",[673,857],{"id":674,"title":675,"body":676,"date":86,"description":846,"draft":847,"extension":17,"meta":848,"navigation":23,"path":849,"seo":850,"stem":851,"summary":852,"tags":853,"__hash__":856},"posts\u002Fposts\u002F2026-09-27-backbone-hot-reload.md","Changing a Minecraft server without restarting it",{"type":11,"value":677,"toc":841},[678,691,696,699,787,793,797,804,808,832,839],[41,679,680,681,686,687,690],{},"Developing plugins for a Spigot server usually means the same loop: change code, build a jar, restart the server, rejoin, test. ",[682,683,326],"a",{"href":536,"rel":684},[685],"nofollow"," removes the restart. Server logic lives in Kotlin scripts (",[116,688,689],{},".bb.kts",") that are compiled and reloaded while the server keeps running.",[692,693,695],"h2",{"id":694},"one-lifecycle-per-script","One lifecycle per script",[41,697,698],{},"Every script declares what happens when it loads and which events it listens to:",[330,700,702],{"className":332,"code":701,"language":334,"meta":14,"style":14},"lifecycle {\n    \u002F\u002F 'sustained' properties persist across script reloads\n    var counter by sustained(0)\n\n    onLoad {\n        println(\"Script loaded. Counter: $counter\")\n    }\n\n    listener\u003CTickEvent> {\n        counter++\n    }\n}\n",[116,703,704,710,715,731,735,741,755,759,763,773,779,783],{"__ignoreMap":14},[338,705,706,708],{"class":340,"line":24},[338,707,344],{"class":343},[338,709,348],{"class":347},[338,711,712],{"class":340,"line":15},[338,713,714],{"class":353},"    \u002F\u002F 'sustained' properties persist across script reloads\n",[338,716,717,719,721,723,725,727,729],{"class":340,"line":235},[338,718,360],{"class":359},[338,720,363],{"class":347},[338,722,367],{"class":366},[338,724,370],{"class":343},[338,726,373],{"class":347},[338,728,377],{"class":376},[338,730,380],{"class":347},[338,732,733],{"class":340,"line":383},[338,734,386],{"emptyLinePlaceholder":23},[338,736,737,739],{"class":340,"line":389},[338,738,392],{"class":343},[338,740,348],{"class":347},[338,742,743,745,747,749,751,753],{"class":340,"line":397},[338,744,400],{"class":343},[338,746,373],{"class":347},[338,748,406],{"class":405},[338,750,409],{"class":347},[338,752,412],{"class":405},[338,754,380],{"class":347},[338,756,757],{"class":340,"line":417},[338,758,420],{"class":347},[338,760,761],{"class":340,"line":423},[338,762,386],{"emptyLinePlaceholder":23},[338,764,765,767,769,771],{"class":340,"line":428},[338,766,431],{"class":343},[338,768,434],{"class":347},[338,770,438],{"class":437},[338,772,441],{"class":347},[338,774,775,777],{"class":340,"line":444},[338,776,447],{"class":347},[338,778,450],{"class":366},[338,780,781],{"class":340,"line":453},[338,782,420],{"class":347},[338,784,785],{"class":340,"line":477},[338,786,524],{"class":347},[41,788,789,792],{},[116,790,791],{},"\u002Fbb scripting reload"," swaps in the new version of every script without touching the rest of the server.",[692,794,796],{"id":795},"keeping-state-across-reloads","Keeping state across reloads",[41,798,799,800,803],{},"Reloading would be much less useful if every counter, cache or cooldown reset each time. Properties declared with ",[116,801,802],{},"sustained(...)"," keep their value when the script is reloaded, so you can change behaviour while the state stays where it was.",[692,805,807],{"id":806},"more-than-single-files","More than single files",[809,810,811,819,826,829],"ul",{},[812,813,814,815,818],"li",{},"Scripts can pull Maven dependencies with ",[116,816,817],{},"@DependsOn",".",[812,820,821,822,825],{},"Shared code goes into utility scripts (",[116,823,824],{},".bbu.kts",") that other scripts import.",[812,827,828],{},"Scripts define commands, build inventory GUIs and talk to each other through inter-script messaging, and all of it is hot-reloadable.",[812,830,831],{},"Around that sit a custom event bus, SQLite backed storage, typed config files, custom items and entities.",[41,833,834,835,838],{},"Backbone is on ",[682,836,538],{"href":539,"rel":837},[685]," and runs on Spigot based servers (Spigot, Paper) for Minecraft 1.21.11 and Java 17 or newer.",[526,840,528],{},{"title":14,"searchDepth":15,"depth":15,"links":842},[843,844,845],{"id":694,"depth":15,"text":695},{"id":795,"depth":15,"text":796},{"id":806,"depth":15,"text":807},"Developing plugins for a Spigot server usually means the same loop: change code, build a jar, restart the server, rejoin, test. Backbone removes the restart. Server logic lives in Kotlin scripts (.bb.kts) that are compiled and reloaded while the server keeps running.",false,{},"\u002Fposts\u002F2026-09-27-backbone-hot-reload",{"title":675,"description":846},"posts\u002F2026-09-27-backbone-hot-reload","Backbone lets server logic live in Kotlin scripts that reload while the server keeps running. How the lifecycle DSL keeps state across reloads.",[854,334,855],"backbone","minecraft","6u8pkKJJkPY2sHfec1dF5QpOCDK9oEp8NtDURVnmzhY",{"id":858,"title":859,"body":860,"date":86,"description":864,"draft":847,"extension":17,"meta":941,"navigation":23,"path":942,"seo":943,"stem":944,"summary":945,"tags":946,"__hash__":949},"posts\u002Fposts\u002F2026-09-27-osmium-credentials.md","Why Osmium never holds a Minecraft login",{"type":11,"value":861,"toc":936},[862,865,869,875,882,886,894,898,926,929],[41,863,864],{},"Osmium coordinates a fleet of headless Minecraft agents that build one large schematic together. The obvious design would store each account's login in the backend and let the server start agents on demand. I went the other way, and it ended up shaping most of the system.",[692,866,868],{"id":867},"the-rule","The rule",[41,870,871],{},[872,873,874],"strong",{},"Osmium never holds Minecraft credentials, and never performs the login.",[41,876,877,878,881],{},"When an agent should come online, the backend sends its host a ",[116,879,880],{},"setup_agent"," command. The host logs the account in by whatever means it prefers and reports back only the resulting username and UUID. The credentials stay on the machine that runs the host.",[692,883,885],{"id":884},"what-it-buys","What it buys",[41,887,888,889,893],{},"A full dump of the Osmium database reveals ",[890,891,892],"em",{},"which"," accounts you run, but not the ability to run them. The backend simply has nothing that could log an account in.",[692,895,897],{"id":896},"what-it-costs-and-what-followed-from-it","What it costs, and what followed from it",[809,899,900,906,920],{},[812,901,902,905],{},[872,903,904],{},"Hosts dial out."," The backend cannot start anything by itself, so hosts connect to it over a WebSocket and wait for commands, instead of the backend connecting to them.",[812,907,908,911,912,915,916,919],{},[872,909,910],{},"Unknown is not offline."," If a host stops answering, the backend has no way of checking the account itself. An agent on an unreachable host is shown as ",[890,913,914],{},"unknown",", not ",[890,917,918],{},"offline",", because that is all the backend actually knows.",[812,921,922,925],{},[872,923,924],{},"Agents are addressed through their host."," The host that holds an agent is also where its proxies and their credentials live. An operator can route an agent through a proxy by name, and the secret never leaves that machine.",[41,927,928],{},"The same idea keeps coming back while building features: if the backend would need a secret to do something, the host does it instead and reports what happened.",[41,930,931,932,818],{},"The full design lives in the ",[682,933,935],{"href":75,"rel":934},[685],"Osmium repository",{"title":14,"searchDepth":15,"depth":15,"links":937},[938,939,940],{"id":867,"depth":15,"text":868},{"id":884,"depth":15,"text":885},{"id":896,"depth":15,"text":897},{},"\u002Fposts\u002F2026-09-27-osmium-credentials",{"title":859,"description":864},"posts\u002F2026-09-27-osmium-credentials","Osmium runs a fleet of Minecraft agents, but its backend never sees their credentials. That one rule shaped the protocol, the liveness model and how hosts connect.",[104,947,948],"architecture","security","0K9Wh_C2hyCuVWBB4p2BItVlAAlMRlr3XhXbwC5p5Bc",{"id":951,"entries":952,"extension":980,"meta":981,"stem":982,"__hash__":983},"timeline\u002Fen\u002Ftimeline.yml",[953,957,961,965,969,973,976],{"when":954,"title":955,"detail":956},"2021","Started with Java","Object-oriented basics, small projects, first libraries.",{"when":958,"title":959,"detail":960},"2023","Switched to Kotlin","Has been my main language since.",{"when":962,"title":963,"detail":964},"2024","Spring and Vue","Backends in Spring, frontends in Vue. First published mod, Helix.",{"when":966,"title":967,"detail":968},"07\u002F2025 – 08\u002F2025","Internship, Cloudflight Austria GmbH","Mobile app for employees, built with Kotlin Multiplatform.",{"when":970,"title":971,"detail":972},"2026","Backbone, Clay, Granum, Osmium","Server framework, docs toolchain, Claude Code memory, agent orchestration.",{"when":974,"title":967,"detail":975},"07\u002F2026 – 08\u002F2026","Android app for last mile management, Kotlin and Jetpack Compose.",{"when":977,"title":978,"detail":979},"next","Next up","Whatever turns out to be interesting.","yml",{},"en\u002Ftimeline","mi8ZJXsJzmN-ZU1WhUQGrGYilMxaxIvwZ8Q-BrhKCs0",{"id":985,"categories":986,"extension":980,"meta":1161,"stem":1162,"__hash__":1163},"skills\u002Fen\u002Fskills.yml",[987,1021,1043,1095,1138],{"category":988,"items":989},"Languages",[990,993,996,1000,1003,1006,1010,1014,1017],{"name":28,"favorite":23,"what":991,"rating":389,"why":992},"A modern language for the JVM and more, by JetBrains; concise and null-safe.","I rate it 5\u002F5 because: it is my personal favourite, with null safety, clean and compact code, a rich standard library, and the whole Java ecosystem behind it.",{"name":587,"what":994,"rating":389,"why":995},"The classic JVM language behind much of enterprise software, and Minecraft.","I rate it 5\u002F5 because: it is where I started, and it is versatile, with a library for almost everything.",{"name":997,"what":998,"rating":15,"why":999},"JavaScript","The language of the web browser, and of servers through Node.js.","I rate it 2\u002F5 because: as the language of the web, there is no way around it, but its quirks are famous for a reason.",{"name":80,"what":1001,"rating":235,"why":1002},"JavaScript with static types, checked before the code runs.","I rate it 3\u002F5 because: the types make it a lot better than plain JavaScript, but underneath it is still JavaScript.",{"name":147,"what":1004,"rating":383,"why":1005},"Google's small, fast compiled language for servers and command-line tools.","I rate it 4\u002F5 because: it compiles to native code while being easier than C or Rust and safer than C.",{"name":1007,"what":1008,"rating":235,"why":1009},"C","The low-level systems language, close to the hardware.","I rate it 3\u002F5 because: it is unsafe, but knowing how things work this close to the hardware is a must.",{"name":1011,"what":1012,"rating":235,"why":1013},"C#","Microsoft's language for .NET: apps, games and services.","I rate it 3\u002F5 because: while it is not my personal favourite, there is nothing wrong with it and its ecosystem is good.",{"name":53,"what":1015,"rating":235,"why":1016},"A readable scripting language for automation, data work and AI.","I rate it 3\u002F5 because: it is great for prototyping and machine learning, but I don't like its syntax.",{"name":1018,"what":1019,"rating":383,"why":1020},"Shell","Command-line scripts (Bash, zsh) that glue tools together.","I rate it 4\u002F5 because: it is a must-have; with Bash and Linux everywhere, it pretty much explains itself.",{"category":1022,"items":1023},"Databases",[1024,1028,1032,1035,1039],{"name":1025,"what":1026,"rating":383,"why":1027},"Oracle","Oracle Database, a large commercial SQL database common in companies.","I rate it 4\u002F5 because: it is solid, has been around for a long time, and is used a lot in business.",{"name":1029,"what":1030,"rating":235,"why":1031},"MySQL","A widespread open-source SQL database.","I rate it 3\u002F5 because: it is fair, but I haven't used it much and it doesn't stand out.",{"name":287,"what":1033,"rating":383,"why":1034},"A whole SQL database in a single file, built into the app.","I rate it 4\u002F5 because: it is great for storage on the device, even more so with tools like Room on Android.",{"name":1036,"what":1037,"rating":235,"why":1038},"MongoDB","A document database: stores JSON-like records instead of tables.","I rate it 3\u002F5 because: it is good for unstructured data and has its use cases.",{"name":1040,"favorite":23,"what":1041,"rating":389,"why":1042},"Postgres","PostgreSQL, a powerful open-source SQL database.","I rate it 5\u002F5 because: it is my favourite right now, versatile and widely used.",{"category":1044,"items":1045},"Frameworks",[1046,1050,1054,1058,1061,1064,1068,1071,1074,1078,1082,1086,1089,1092],{"name":1047,"what":1048,"rating":389,"why":1049},"Kotlin Multiplatform","Shares Kotlin code between Android, iOS, desktop and the web.","I rate it 5\u002F5 because: it is awesome tech, and I got to use it during my internship.",{"name":1051,"favorite":23,"what":1052,"rating":389,"why":1053},"Android Jetpack","Google's libraries for Android apps, including Jetpack Compose for the UI.","I rate it 5\u002F5 because: it is my favourite way to develop for mobile, it works great with Compose, and its APIs are easy to use.",{"name":1055,"what":1056,"rating":235,"why":1057},"JavaFX","A toolkit for desktop user interfaces in Java.","I rate it 3\u002F5 because: it is fine for simpler UI apps, but I don't really enjoy working with it.",{"name":81,"favorite":23,"what":1059,"rating":389,"why":1060},"A JavaScript framework for building web interfaces from components.","I rate it 5\u002F5 because: it is my personal favourite for web development, with a really nice syntax.",{"name":146,"what":1062,"rating":389,"why":1063},"Vue plus routing, server rendering and static sites. This site is built with it.","I rate it 5\u002F5 because: it makes Vue even better, with lots of utilities and far less boilerplate.",{"name":1065,"what":1066,"rating":383,"why":1067},"Tailwind CSS","Styles web pages with small utility classes right in the markup.","I rate it 4\u002F5 because: it does a lot of the heavy lifting, but falls short on some of the more complex CSS.",{"name":240,"what":1069,"rating":235,"why":1070},"Meta's library for building user interfaces from components.","I rate it 3\u002F5 because: it was my first JavaScript framework and it is widely used with many libraries, but it doesn't stand out to me.",{"name":82,"favorite":23,"what":1072,"rating":389,"why":1073},"The standard framework for Java and Kotlin backends and web services.","I rate it 5\u002F5 because: it is my favourite backend framework, with a huge ecosystem and so, so many libraries and starters.",{"name":1075,"what":1076,"rating":389,"why":1077},"Spring Security","Login, tokens and access rules for Spring applications.","I rate it 5\u002F5 because: it makes Spring even better, which pretty much says why I like it.",{"name":1079,"what":1080,"rating":389,"why":1081},"JPA \u002F Hibernate","Maps database tables to Java and Kotlin objects.","I rate it 5\u002F5 because: it is a great mapper that saves you a lot of SQL headaches, especially together with Spring.",{"name":1083,"what":1084,"rating":383,"why":1085},"Quarkus","A fast-starting Java framework made for containers and the cloud.","I rate it 4\u002F5 because: it has nice native builds and works well with Docker, though I am more at home in the Spring ecosystem.",{"name":286,"what":1087,"rating":15,"why":1088},"A minimal web server framework for Node.js.","I rate it 2\u002F5 because: a server in JavaScript has one use for me, prototyping; I would never pick it for a big app.",{"name":588,"favorite":23,"what":1090,"rating":389,"why":1091},"A toolchain for Minecraft mods, which change the game itself.","I rate it 5\u002F5 because: it is my favourite Minecraft mod loader, and I especially like Loom and its mappings.",{"name":545,"what":1093,"rating":383,"why":1094},"A Minecraft server with a plugin API for adding features to servers.","I rate it 4\u002F5 because: the API is nice, but it does too much for you and lacks easy lower-level access.",{"category":1096,"items":1097},"Tools & DevOps",[1098,1102,1106,1110,1114,1118,1122,1126,1130,1134],{"name":1099,"what":1100,"rating":389,"why":1101},"Git","Version control: keeps track of every change to the code.","I rate it 5\u002F5 because: it explains itself; if you don't know Git, what are you doing?",{"name":1103,"what":1104,"rating":383,"why":1105},"GitHub","Hosts Git repositories, with issues and pull requests for working together.","I rate it 4\u002F5 because: it is a good free Git host with lots of integrations, though I don't like the AI features pushed onto you.",{"name":1107,"what":1108,"rating":389,"why":1109},"GitHub Actions","Runs builds, tests and deployments automatically on GitHub.","I rate it 5\u002F5 because: it gives you really nice pipelines that are easy to set up.",{"name":1111,"what":1112,"rating":389,"why":1113},"Docker","Packs an app with everything it needs into a container that runs anywhere.","I rate it 5\u002F5 because: it makes deployment so easy.",{"name":1115,"what":1116,"rating":235,"why":1117},"Kubernetes","Runs and scales many containers across servers.","I rate it 3\u002F5 because: it is nice for big apps, but more than most of my projects need.",{"name":1119,"what":1120,"rating":389,"why":1121},"Vite","A fast build tool and dev server for web projects.","I rate it 5\u002F5 because: it does lots of things right, and I use it every time.",{"name":1123,"favorite":23,"what":1124,"rating":389,"why":1125},"Gradle","The build tool for Java and Kotlin projects, configured in code.","I rate it 5\u002F5 because: it is my favourite build system and very flexible.",{"name":1127,"what":1128,"rating":383,"why":1129},"Maven","The long-standing build and dependency tool for Java.","I rate it 4\u002F5 because: it is a good build system, but not as flexible as Gradle, which I prefer.",{"name":1131,"what":1132,"rating":235,"why":1133},"Flyway","Versioned database migrations that run with the app.","I rate it 3\u002F5 because: it makes versioning a database easy, but I haven't used it enough to rate it higher yet.",{"name":1135,"what":1136,"rating":389,"why":1137},"Swagger","Describes and documents web APIs (OpenAPI) and lets you try them out.","I rate it 5\u002F5 because: it is a must-have for any medium to large API.",{"category":1139,"items":1140},"Testing",[1141,1145,1149,1153,1157],{"name":1142,"what":1143,"rating":389,"why":1144},"Jest","A test runner for JavaScript and TypeScript.","I rate it 5\u002F5 because: I like its syntax for writing tests, and I have used it a lot for testing JavaScript and TypeScript code.",{"name":1146,"what":1147,"rating":389,"why":1148},"JUnit","The standard testing framework for Java and Kotlin.","I rate it 5\u002F5 because: it is an awesome framework for Java and the industry standard, and it does lots of things right.",{"name":1150,"what":1151,"rating":383,"why":1152},"xUnit","xUnit.net, the common testing framework for C# and .NET.","I rate it 4\u002F5 because: it is good and a lot like JUnit, but I don't like its split into facts and theories.",{"name":1154,"what":1155,"rating":389,"why":1156},"Playwright","Drives real browsers to test web apps end to end.","I rate it 5\u002F5 because: it is great for UI tests, and it has some nice uses with AI now too.",{"name":1158,"what":1159,"rating":383,"why":1160},"Selenium","Browser automation, long used for testing websites.","I rate it 4\u002F5 because: it does much the same job as Playwright, but I like Playwright more.",{},"en\u002Fskills","9XV856H8KI5wLlkxWkKmLrfuTJ0AiufZp3a4asZZdOw",{"id":1165,"birth":1166,"cvNote":1168,"email":1169,"extension":980,"fullName":1170,"handle":1171,"links":1172,"location":1183,"lookingFor":1184,"meta":1185,"name":1186,"pitch":1187,"role":1188,"stem":1189,"__hash__":1190},"profile\u002Fen\u002Fprofile.yml",{"year":1167,"month":389},2009,"CV available on request.","hello@integr.cc","Erik Reitbauer","integr",[1173,1177,1180],{"label":1174,"href":1175,"icon":1176},"integr-dev","https:\u002F\u002Fgithub.com\u002Fintegr-dev","github",{"label":1178,"href":1179,"icon":1176},"e-reitbauer","https:\u002F\u002Fgithub.com\u002Fe-reitbauer",{"label":538,"href":1181,"icon":1182},"https:\u002F\u002Fmodrinth.com\u002Fuser\u002Fintegr","cube","Austria","Open to internships and developer jobs.",{},"Erik","I write software, mostly in Kotlin, and publish most of it as open source. Servers, tools, libraries, and the odd experiment.","Software developer","en\u002Fprofile","4yashhgPFQD_waybwFRK8izbd-MLrwLclRpoBZg0q9g",{"projects":1192,"posts":1578,"timeline":1776,"skills":1802,"profile":1947},[1193,1204,1218,1243,1281,1292,1306,1321,1332,1367,1522],{"id":7,"title":8,"badge":9,"body":1194,"built":9,"description":14,"extension":17,"links":1198,"meta":1200,"navigation":23,"order":24,"path":25,"seo":1201,"stack":1202,"stats":9,"stem":31,"tagline":1203,"tier":33,"why":9,"__hash__":34},{"type":11,"value":1195,"toc":1196},[],{"title":14,"searchDepth":15,"depth":15,"links":1197},[],[1199],{"label":20,"href":21},{},{"title":8,"description":14},[28,29,30],"Socket-Transport mit Binär-Codec, kotlinx.serialization und Coroutines.",{"id":36,"title":37,"badge":9,"body":1205,"built":9,"description":43,"extension":17,"links":1212,"meta":1214,"navigation":23,"order":24,"path":50,"seo":1215,"stack":1216,"stats":9,"stem":56,"tagline":1217,"tier":58,"why":9,"__hash__":59},{"type":11,"value":1206,"toc":1210},[1207],[41,1208,1209],{},"Speichert Entscheidungen, Vorlieben und Einschränkungen als typisierte Abschnitte, findet sie über Ähnlichkeit plus Graphsuche wieder und trennt das Gedächtnis pro Git-Branch.",{"title":14,"searchDepth":15,"depth":15,"links":1211},[],[1213],{"label":20,"href":48},{},{"title":37,"description":43},[53,54,55],"Dauerhaftes Gedächtnis für Claude Code, gestützt auf eine lokale Vektor- und Graphdatenbank.",{"id":61,"title":62,"badge":9,"body":1219,"built":1226,"description":67,"extension":17,"links":1229,"meta":1231,"navigation":23,"order":24,"path":77,"seo":1232,"stack":1233,"stats":1234,"stem":97,"tagline":1239,"tier":99,"visuals":1240,"why":1242,"__hash__":106},{"type":11,"value":1220,"toc":1224},[1221],[41,1222,1223],{},"Agenten melden sich über einen Host-Prozess an, gehen oder fliegen zu ihrem Segment und setzen es Lage für Lage. Das Dashboard zeigt Live-3D-Ansichten, eine gemeinsame Karte, die die Agenten beim Bewegen erkunden, Inventare, Telemetrie und ein Audit-Log. Die Konfiguration liegt zentral und wird Hosts bei jeder Neuverbindung erneut übergeben.",{"title":14,"searchDepth":15,"depth":15,"links":1225},[],{"problem":1227,"solution":1228},"Ein Abzug der Datenbank darf nie reichen, um die Minecraft-Accounts der Flotte zu übernehmen.","Osmium hält die Zugangsdaten nie und meldet sich nie selbst an. Das Backend schickt einem Host nur einen Setup-Befehl; der Host meldet den Account auf einem Rechner an, den sein Besitzer kontrolliert, und schickt nur Benutzernamen und UUID zurück. Hosts verbinden sich von sich aus zum Backend, statt angesprochen zu werden, und ist ein Host nicht erreichbar, gilt der Zustand seiner Agenten als unbekannt statt offline.",[1230],{"label":20,"href":75},{},{"title":62,"description":67},[80,28,81,82,83,84],{"asOf":86,"source":75,"items":1235},[1236,1237,1238],{"label":89,"value":90},{"label":92,"value":93},{"label":95,"value":96},"Steuert eine Flotte von Minecraft-Agenten ohne Oberfläche, die gemeinsam eine große Schematic bauen.",[1241],{"kind":102,"label":103,"diagram":104},"Mein bisher größtes System. Eine Person lädt eine Schematic hoch, Osmium teilt sie in Segmente, gibt jedem Agenten seinen Teil, und ein Web-Dashboard verfolgt jeden Agenten live.",{"id":108,"title":109,"badge":9,"body":1244,"built":1257,"description":129,"extension":17,"links":1260,"meta":1265,"navigation":23,"order":15,"path":143,"seo":1266,"stack":1267,"stats":1268,"stem":160,"tagline":1273,"tier":99,"visuals":1274,"why":1280,"__hash__":176},{"type":11,"value":1245,"toc":1255},[1246],[41,1247,1248,1249,1251,1252,1254],{},"Die Dokumentation liegt als einfaches Markdown in ",[116,1250,118],{},". Clay Oven durchsucht sie, schreibt die Navigationsstruktur und bündelt sie mit einem fertig gebauten Clay-Frontend. Eine ",[116,1253,122],{}," legt Titel, Navigationsleiste, Sprachen und Startseite fest.",{"title":14,"searchDepth":15,"depth":15,"links":1256},[],{"problem":1258,"solution":1259},"Die meisten Doku-Tools verlangen, dass ein Projekt einen Static Site Generator und dessen Build übernimmt.","Das Clay-Frontend kommt fertig gebaut und liest zur Laufzeit alles aus zwei Dateien: clay.yaml, von Hand geschrieben, und clay-structure.yaml, die Clay Oven, ein Go-CLI, beim Durchsuchen von docs\u002F erzeugt. Ein Repository bekommt nur Markdown und eine Konfigurationsdatei dazu.",[1261,1262,1263,1264],{"label":132,"href":133},{"label":109,"href":135},{"label":137,"href":138},{"label":140,"href":141},{},{"title":109,"description":129},[81,146,80,147,148],{"asOf":86,"source":150,"items":1269},[1270,1271,1272],{"label":153,"value":154},{"label":89,"value":156},{"label":158,"value":159},"Ein Dokumentations-Framework, das sich in ein bestehendes Repository einfügt.",[1275,1276],{"kind":102,"label":164,"diagram":165},{"kind":167,"label":168,"images":1277},[1278],{"src":171,"alt":1279,"width":173,"height":174},"Die Clay-Beispieldoku mit der Seite Advanced Features, Seitenleiste und hervorgehobenem Code","Eine komplette Toolchain, die ich unter einer eigenen Organisation entworfen habe und pflege. Ein Frontend mit Vue und Nuxt plus ein Go-CLI, das aus einem Ordner voller Markdown eine fertige Website macht.",{"id":178,"title":179,"badge":9,"body":1282,"built":9,"description":14,"extension":17,"links":1286,"meta":1288,"navigation":23,"order":15,"path":188,"seo":1289,"stack":1290,"stats":9,"stem":191,"tagline":1291,"tier":33,"why":9,"__hash__":193},{"type":11,"value":1283,"toc":1284},[],{"title":14,"searchDepth":15,"depth":15,"links":1285},[],[1287],{"label":20,"href":186},{},{"title":179,"description":14},[28],"Eine kleine Bibliothek zum Parsen von JSON.",{"id":195,"title":196,"badge":9,"body":1293,"built":9,"description":201,"extension":17,"links":1300,"meta":1302,"navigation":23,"order":15,"path":208,"seo":1303,"stack":1304,"stats":9,"stem":214,"tagline":1305,"tier":58,"why":9,"__hash__":216},{"type":11,"value":1294,"toc":1298},[1295],[41,1296,1297],{},"Überall Option Leertaste drücken, tippen, und die Datei öffnet sich an der passenden Zeile. Die Suche auf dieser Seite funktioniert genauso.",{"title":14,"searchDepth":15,"depth":15,"links":1299},[],[1301],{"label":20,"href":206},{},{"title":196,"description":201},[211,212,213],"Eine Suchleiste für macOS. Wie grep, nur für Menschen.",{"id":218,"title":219,"badge":9,"body":1307,"built":9,"description":224,"extension":17,"links":1314,"meta":1317,"navigation":23,"order":235,"path":236,"seo":1318,"stack":1319,"stats":9,"stem":241,"tagline":1320,"tier":58,"why":9,"__hash__":243},{"type":11,"value":1308,"toc":1312},[1309],[41,1310,1311],{},"Züge werden für die Geschwindigkeit im Client geprüft und noch einmal auf dem Server. Bots laufen im Backend hinter einer gemeinsamen Schnittstelle.",{"title":14,"searchDepth":15,"depth":15,"links":1313},[],[1315,1316],{"label":229,"href":230},{"label":232,"href":233},{},{"title":219,"description":224},[28,239,80,240],"Schach gegen Bots, die man selbst schreiben kann.",{"id":245,"title":246,"badge":9,"body":1322,"built":9,"description":14,"extension":17,"links":1326,"meta":1328,"navigation":23,"order":235,"path":255,"seo":1329,"stack":1330,"stats":9,"stem":260,"tagline":1331,"tier":33,"why":9,"__hash__":262},{"type":11,"value":1323,"toc":1324},[],{"title":14,"searchDepth":15,"depth":15,"links":1325},[],[1327],{"label":20,"href":253},{},{"title":246,"description":14},[28,53,258,259],"Erzeugt kurze Videos mit Sprachausgabe und automatischen Untertiteln.",{"id":264,"title":265,"badge":9,"body":1333,"built":1340,"description":270,"extension":17,"links":1343,"meta":1346,"navigation":23,"order":235,"path":282,"seo":1347,"stack":1348,"stats":1349,"stem":301,"tagline":1355,"tier":99,"visuals":1356,"why":1366,"__hash__":323},{"type":11,"value":1334,"toc":1338},[1335],[41,1336,1337],{},"Die Rezepte kommen von der Spoonacular-API. Portionen rechnen die Zutatenmengen um, gleiche Zutaten werden über die Woche summiert, und was schon zu Hause ist, lässt sich abhaken.",{"title":14,"searchDepth":15,"depth":15,"links":1339},[],{"problem":1341,"solution":1342},"Eine Woche voller Rezepte listet dieselbe Zutat immer wieder, in Mengen für unterschiedlich viele Personen.","Die Einkaufsliste entsteht aus dem Wochenplan: Mengen werden auf die Portionen jeder Mahlzeit umgerechnet, gleiche Zutaten über die Woche zusammengeführt und summiert, und was schon zu Hause ist, lässt sich abhaken oder reduzieren.",[1344,1345],{"label":132,"href":278},{"label":20,"href":280},{},{"title":265,"description":270},[146,81,285,80,286,287],{"asOf":86,"source":289,"items":1350},[1351,1352,1353,1354],{"label":89,"value":292},{"label":92,"value":294},{"label":296,"value":297},{"label":299,"value":300},"Essensplanung mit einer Woche per Drag and Drop und einer Einkaufsliste, die sich selbst schreibt.",[1357,1358],{"kind":102,"label":103,"diagram":305},{"kind":167,"label":307,"images":1359},[1360,1362,1364],{"src":310,"alt":1361,"width":312,"height":313},"Forkcast-Wochenplan mit Rezepten an den einzelnen Tagen",{"src":315,"alt":1363,"width":312,"height":317},"Forkcast-Dashboard",{"src":319,"alt":1365,"width":312,"height":321},"Von Forkcast erzeugte Einkaufsliste","Ein Teamprodukt mit echter Oberflächenarbeit. Planen per Drag and Drop, Zutatenlisten über Rezepte hinweg zusammengeführt, Freunde und neun Sprachen, auch von rechts nach links.",{"id":325,"title":326,"badge":9,"body":1368,"built":1504,"description":14,"extension":17,"links":1507,"meta":1510,"navigation":23,"order":383,"path":541,"seo":1511,"stack":1512,"stats":1513,"stem":555,"tagline":1518,"tier":99,"visuals":1519,"why":1521,"__hash__":561},{"type":11,"value":1369,"toc":1502},[1370,1500],[330,1371,1372],{"className":332,"code":333,"language":334,"meta":14,"style":14},[116,1373,1374,1380,1384,1400,1404,1410,1424,1428,1432,1442,1448,1464,1468,1488,1492,1496],{"__ignoreMap":14},[338,1375,1376,1378],{"class":340,"line":24},[338,1377,344],{"class":343},[338,1379,348],{"class":347},[338,1381,1382],{"class":340,"line":15},[338,1383,354],{"class":353},[338,1385,1386,1388,1390,1392,1394,1396,1398],{"class":340,"line":235},[338,1387,360],{"class":359},[338,1389,363],{"class":347},[338,1391,367],{"class":366},[338,1393,370],{"class":343},[338,1395,373],{"class":347},[338,1397,377],{"class":376},[338,1399,380],{"class":347},[338,1401,1402],{"class":340,"line":383},[338,1403,386],{"emptyLinePlaceholder":23},[338,1405,1406,1408],{"class":340,"line":389},[338,1407,392],{"class":343},[338,1409,348],{"class":347},[338,1411,1412,1414,1416,1418,1420,1422],{"class":340,"line":397},[338,1413,400],{"class":343},[338,1415,373],{"class":347},[338,1417,406],{"class":405},[338,1419,409],{"class":347},[338,1421,412],{"class":405},[338,1423,380],{"class":347},[338,1425,1426],{"class":340,"line":417},[338,1427,420],{"class":347},[338,1429,1430],{"class":340,"line":423},[338,1431,386],{"emptyLinePlaceholder":23},[338,1433,1434,1436,1438,1440],{"class":340,"line":428},[338,1435,431],{"class":343},[338,1437,434],{"class":347},[338,1439,438],{"class":437},[338,1441,441],{"class":347},[338,1443,1444,1446],{"class":340,"line":444},[338,1445,447],{"class":347},[338,1447,450],{"class":366},[338,1449,1450,1452,1454,1456,1458,1460,1462],{"class":340,"line":453},[338,1451,456],{"class":359},[338,1453,459],{"class":347},[338,1455,462],{"class":366},[338,1457,465],{"class":376},[338,1459,468],{"class":366},[338,1461,471],{"class":376},[338,1463,474],{"class":347},[338,1465,1466],{"class":340,"line":477},[338,1467,480],{"class":347},[338,1469,1470,1472,1474,1476,1478,1480,1482,1484,1486],{"class":340,"line":483},[338,1471,486],{"class":347},[338,1473,489],{"class":343},[338,1475,492],{"class":347},[338,1477,495],{"class":343},[338,1479,373],{"class":347},[338,1481,500],{"class":405},[338,1483,409],{"class":347},[338,1485,412],{"class":405},[338,1487,507],{"class":347},[338,1489,1490],{"class":340,"line":510},[338,1491,513],{"class":347},[338,1493,1494],{"class":340,"line":516},[338,1495,420],{"class":347},[338,1497,1498],{"class":340,"line":521},[338,1499,524],{"class":347},[526,1501,528],{},{"title":14,"searchDepth":15,"depth":15,"links":1503},[],{"problem":1505,"solution":1506},"Jede Änderung an der Serverlogik bedeutete einen Neustart des Minecraft-Servers.","Die Logik steckt in Kotlin-Skripten, die mit \u002Fbb scripting reload an Ort und Stelle neu kompiliert und geladen werden. Als sustained deklarierte Eigenschaften behalten ihren Wert über das Neuladen hinweg, sodass ein Skript dort weitermacht, wo es war.",[1508,1509],{"label":20,"href":536},{"label":538,"href":539},{},{"title":326,"description":14},[28,544,29,545,287],{"asOf":86,"source":539,"items":1514},[1515,1516,1517],{"label":89,"value":549},{"label":158,"value":551},{"label":553,"value":554},"Ein Framework für Spigot-Server mit Kotlin-Skripten, die sich im laufenden Betrieb neu laden lassen.",[1520],{"kind":116,"label":559},"Serverlogik ändern ohne Neustart. Skripte bekommen ihren eigenen Event-Bus, Befehle, Inventar-Oberflächen und Speicher und werden an Ort und Stelle neu geladen.",{"id":563,"title":564,"badge":1523,"body":1525,"built":1532,"description":573,"extension":17,"links":1535,"meta":1538,"navigation":23,"order":389,"path":584,"seo":1539,"stack":1540,"stats":1541,"stem":598,"tagline":1546,"tier":99,"visuals":1547,"why":1577,"__hash__":671},{"value":566,"label":1524,"href":568},"Downloads auf Modrinth",{"type":11,"value":1526,"toc":1530},[1527],[41,1528,1529],{},"Kostenlos und Open Source. Themes, Akzentfarben und eine Reihe kleiner Funktionen, die das Spiel angenehmer machen.",{"title":14,"searchDepth":15,"depth":15,"links":1531},[],{"problem":1533,"solution":1534},"Serverbetreiber brauchen einen Weg, Module abzuschalten, die sie nicht erlauben, ohne dass Spieler ihre Installation ändern.","Der Server schickt eine Plugin-Nachricht auf dem Kanal helix:config mit einer JSON-Liste von Modul-IDs; Helix schaltet diese Module ab, bis der Spieler neu beitritt. Ungültiges JSON und unbekannte IDs werden ignoriert.",[1536,1537],{"label":20,"href":581},{"label":538,"href":568},{},{"title":564,"description":573},[28,587,588],{"asOf":86,"source":568,"items":1542},[1543,1544,1545],{"label":553,"value":592},{"label":594,"value":595},{"label":89,"value":597},"Ein Quality-of-Life-Mod für Fabric.",[1548,1563],{"kind":602,"label":603,"chart":1549},{"title":1550,"note":1551,"source":607,"bars":1552},"Downloads pro Release","10 Releases zwischen 14. Apr. und 31. Mai 2024, Fabric, Minecraft 1.20.4 und 1.20.5",[1553,1554,1555,1556,1557,1558,1559,1560,1561,1562],{"label":610,"value":611},{"label":613,"value":614},{"label":616,"value":617},{"label":619,"value":620},{"label":622,"value":623},{"label":625,"value":626},{"label":628,"value":629},{"label":631,"value":632},{"label":634,"value":635},{"label":637,"value":638},{"kind":167,"label":307,"images":1564},[1565,1567,1569,1571,1573,1575],{"src":642,"alt":1566,"width":644,"height":645},"Helix-Hauptmenü",{"src":647,"alt":1568,"width":649,"height":650},"Helix-Einstellungen im Spiel",{"src":652,"alt":1570,"width":654,"height":655},"Helix-Modulkonfiguration",{"src":657,"alt":1572,"width":659,"height":635},"Helix-Oberflächenelemente",{"src":661,"alt":1574,"width":663,"height":664},"Helix-Hotbar",{"src":666,"alt":1576,"width":668,"height":669},"Helix-Präsenz in Discord","An echte Spieler ausgeliefert und wird noch immer heruntergeladen.",[1579,1720],{"id":674,"title":675,"body":1580,"date":86,"description":846,"draft":847,"extension":17,"meta":1717,"navigation":23,"path":849,"seo":1718,"stem":851,"summary":852,"tags":1719,"__hash__":856},{"type":11,"value":1581,"toc":1712},[1582,1589,1591,1593,1679,1683,1685,1689,1691,1705,1710],[41,1583,680,1584,686,1587,690],{},[682,1585,326],{"href":536,"rel":1586},[685],[116,1588,689],{},[692,1590,695],{"id":694},[41,1592,698],{},[330,1594,1595],{"className":332,"code":701,"language":334,"meta":14,"style":14},[116,1596,1597,1603,1607,1623,1627,1633,1647,1651,1655,1665,1671,1675],{"__ignoreMap":14},[338,1598,1599,1601],{"class":340,"line":24},[338,1600,344],{"class":343},[338,1602,348],{"class":347},[338,1604,1605],{"class":340,"line":15},[338,1606,714],{"class":353},[338,1608,1609,1611,1613,1615,1617,1619,1621],{"class":340,"line":235},[338,1610,360],{"class":359},[338,1612,363],{"class":347},[338,1614,367],{"class":366},[338,1616,370],{"class":343},[338,1618,373],{"class":347},[338,1620,377],{"class":376},[338,1622,380],{"class":347},[338,1624,1625],{"class":340,"line":383},[338,1626,386],{"emptyLinePlaceholder":23},[338,1628,1629,1631],{"class":340,"line":389},[338,1630,392],{"class":343},[338,1632,348],{"class":347},[338,1634,1635,1637,1639,1641,1643,1645],{"class":340,"line":397},[338,1636,400],{"class":343},[338,1638,373],{"class":347},[338,1640,406],{"class":405},[338,1642,409],{"class":347},[338,1644,412],{"class":405},[338,1646,380],{"class":347},[338,1648,1649],{"class":340,"line":417},[338,1650,420],{"class":347},[338,1652,1653],{"class":340,"line":423},[338,1654,386],{"emptyLinePlaceholder":23},[338,1656,1657,1659,1661,1663],{"class":340,"line":428},[338,1658,431],{"class":343},[338,1660,434],{"class":347},[338,1662,438],{"class":437},[338,1664,441],{"class":347},[338,1666,1667,1669],{"class":340,"line":444},[338,1668,447],{"class":347},[338,1670,450],{"class":366},[338,1672,1673],{"class":340,"line":453},[338,1674,420],{"class":347},[338,1676,1677],{"class":340,"line":477},[338,1678,524],{"class":347},[41,1680,1681,792],{},[116,1682,791],{},[692,1684,796],{"id":795},[41,1686,799,1687,803],{},[116,1688,802],{},[692,1690,807],{"id":806},[809,1692,1693,1697,1701,1703],{},[812,1694,814,1695,818],{},[116,1696,817],{},[812,1698,821,1699,825],{},[116,1700,824],{},[812,1702,828],{},[812,1704,831],{},[41,1706,834,1707,838],{},[682,1708,538],{"href":539,"rel":1709},[685],[526,1711,528],{},{"title":14,"searchDepth":15,"depth":15,"links":1713},[1714,1715,1716],{"id":694,"depth":15,"text":695},{"id":795,"depth":15,"text":796},{"id":806,"depth":15,"text":807},{},{"title":675,"description":846},[854,334,855],{"id":858,"title":859,"body":1721,"date":86,"description":864,"draft":847,"extension":17,"meta":1773,"navigation":23,"path":942,"seo":1774,"stem":944,"summary":945,"tags":1775,"__hash__":949},{"type":11,"value":1722,"toc":1768},[1723,1725,1727,1731,1735,1737,1741,1743,1761,1763],[41,1724,864],{},[692,1726,868],{"id":867},[41,1728,1729],{},[872,1730,874],{},[41,1732,877,1733,881],{},[116,1734,880],{},[692,1736,885],{"id":884},[41,1738,888,1739,893],{},[890,1740,892],{},[692,1742,897],{"id":896},[809,1744,1745,1749,1757],{},[812,1746,1747,905],{},[872,1748,904],{},[812,1750,1751,911,1753,915,1755,919],{},[872,1752,910],{},[890,1754,914],{},[890,1756,918],{},[812,1758,1759,925],{},[872,1760,924],{},[41,1762,928],{},[41,1764,931,1765,818],{},[682,1766,935],{"href":75,"rel":1767},[685],{"title":14,"searchDepth":15,"depth":15,"links":1769},[1770,1771,1772],{"id":867,"depth":15,"text":868},{"id":884,"depth":15,"text":885},{"id":896,"depth":15,"text":897},{},{"title":859,"description":864},[104,947,948],{"id":1777,"entries":1778,"extension":980,"meta":1799,"stem":1800,"__hash__":1801},"timeline_de\u002Fde\u002Ftimeline.yml",[1779,1782,1785,1788,1791,1793,1795],{"when":954,"title":1780,"detail":1781},"Einstieg mit Java","Grundlagen der Objektorientierung, kleine Projekte, erste Bibliotheken.",{"when":958,"title":1783,"detail":1784},"Wechsel zu Kotlin","Seitdem meine Hauptsprache.",{"when":962,"title":1786,"detail":1787},"Spring und Vue","Backends mit Spring, Frontends mit Vue. Erster veröffentlichter Mod, Helix.",{"when":966,"title":1789,"detail":1790},"Praktikum, Cloudflight Austria GmbH","Mobile App für Mitarbeitende, gebaut mit Kotlin Multiplatform.",{"when":970,"title":971,"detail":1792},"Server-Framework, Doku-Toolchain, Gedächtnis für Claude Code, Agenten-Orchestrierung.",{"when":974,"title":1789,"detail":1794},"Android-App für Last-Mile-Management, Kotlin und Jetpack Compose.",{"when":1796,"title":1797,"detail":1798},"als Nächstes","Was kommt","Was auch immer sich als spannend herausstellt.",{},"de\u002Ftimeline","wMYeO9301yyIssXBCjk1b3a-amPOyKNFbA8JWf_vhDY",{"id":985,"categories":1803,"extension":980,"meta":1946,"stem":1162,"__hash__":1163},[1804,1834,1852,1896,1928],{"category":1805,"items":1806},"Sprachen",[1807,1810,1813,1816,1819,1822,1825,1828,1831],{"name":28,"favorite":23,"what":1808,"rating":389,"why":1809},"Moderne Sprache von JetBrains für die JVM und mehr, knapp und null-sicher.","Ich bewerte es mit 5\u002F5, weil: Kotlin ist mein persönlicher Favorit, mit Null-Sicherheit, sauberer und kompakter Code, eine umfangreiche Standardbibliothek und das ganze Java-Ökosystem dahinter.",{"name":587,"what":1811,"rating":389,"why":1812},"Die klassische JVM-Sprache hinter viel Unternehmenssoftware und Minecraft.","Ich bewerte es mit 5\u002F5, weil: Mit Java habe ich angefangen, und es ist vielseitig, mit einer Bibliothek für fast alles.",{"name":997,"what":1814,"rating":15,"why":1815},"Die Sprache des Webbrowsers, über Node.js auch auf Servern.","Ich bewerte es mit 2\u002F5, weil: Als Sprache des Webs kommt man nicht an JavaScript vorbei, aber seine Eigenheiten sind nicht umsonst berüchtigt.",{"name":80,"what":1817,"rating":235,"why":1818},"JavaScript mit statischen Typen, die vor dem Ausführen geprüft werden.","Ich bewerte es mit 3\u002F5, weil: Die Typen machen es deutlich besser als reines JavaScript, aber darunter steckt immer noch JavaScript.",{"name":147,"what":1820,"rating":383,"why":1821},"Googles kleine, schnelle kompilierte Sprache für Server und Kommandozeilen-Tools.","Ich bewerte es mit 4\u002F5, weil: Go kompiliert zu nativem Code und ist dabei einfacher als C oder Rust und sicherer als C.",{"name":1007,"what":1823,"rating":235,"why":1824},"Die hardwarenahe Systemsprache.","Ich bewerte es mit 3\u002F5, weil: C ist zwar unsicher, aber man muss wissen, wie es so nah an der Hardware zugeht.",{"name":1011,"what":1826,"rating":235,"why":1827},"Microsofts Sprache für .NET: Apps, Spiele und Dienste.","Ich bewerte es mit 3\u002F5, weil: C# ist zwar nicht mein Favorit, aber es spricht nichts dagegen, und das Ökosystem ist gut.",{"name":53,"what":1829,"rating":235,"why":1830},"Gut lesbare Skriptsprache für Automatisierung, Daten und KI.","Ich bewerte es mit 3\u002F5, weil: Python ist super für Prototypen und Machine Learning, aber die Syntax mag ich nicht.",{"name":1018,"what":1832,"rating":383,"why":1833},"Kommandozeilen-Skripte (Bash, zsh), die Werkzeuge verbinden.","Ich bewerte es mit 4\u002F5, weil: Sie ist ein Muss; mit Bash und Linux überall erklärt sich das fast von selbst.",{"category":1835,"items":1836},"Datenbanken",[1837,1840,1843,1846,1849],{"name":1025,"what":1838,"rating":383,"why":1839},"Oracle Database, eine große kommerzielle SQL-Datenbank, verbreitet in Unternehmen.","Ich bewerte es mit 4\u002F5, weil: Oracle ist solide, gibt es schon lange und wird in Unternehmen oft eingesetzt.",{"name":1029,"what":1841,"rating":235,"why":1842},"Weit verbreitete Open-Source-SQL-Datenbank.","Ich bewerte es mit 3\u002F5, weil: MySQL ist in Ordnung, aber ich habe es wenig genutzt, und es sticht nicht heraus.",{"name":287,"what":1844,"rating":383,"why":1845},"Eine komplette SQL-Datenbank in einer Datei, direkt in der Anwendung.","Ich bewerte es mit 4\u002F5, weil: SQLite ist super für Speicher direkt auf dem Gerät, besonders mit Tools wie Room auf Android.",{"name":1036,"what":1847,"rating":235,"why":1848},"Dokumentendatenbank: speichert JSON-ähnliche Einträge statt Tabellen.","Ich bewerte es mit 3\u002F5, weil: MongoDB ist gut für unstrukturierte Daten und hat seine Einsatzzwecke.",{"name":1040,"favorite":23,"what":1850,"rating":389,"why":1851},"PostgreSQL, eine leistungsfähige Open-Source-SQL-Datenbank.","Ich bewerte es mit 5\u002F5, weil: Postgres ist gerade mein Favorit, vielseitig und weit verbreitet.",{"category":1044,"items":1853},[1854,1857,1860,1863,1866,1869,1872,1875,1878,1881,1884,1887,1890,1893],{"name":1047,"what":1855,"rating":389,"why":1856},"Teilt Kotlin-Code zwischen Android, iOS, Desktop und Web.","Ich bewerte es mit 5\u002F5, weil: Es ist eine großartige Technologie, die ich in meinem Praktikum einsetzen durfte.",{"name":1051,"favorite":23,"what":1858,"rating":389,"why":1859},"Googles Bibliotheken für Android-Apps, samt Jetpack Compose für die Oberfläche.","Ich bewerte es mit 5\u002F5, weil: Es ist meine liebste Art, für Mobilgeräte zu entwickeln, es passt super zu Compose, und die APIs sind einfach zu nutzen.",{"name":1055,"what":1861,"rating":235,"why":1862},"Toolkit für Desktop-Oberflächen in Java.","Ich bewerte es mit 3\u002F5, weil: JavaFX ist für einfachere UI-Apps gut, aber ich arbeite nicht wirklich gern damit.",{"name":81,"favorite":23,"what":1864,"rating":389,"why":1865},"JavaScript-Framework für Weboberflächen aus Komponenten.","Ich bewerte es mit 5\u002F5, weil: Vue ist mein persönlicher Favorit für Webentwicklung, mit einer richtig schönen Syntax.",{"name":146,"what":1867,"rating":389,"why":1868},"Vue mit Routing, Server-Rendering und statischen Seiten. Diese Seite ist damit gebaut.","Ich bewerte es mit 5\u002F5, weil: Nuxt macht Vue noch besser, mit vielen Hilfsmitteln und deutlich weniger Boilerplate.",{"name":1065,"what":1870,"rating":383,"why":1871},"Gestaltet Webseiten mit kleinen Utility-Klassen direkt im Markup.","Ich bewerte es mit 4\u002F5, weil: Tailwind nimmt viel Arbeit ab, stößt bei komplexerem CSS aber an Grenzen.",{"name":240,"what":1873,"rating":235,"why":1874},"Metas Bibliothek für Benutzeroberflächen aus Komponenten.","Ich bewerte es mit 3\u002F5, weil: React war mein erstes JavaScript-Framework und ist mit vielen Bibliotheken weit verbreitet, sticht für mich aber nicht heraus.",{"name":82,"favorite":23,"what":1876,"rating":389,"why":1877},"Das Standard-Framework für Java- und Kotlin-Backends und Webdienste.","Ich bewerte es mit 5\u002F5, weil: Spring Boot ist mein liebstes Backend-Framework, mit einem riesigen Ökosystem und unglaublich vielen Bibliotheken und Startern.",{"name":1075,"what":1879,"rating":389,"why":1880},"Anmeldung, Tokens und Zugriffsregeln für Spring-Anwendungen.","Ich bewerte es mit 5\u002F5, weil: Es macht Spring noch besser, und das sagt eigentlich schon alles.",{"name":1079,"what":1882,"rating":389,"why":1883},"Bildet Datenbanktabellen auf Java- und Kotlin-Objekte ab.","Ich bewerte es mit 5\u002F5, weil: Es ist ein toller Mapper, der einem viel SQL-Kopfweh erspart, besonders zusammen mit Spring.",{"name":1083,"what":1885,"rating":383,"why":1886},"Schnell startendes Java-Framework für Container und die Cloud.","Ich bewerte es mit 4\u002F5, weil: Quarkus hat schöne native Builds und spielt gut mit Docker zusammen, aber im Spring-Ökosystem bin ich mehr zu Hause.",{"name":286,"what":1888,"rating":15,"why":1889},"Schlankes Webserver-Framework für Node.js.","Ich bewerte es mit 2\u002F5, weil: Ein Server in JavaScript hat für mich nur einen Zweck, Prototypen; für eine große Anwendung würde ich es nie wählen.",{"name":588,"favorite":23,"what":1891,"rating":389,"why":1892},"Werkzeugkette für Minecraft-Mods, die das Spiel selbst verändern.","Ich bewerte es mit 5\u002F5, weil: Fabric ist mein liebster Minecraft-Modloader, und besonders Loom und seine Mappings mag ich.",{"name":545,"what":1894,"rating":383,"why":1895},"Minecraft-Server mit Plugin-Schnittstelle, um Servern Funktionen hinzuzufügen.","Ich bewerte es mit 4\u002F5, weil: Die API ist schön, aber sie nimmt zu viel ab, und einfacher Low-Level-Zugriff fehlt.",{"category":1096,"items":1897},[1898,1901,1904,1907,1910,1913,1916,1919,1922,1925],{"name":1099,"what":1899,"rating":389,"why":1900},"Versionsverwaltung: hält jede Änderung am Code fest.","Ich bewerte es mit 5\u002F5, weil: Es erklärt sich von selbst; wer Git nicht kennt, was macht der eigentlich?",{"name":1103,"what":1902,"rating":383,"why":1903},"Hostet Git-Repositories, mit Issues und Pull Requests zur Zusammenarbeit.","Ich bewerte es mit 4\u002F5, weil: GitHub ist ein guter kostenloser Git-Host mit vielen Integrationen, aber die aufgedrängten KI-Funktionen mag ich nicht.",{"name":1107,"what":1905,"rating":389,"why":1906},"Führt Builds, Tests und Deployments automatisch auf GitHub aus.","Ich bewerte es mit 5\u002F5, weil: Man bekommt damit richtig schöne Pipelines, die leicht einzurichten sind.",{"name":1111,"what":1908,"rating":389,"why":1909},"Packt eine Anwendung samt allem, was sie braucht, in einen Container, der überall läuft.","Ich bewerte es mit 5\u002F5, weil: Docker macht das Deployment so einfach.",{"name":1115,"what":1911,"rating":235,"why":1912},"Betreibt und skaliert viele Container über mehrere Server.","Ich bewerte es mit 3\u002F5, weil: Kubernetes ist für große Anwendungen toll, für die meisten meiner Projekte aber mehr als nötig.",{"name":1119,"what":1914,"rating":389,"why":1915},"Schnelles Build-Tool und Entwicklungsserver für Webprojekte.","Ich bewerte es mit 5\u002F5, weil: Vite macht vieles richtig, und ich verwende es jedes Mal.",{"name":1123,"favorite":23,"what":1917,"rating":389,"why":1918},"Build-Tool für Java- und Kotlin-Projekte, in Code konfiguriert.","Ich bewerte es mit 5\u002F5, weil: Gradle ist mein liebstes Build-System und sehr flexibel.",{"name":1127,"what":1920,"rating":383,"why":1921},"Das bewährte Build- und Abhängigkeitswerkzeug für Java.","Ich bewerte es mit 4\u002F5, weil: Maven ist ein gutes Build-System, aber nicht so flexibel wie Gradle, das ich bevorzuge.",{"name":1131,"what":1923,"rating":235,"why":1924},"Versionierte Datenbank-Migrationen, die mit der Anwendung laufen.","Ich bewerte es mit 3\u002F5, weil: Flyway macht das Versionieren einer Datenbank einfach, aber ich habe es noch zu wenig genutzt, um es höher zu bewerten.",{"name":1135,"what":1926,"rating":389,"why":1927},"Beschreibt und dokumentiert Web-APIs (OpenAPI) und lässt sie ausprobieren.","Ich bewerte es mit 5\u002F5, weil: Swagger ist für jede mittlere bis große API ein Muss.",{"category":1929,"items":1930},"Tests",[1931,1934,1937,1940,1943],{"name":1142,"what":1932,"rating":389,"why":1933},"Test-Runner für JavaScript und TypeScript.","Ich bewerte es mit 5\u002F5, weil: Ich mag die Syntax zum Schreiben von Tests und habe Jest oft zum Testen von JavaScript- und TypeScript-Code verwendet.",{"name":1146,"what":1935,"rating":389,"why":1936},"Das Standard-Test-Framework für Java und Kotlin.","Ich bewerte es mit 5\u002F5, weil: JUnit ist ein großartiges Framework für Java, der Industriestandard, und macht vieles richtig.",{"name":1150,"what":1938,"rating":383,"why":1939},"xUnit.net, das gängige Test-Framework für C# und .NET.","Ich bewerte es mit 4\u002F5, weil: xUnit ist gut und JUnit sehr ähnlich, aber die Aufteilung in Facts und Theories mag ich nicht.",{"name":1154,"what":1941,"rating":389,"why":1942},"Steuert echte Browser, um Webanwendungen durchgehend zu testen.","Ich bewerte es mit 5\u002F5, weil: Playwright ist super für UI-Tests und hat inzwischen auch schöne Einsatzmöglichkeiten mit KI.",{"name":1158,"what":1944,"rating":383,"why":1945},"Browser-Automatisierung, seit Langem zum Testen von Websites genutzt.","Ich bewerte es mit 4\u002F5, weil: Selenium macht im Grunde dasselbe wie Playwright, aber Playwright gefällt mir besser.",{},{"id":1165,"birth":1948,"cvNote":1949,"email":1169,"extension":980,"fullName":1170,"handle":1171,"links":1950,"location":1954,"lookingFor":1955,"meta":1956,"name":1186,"pitch":1957,"role":1958,"stem":1189,"__hash__":1190},{"year":1167,"month":389},"Lebenslauf auf Anfrage.",[1951,1952,1953],{"label":1174,"href":1175,"icon":1176},{"label":1178,"href":1179,"icon":1176},{"label":538,"href":1181,"icon":1182},"Österreich","Offen für Praktika und Jobs als Entwickler neben der Schule.",{},"Ich schreibe Software, meistens in Kotlin, und veröffentliche das meiste davon als Open Source. Server, Tools, Bibliotheken und das eine oder andere Experiment.","Softwareentwickler",{"id":1960,"title":62,"body":1961,"description":1965,"extension":17,"meta":2295,"navigation":23,"path":2296,"seo":2297,"stem":2298,"__hash__":2299},"readmes\u002Freadmes\u002Fosmium.md",{"type":11,"value":1962,"toc":2290},[1963,1966,1969,1973,2084,2088,2092,2101,2107,2117,2121,2134,2259,2262,2287],[41,1964,1965],{},"Orchestration for a fleet of Minecraft agents that build a large schematic together. An operator uploads a schematic, picks the agents to work it, and Osmium splits it into segments and hands each agent its own slice. The dashboard shows what the fleet is doing: blocks left, throughput, the traffic every host moves, what needs attention, and what happened.",[41,1967,1968],{},"Agents can be sent anywhere by clicking the map or the 3D view. They walk there, or fly where the server allows it, and build what they are given one course at a time: stairs the right way round, slabs on the right half, doors hinged on the side they were drawn on.",[692,1970,1972],{"id":1971},"modules","Modules",[1974,1975,1976,1992],"table",{},[1977,1978,1979],"thead",{},[1980,1981,1982,1986,1989],"tr",{},[1983,1984,1985],"th",{},"Module",[1983,1987,1988],{},"What it is",[1983,1990,1991],{},"State",[1993,1994,1995,2013,2030,2047,2064],"tbody",{},[1980,1996,1997,2007,2010],{},[1998,1999,2000],"td",{},[682,2001,2004],{"href":2002,"rel":2003},"https:\u002F\u002Fgithub.com\u002Fintegr-dev\u002Fosmium\u002Fblob\u002FHEAD\u002Fbackend\u002F",[685],[116,2005,2006],{},"backend\u002F",[1998,2008,2009],{},"Spring Boot 4.1 \u002F Kotlin. Auth, accounts, hosts, agents, schematics, build plans and jobs, and the WebSocket hosts dial into.",[1998,2011,2012],{},"Built, 695 tests",[1980,2014,2015,2024,2027],{},[1998,2016,2017],{},[682,2018,2021],{"href":2019,"rel":2020},"https:\u002F\u002Fgithub.com\u002Fintegr-dev\u002Fosmium\u002Fblob\u002FHEAD\u002Ffrontend\u002F",[685],[116,2022,2023],{},"frontend\u002F",[1998,2025,2026],{},"Vue 3 \u002F Vite SPA. Operator dashboard, the build pipeline, the live world viewer, the charted map and the storage breakdown.",[1998,2028,2029],{},"Built, 665 tests",[1980,2031,2032,2041,2044],{},[1998,2033,2034],{},[682,2035,2038],{"href":2036,"rel":2037},"https:\u002F\u002Fgithub.com\u002Fintegr-dev\u002Fosmium\u002Fblob\u002FHEAD\u002Fhost\u002F",[685],[116,2039,2040],{},"host\u002F",[1998,2042,2043],{},"Runs on a machine you control, holds the Minecraft credentials and the proxies, drives the agents. TypeScript, on mineflayer.",[1998,2045,2046],{},"Connects, plays, walks or flies where it is sent, reports its world, inventory and neighbours, streams what it sees, and builds the pieces it is given, 702 tests",[1980,2048,2049,2058,2061],{},[1998,2050,2051],{},[682,2052,2055],{"href":2053,"rel":2054},"https:\u002F\u002Fgithub.com\u002Fintegr-dev\u002Fosmium\u002Fblob\u002FHEAD\u002Ftestserver\u002F",[685],[116,2056,2057],{},"testserver\u002F",[1998,2059,2060],{},"A Paper server and the rig that builds on it: a schematic made of nothing but the block states that are hard to place, built for real and read back.",[1998,2062,2063],{},"Two scripts; see its README",[1980,2065,2066,2078,2081],{},[1998,2067,2068],{},[682,2069,2072,2074,2075],{"href":2070,"rel":2071},"https:\u002F\u002Fgithub.com\u002Fintegr-dev\u002Fosmium\u002Fblob\u002FHEAD\u002Fhost\u002FREADME.md",[685],[116,2073,2040],{}," → ",[116,2076,2077],{},"osmium-link",[1998,2079,2080],{},"The host's own command line: the accounts it can log in with, and the proxies it can route through.",[1998,2082,2083],{},"Built",[692,2085,2087],{"id":2086},"the-one-idea-worth-knowing","The one idea worth knowing",[41,2089,2090],{},[872,2091,874],{},[41,2093,2094,2095,2097,2098,2100],{},"The backend sends a host a ",[116,2096,880],{}," command; that host logs the account in by whatever means it\nprefers and reports back only the resulting username and UUID. A full database dump therefore\nreveals ",[890,2099,892],{}," accounts you run, not the ability to run them.",[41,2102,2103,2104,2106],{},"That constraint shapes everything else: how agents are addressed, why hosts dial out instead of\nbeing connected to, and why a host being unreachable makes an agent's state ",[890,2105,914],{}," rather than\noffline.",[41,2108,2109,2116],{},[682,2110,2113],{"href":2111,"rel":2112},"https:\u002F\u002Fgithub.com\u002Fintegr-dev\u002Fosmium\u002Fblob\u002FHEAD\u002FFLEET_CONNECTIVITY.md",[685],[116,2114,2115],{},"FLEET_CONNECTIVITY.md"," is the design document, credential custody, the\nwire protocol, liveness, chat, and the alternatives that were rejected and why.",[692,2118,2120],{"id":2119},"running-it-locally","Running it locally",[41,2122,2123,2124,2127,2128,2131,2132,818],{},"Needs ",[872,2125,2126],{},"JDK 25",", ",[872,2129,2130],{},"Node 24"," and ",[872,2133,1111],{},[330,2135,2139],{"className":2136,"code":2137,"language":2138,"meta":14,"style":14},"language-bash shiki shiki-themes everforest-light everforest-dark","# 1. Postgres\ndocker compose -f backend\u002Fdocker-compose.yml up -d\n\n# 2. Backend on :8080\ncd backend && .\u002Fgradlew bootRun          # gradlew.bat on Windows\n\n# 3. Frontend on :5173, proxying \u002Fapi to the backend\ncd frontend && npm install && npm run dev\n\n# 4. Optional: a mock host, once you have registered one and copied its token\ncd backend && OSMIUM_HOST_TOKEN=osm_host_1_… .\u002Fgradlew mockHost\n","bash",[116,2140,2141,2146,2166,2170,2175,2195,2199,2204,2229,2233,2238],{"__ignoreMap":14},[338,2142,2143],{"class":340,"line":24},[338,2144,2145],{"class":353},"# 1. Postgres\n",[338,2147,2148,2151,2154,2157,2160,2163],{"class":340,"line":15},[338,2149,2150],{"class":343},"docker",[338,2152,2153],{"class":405}," compose",[338,2155,2156],{"class":405}," -f",[338,2158,2159],{"class":405}," backend\u002Fdocker-compose.yml",[338,2161,2162],{"class":405}," up",[338,2164,2165],{"class":405}," -d\n",[338,2167,2168],{"class":340,"line":235},[338,2169,386],{"emptyLinePlaceholder":23},[338,2171,2172],{"class":340,"line":383},[338,2173,2174],{"class":353},"# 2. Backend on :8080\n",[338,2176,2177,2180,2183,2186,2189,2192],{"class":340,"line":389},[338,2178,2179],{"class":405},"cd",[338,2181,2182],{"class":405}," backend",[338,2184,2185],{"class":347}," && ",[338,2187,2188],{"class":343},".\u002Fgradlew",[338,2190,2191],{"class":405}," bootRun",[338,2193,2194],{"class":353},"          # gradlew.bat on Windows\n",[338,2196,2197],{"class":340,"line":397},[338,2198,386],{"emptyLinePlaceholder":23},[338,2200,2201],{"class":340,"line":417},[338,2202,2203],{"class":353},"# 3. Frontend on :5173, proxying \u002Fapi to the backend\n",[338,2205,2206,2208,2211,2213,2216,2219,2221,2223,2226],{"class":340,"line":423},[338,2207,2179],{"class":405},[338,2209,2210],{"class":405}," frontend",[338,2212,2185],{"class":347},[338,2214,2215],{"class":343},"npm",[338,2217,2218],{"class":405}," install",[338,2220,2185],{"class":347},[338,2222,2215],{"class":343},[338,2224,2225],{"class":405}," run",[338,2227,2228],{"class":405}," dev\n",[338,2230,2231],{"class":340,"line":428},[338,2232,386],{"emptyLinePlaceholder":23},[338,2234,2235],{"class":340,"line":444},[338,2236,2237],{"class":353},"# 4. Optional: a mock host, once you have registered one and copied its token\n",[338,2239,2240,2242,2244,2247,2250,2253,2256],{"class":340,"line":453},[338,2241,2179],{"class":405},[338,2243,2182],{"class":405},[338,2245,2246],{"class":347}," && OSMIUM_HOST_TOKEN",[338,2248,2249],{"class":366},"=",[338,2251,2252],{"class":405},"osm_host_1_…",[338,2254,2255],{"class":343}," .\u002Fgradlew",[338,2257,2258],{"class":405}," mockHost\n",[41,2260,2261],{},"The mock host speaks the real protocol over the real socket, it connects, reports agents,\ntelemetry and chat, fetches segments and places blocks, so the whole pipeline can be exercised\nwithout a Minecraft account. It is a development convenience, not a stand-in for the host program.",[41,2263,2264,2265,2268,2269,2271,2272,2275,2276,2268,2279,2282,2283,2286],{},"Sign in with ",[116,2266,2267],{},"admin"," \u002F ",[116,2270,2267],{},". Those are development defaults and are seeded only while the ",[116,2273,2274],{},"users","\ntable is empty, override ",[116,2277,2278],{},"OSMIUM_BOOTSTRAP_USERNAME",[116,2280,2281],{},"OSMIUM_BOOTSTRAP_PASSWORD",", and\n",[116,2284,2285],{},"OSMIUM_JWT_SECRET",", before running this anywhere real.",[526,2288,2289],{},"html pre.shiki code .saOx9, html code.shiki .saOx9{--shiki-default:#939F91;--shiki-default-font-style:italic;--shiki-dark:#859289;--shiki-dark-font-style:italic}html pre.shiki code .s4IWU, html code.shiki .s4IWU{--shiki-default:#8DA101;--shiki-dark:#A7C080}html pre.shiki code .spy5Z, html code.shiki .spy5Z{--shiki-default:#DFA000;--shiki-dark:#DBBC7F}html pre.shiki code .sXf0S, html code.shiki .sXf0S{--shiki-default:#5C6A72;--shiki-dark:#D3C6AA}html pre.shiki code .sOk1_, html code.shiki .sOk1_{--shiki-default:#F57D26;--shiki-dark:#E69875}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":14,"searchDepth":15,"depth":15,"links":2291},[2292,2293,2294],{"id":1971,"depth":15,"text":1972},{"id":2086,"depth":15,"text":2087},{"id":2119,"depth":15,"text":2120},{},"\u002Freadmes\u002Fosmium",{"title":62,"description":1965},"readmes\u002Fosmium","oEpHVhFT02ea4b2bUrzOioQaBD8RePO7G4QJl-5Ul7E",{"id":2301,"title":109,"body":2302,"description":2592,"extension":17,"meta":2593,"navigation":23,"path":2594,"seo":2595,"stem":2596,"__hash__":2597},"readmes\u002Freadmes\u002Fclay.md",{"type":11,"value":2303,"toc":2586},[2304,2321,2331,2335,2382,2386,2389,2397,2401,2406,2552,2561,2565,2583],[41,2305,2306,2307,2131,2312,2317,2318,818],{},"A documentation framework for developers, built on ",[682,2308,2311],{"href":2309,"rel":2310},"https:\u002F\u002Fnuxt.com\u002F",[685],"Nuxt.js",[682,2313,2316],{"href":2314,"rel":2315},"https:\u002F\u002Fvuejs.org\u002F",[685],"Vue.js",". Clay provides a structured, auto-generated system for displaying documentation written in ",[872,2319,2320],{},"Markdown",[2322,2323,2324],"blockquote",{},[41,2325,2326,2327,2330],{},"Clay is ",[872,2328,2329],{},"not"," a static site generator. It is a documentation framework that integrates into existing projects with minimal effort.",[692,2332,2334],{"id":2333},"capabilities","Capabilities",[809,2336,2337,2343,2359,2376],{},[812,2338,2339,2340,2342],{},"Auto-generates documentation structure from the contents of the ",[116,2341,118],{}," directory.",[812,2344,2345,2346,2131,2353,818],{},"Modern UI via ",[872,2347,2348],{},[682,2349,2352],{"href":2350,"rel":2351},"https:\u002F\u002Fdaisyui.com\u002F",[685],"daisyUI",[872,2354,2355],{},[682,2356,1065],{"href":2357,"rel":2358},"https:\u002F\u002Ftailwindcss.com\u002F",[685],[812,2360,2361,2362,2369,2370,818],{},"Rich Markdown parsing via ",[872,2363,2364],{},[682,2365,2368],{"href":2366,"rel":2367},"https:\u002F\u002Fmarked.js.org\u002F",[685],"marked.js"," and syntax highlighting via ",[872,2371,2372],{},[682,2373,148],{"href":2374,"rel":2375},"https:\u002F\u002Fshiki.matsu.io\u002F",[685],[812,2377,2378,2379,2381],{},"Customizable through a single ",[116,2380,122],{}," config file.",[692,2383,2385],{"id":2384},"how-it-works","How It Works",[41,2387,2388],{},"The Clay frontend is pre-built and loads everything it needs from a couple of config files, so it drops into any repository with minimal effort.",[330,2390,2395],{"className":2391,"code":2393,"language":2394,"meta":14},[2392],"language-text",".\n├── docs\u002F                    # Documentation directory (Markdown)\n│   ├── my-doc.md\n│   └── my-sub-directory\u002F\n│       └── nested-doc.md\n├── clay.yaml                # Main configuration file\n├── clay-structure.yaml      # Structure file (generated by Clay Oven)\n└── logo.svg                 # Optional logo\n","text",[116,2396,2393],{"__ignoreMap":14},[692,2398,2400],{"id":2399},"configuration","Configuration",[41,2402,2403,2405],{},[116,2404,122],{}," configures the title, navbar, languages, and landing page:",[330,2407,2411],{"className":2408,"code":2409,"language":2410,"meta":14,"style":14},"language-yaml shiki shiki-themes everforest-light everforest-dark","title: \"Demo\"\nfavicon: \"logo.svg\"\nbaseURL: \"\u002F\"\nnavbar:\n  logo: \"logo.svg\"\n  links:\n    - name: \"Homepage\"\n      icon: \"fa-solid fa-house\"\n      link: \"https:\u002F\u002Fexample.com\"\nindex:\n  title: \"Welcome to the Demo\"\n  icon: \"fa-solid fa-rocket\"\nlangs:\n  - \"python\"\n  - \"js\"\n","yaml",[116,2412,2413,2425,2435,2445,2453,2462,2469,2483,2493,2503,2510,2520,2530,2537,2545],{"__ignoreMap":14},[338,2414,2415,2418,2422],{"class":340,"line":24},[338,2416,2417],{"class":366},"title",[338,2419,2421],{"class":2420},"sMKMZ",":",[338,2423,2424],{"class":343}," \"Demo\"\n",[338,2426,2427,2430,2432],{"class":340,"line":15},[338,2428,2429],{"class":366},"favicon",[338,2431,2421],{"class":2420},[338,2433,2434],{"class":343}," \"logo.svg\"\n",[338,2436,2437,2440,2442],{"class":340,"line":235},[338,2438,2439],{"class":366},"baseURL",[338,2441,2421],{"class":2420},[338,2443,2444],{"class":343}," \"\u002F\"\n",[338,2446,2447,2450],{"class":340,"line":383},[338,2448,2449],{"class":366},"navbar",[338,2451,2452],{"class":2420},":\n",[338,2454,2455,2458,2460],{"class":340,"line":389},[338,2456,2457],{"class":366},"  logo",[338,2459,2421],{"class":2420},[338,2461,2434],{"class":343},[338,2463,2464,2467],{"class":340,"line":397},[338,2465,2466],{"class":366},"  links",[338,2468,2452],{"class":2420},[338,2470,2471,2475,2478,2480],{"class":340,"line":417},[338,2472,2474],{"class":2473},"sZsqx","    -",[338,2476,2477],{"class":366}," name",[338,2479,2421],{"class":2420},[338,2481,2482],{"class":343}," \"Homepage\"\n",[338,2484,2485,2488,2490],{"class":340,"line":423},[338,2486,2487],{"class":366},"      icon",[338,2489,2421],{"class":2420},[338,2491,2492],{"class":343}," \"fa-solid fa-house\"\n",[338,2494,2495,2498,2500],{"class":340,"line":428},[338,2496,2497],{"class":366},"      link",[338,2499,2421],{"class":2420},[338,2501,2502],{"class":343}," \"https:\u002F\u002Fexample.com\"\n",[338,2504,2505,2508],{"class":340,"line":444},[338,2506,2507],{"class":366},"index",[338,2509,2452],{"class":2420},[338,2511,2512,2515,2517],{"class":340,"line":453},[338,2513,2514],{"class":366},"  title",[338,2516,2421],{"class":2420},[338,2518,2519],{"class":343}," \"Welcome to the Demo\"\n",[338,2521,2522,2525,2527],{"class":340,"line":477},[338,2523,2524],{"class":366},"  icon",[338,2526,2421],{"class":2420},[338,2528,2529],{"class":343}," \"fa-solid fa-rocket\"\n",[338,2531,2532,2535],{"class":340,"line":483},[338,2533,2534],{"class":366},"langs",[338,2536,2452],{"class":2420},[338,2538,2539,2542],{"class":340,"line":510},[338,2540,2541],{"class":2473},"  -",[338,2543,2544],{"class":343}," \"python\"\n",[338,2546,2547,2549],{"class":340,"line":516},[338,2548,2541],{"class":2473},[338,2550,2551],{"class":343}," \"js\"\n",[41,2553,2554,2557,2558,2560],{},[116,2555,2556],{},"clay-structure.yaml"," defines the navigation tree and is generated automatically by ",[872,2559,137],{},", the companion Go build tool.",[692,2562,2564],{"id":2563},"the-clay-toolchain","The Clay Toolchain",[809,2566,2567,2572,2577],{},[812,2568,2569,2571],{},[872,2570,109],{},", the Vue\u002FNuxt documentation frontend.",[812,2573,2574,2576],{},[872,2575,137],{},", a Go CLI that scans your docs, generates structure files, and bundles them with a Clay distribution into a ready-to-deploy site.",[812,2578,2579,2582],{},[872,2580,2581],{},"Clay Example Repo",", a fully working example project.",[526,2584,2585],{},"html pre.shiki code .sOk1_, html code.shiki .sOk1_{--shiki-default:#F57D26;--shiki-dark:#E69875}html pre.shiki code .sMKMZ, html code.shiki .sMKMZ{--shiki-default:#939F91;--shiki-dark:#859289}html pre.shiki code .s4IWU, html code.shiki .s4IWU{--shiki-default:#8DA101;--shiki-dark:#A7C080}html pre.shiki code .sZsqx, html code.shiki .sZsqx{--shiki-default:#35A77C;--shiki-dark:#83C092}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":14,"searchDepth":15,"depth":15,"links":2587},[2588,2589,2590,2591],{"id":2333,"depth":15,"text":2334},{"id":2384,"depth":15,"text":2385},{"id":2399,"depth":15,"text":2400},{"id":2563,"depth":15,"text":2564},"A documentation framework for developers, built on Nuxt.js and Vue.js. Clay provides a structured, auto-generated system for displaying documentation written in Markdown.",{},"\u002Freadmes\u002Fclay",{"title":109,"description":2592},"readmes\u002Fclay","FFkCrbF55lPnYYJPwtsEY1_G9fHF9915BOA7GD6mztA",{"id":2599,"title":265,"body":2600,"description":2604,"extension":17,"meta":2843,"navigation":23,"path":2844,"seo":2845,"stem":2846,"__hash__":2847},"readmes\u002Freadmes\u002Fforkcast.md",{"type":11,"value":2601,"toc":2832},[2602,2605,2609,2614,2625,2629,2640,2644,2655,2659,2673,2675,2678,2719,2730,2734,2737,2822,2826,2829],[41,2603,2604],{},"Forkcast is a web application that digitizes and simplifies meal planning. Instead of juggling paper lists, it combines a drag-and-drop weekly calendar with a smart shopping list, recipe discovery, and a small social layer around friends.",[692,2606,2608],{"id":2607},"features","Features",[2610,2611,2613],"h3",{"id":2612},"meal-planner-calendar","Meal Planner & Calendar",[809,2615,2616,2619,2622],{},[812,2617,2618],{},"Interactive weekly calendar as the core of the app.",[812,2620,2621],{},"Drag & drop recipes onto a weekday, categorized as breakfast, lunch, dinner, or a free-text label.",[812,2623,2624],{},"Portions scale ingredient amounts to the number of people.",[2610,2626,2628],{"id":2627},"smart-shopping-list","Smart Shopping List",[809,2630,2631,2634,2637],{},[812,2632,2633],{},"Generated automatically from the weekly plan.",[812,2635,2636],{},"Identical ingredients across recipes (e.g. onions) are merged and summed.",[812,2638,2639],{},"Stock check: tick off or reduce quantities for items already at home.",[2610,2641,2643],{"id":2642},"discovery-social","Discovery & Social",[809,2645,2646,2649,2652],{},[812,2647,2648],{},"Home page acts as an inspiration feed with a daily highlight.",[812,2650,2651],{},"Friend network: add friends by username, send\u002Faccept\u002Fdecline requests.",[812,2653,2654],{},"Privacy: each user chooses whether their weekly plan is public or private.",[2610,2656,2658],{"id":2657},"recipes-personalization","Recipes & Personalization",[809,2660,2661,2664,2667,2670],{},[812,2662,2663],{},"Spoonacular API as recipe source, with detailed ingredients and nutrition.",[812,2665,2666],{},"Search with filters, favorites, and per-recipe ratings.",[812,2668,2669],{},"Allergy \u002F dietary filters applied to recommendations.",[812,2671,2672],{},"9 UI languages including right-to-left (Arabic, Hebrew).",[692,2674,103],{"id":947},[41,2676,2677],{},"Monorepo with two independently deployed apps:",[1974,2679,2680,2693],{},[1977,2681,2682],{},[1980,2683,2684,2687,2690],{},[1983,2685,2686],{},"Part",[1983,2688,2689],{},"Stack",[1983,2691,2692],{},"Deploy",[1993,2694,2695,2707],{},[1980,2696,2697,2701,2704],{},[1998,2698,2699],{},[116,2700,2023],{},[1998,2702,2703],{},"Nuxt 4 (Vue 3), Pinia, TailwindCSS 4 + DaisyUI, i18n",[1998,2705,2706],{},"Static site → GitHub Pages",[1980,2708,2709,2713,2716],{},[1998,2710,2711],{},[116,2712,2006],{},[1998,2714,2715],{},"Express 5, better-sqlite3, JWT, Spoonacular",[1998,2717,2718],{},"Docker image → GHCR",[41,2720,2721,2722,2725,2726,2729],{},"The frontend is a static SPA: it talks to the backend REST API at ",[116,2723,2724],{},"\u002Fapi",", holds the JWT in ",[116,2727,2728],{},"sessionStorage",", and renders the dashboard client-side. The backend owns auth, the SQLite database, recipe caching from Spoonacular, and email (verification \u002F password reset).",[692,2731,2733],{"id":2732},"quick-start","Quick Start",[41,2735,2736],{},"Run the backend and frontend in two terminals:",[330,2738,2740],{"className":2136,"code":2739,"language":2138,"meta":14,"style":14},"# Backend (REST API on :3000)\ncd backend\ncp example.env .env        # fill in JWT_SECRET, SPOONACULAR_API_KEY, ...\nnpm install && npm start\n\n# Frontend (Nuxt dev server on :8080)\ncd frontend\nnpm install\nnpm run dev -- --port 8080\n",[116,2741,2742,2747,2754,2768,2781,2785,2790,2797,2804],{"__ignoreMap":14},[338,2743,2744],{"class":340,"line":24},[338,2745,2746],{"class":353},"# Backend (REST API on :3000)\n",[338,2748,2749,2751],{"class":340,"line":15},[338,2750,2179],{"class":405},[338,2752,2753],{"class":405}," backend\n",[338,2755,2756,2759,2762,2765],{"class":340,"line":235},[338,2757,2758],{"class":343},"cp",[338,2760,2761],{"class":405}," example.env",[338,2763,2764],{"class":405}," .env",[338,2766,2767],{"class":353},"        # fill in JWT_SECRET, SPOONACULAR_API_KEY, ...\n",[338,2769,2770,2772,2774,2776,2778],{"class":340,"line":383},[338,2771,2215],{"class":343},[338,2773,2218],{"class":405},[338,2775,2185],{"class":347},[338,2777,2215],{"class":343},[338,2779,2780],{"class":405}," start\n",[338,2782,2783],{"class":340,"line":389},[338,2784,386],{"emptyLinePlaceholder":23},[338,2786,2787],{"class":340,"line":397},[338,2788,2789],{"class":353},"# Frontend (Nuxt dev server on :8080)\n",[338,2791,2792,2794],{"class":340,"line":417},[338,2793,2179],{"class":405},[338,2795,2796],{"class":405}," frontend\n",[338,2798,2799,2801],{"class":340,"line":423},[338,2800,2215],{"class":343},[338,2802,2803],{"class":405}," install\n",[338,2805,2806,2808,2810,2813,2816,2819],{"class":340,"line":428},[338,2807,2215],{"class":343},[338,2809,2225],{"class":405},[338,2811,2812],{"class":405}," dev",[338,2814,2815],{"class":405}," --",[338,2817,2818],{"class":405}," --port",[338,2820,2821],{"class":376}," 8080\n",[692,2823,2825],{"id":2824},"team","Team",[41,2827,2828],{},"Kerimcan Yagci, Lukas Grünzweil, Erik Reitbauer and Nico Haider, as a summer project in school.",[526,2830,2831],{},"html pre.shiki code .saOx9, html code.shiki .saOx9{--shiki-default:#939F91;--shiki-default-font-style:italic;--shiki-dark:#859289;--shiki-dark-font-style:italic}html pre.shiki code .spy5Z, html code.shiki .spy5Z{--shiki-default:#DFA000;--shiki-dark:#DBBC7F}html pre.shiki code .s4IWU, html code.shiki .s4IWU{--shiki-default:#8DA101;--shiki-dark:#A7C080}html pre.shiki code .sXf0S, html code.shiki .sXf0S{--shiki-default:#5C6A72;--shiki-dark:#D3C6AA}html pre.shiki code .sc47v, html code.shiki .sc47v{--shiki-default:#DF69BA;--shiki-dark:#D699B6}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":14,"searchDepth":15,"depth":15,"links":2833},[2834,2840,2841,2842],{"id":2607,"depth":15,"text":2608,"children":2835},[2836,2837,2838,2839],{"id":2612,"depth":235,"text":2613},{"id":2627,"depth":235,"text":2628},{"id":2642,"depth":235,"text":2643},{"id":2657,"depth":235,"text":2658},{"id":947,"depth":15,"text":103},{"id":2732,"depth":15,"text":2733},{"id":2824,"depth":15,"text":2825},{},"\u002Freadmes\u002Fforkcast",{"title":265,"description":2604},"readmes\u002Fforkcast","EvJrx5GWPLwDOzwtGvlsjChiktpauOUrGIrS2xBo1DM",{"id":2849,"title":326,"body":2850,"description":2854,"extension":17,"meta":3121,"navigation":23,"path":3122,"seo":3123,"stem":3124,"__hash__":3125},"readmes\u002Freadmes\u002Fbackbone.md",{"type":11,"value":2851,"toc":3116},[2852,2855,2858,2860,2922,2926,2951,2954,2958,2961,3104,3114],[41,2853,2854],{},"Backbone is a powerful and flexible plugin for Spigot-based Minecraft servers. Its core idea: write, test, and update server logic on a live server without restarts, dramatically speeding up the development lifecycle.",[41,2856,2857],{},"Whether you are an admin adding custom features with simple scripts or a developer prototyping new ideas, Backbone gives you the tools to be more productive.",[692,2859,2608],{"id":2607},[809,2861,2862,2868,2874,2880,2886,2892,2898,2904,2910],{},[812,2863,2864,2867],{},[872,2865,2866],{},"Hot-Loadable Scripts:"," Write and reload Kotlin scripts without restarting the server.",[812,2869,2870,2873],{},[872,2871,2872],{},"Advanced Scripting:"," Inter-script imports, Maven dependencies, and custom compiler options.",[812,2875,2876,2879],{},[872,2877,2878],{},"Event System:"," A custom event bus that complements Bukkit's, with more control inside scripts.",[812,2881,2882,2885],{},[872,2883,2884],{},"Command Framework:"," A simple but powerful system to create commands directly from scripts.",[812,2887,2888,2891],{},[872,2889,2890],{},"Storage Abstraction:"," Flexible storage with SQLite databases and typed configuration files.",[812,2893,2894,2897],{},[872,2895,2896],{},"GUI Framework:"," A declarative framework for building interactive inventories.",[812,2899,2900,2903],{},[872,2901,2902],{},"Custom Items & Entities:"," Stateful items with abilities and custom entities via the goals API.",[812,2905,2906,2909],{},[872,2907,2908],{},"Display Entity Rendering:"," Create custom visuals in the world.",[812,2911,2912,2127,2915,2127,2918,2921],{},[872,2913,2914],{},"PlaceholderAPI Integration",[872,2916,2917],{},"HTTP Client DSL",[872,2919,2920],{},"memory-leak detection",", and much more.",[692,2923,2925],{"id":2924},"getting-started","Getting Started",[2927,2928,2929,2939,2942],"ol",{},[812,2930,2931,2932,2935,2936,2342],{},"Download the latest release and drop the ",[116,2933,2934],{},".jar"," into your server's ",[116,2937,2938],{},"plugins",[812,2940,2941],{},"Start the server, Backbone generates its folders automatically.",[812,2943,2944,2945,2947,2948,818],{},"Write custom logic in ",[116,2946,689],{}," script files inside ",[116,2949,2950],{},"scripts\u002F",[41,2952,2953],{},"Requires Minecraft Java 1.21.11+, a Spigot-based server (Spigot, Paper), and Java 17+.",[692,2955,2957],{"id":2956},"scripting-example","Scripting Example",[41,2959,2960],{},"Every script uses the lifecycle DSL for hooks and event listeners:",[330,2962,2964],{"className":332,"code":2963,"language":334,"meta":14,"style":14},"lifecycle {\n    \u002F\u002F 'sustained' properties persist across script reloads.\n    var counter by sustained(0)\n\n    onLoad {\n        println(\"Script loaded! Counter: $counter\")\n    }\n\n    \u002F\u002F Fires every server tick while the script is enabled.\n    listener\u003CTickEvent> { event ->\n        counter++\n        if (counter % 20 == 0) {\n            Backbone.PLUGIN.server.onlinePlayers\n                .forEach { it.sendMessage(\"Count: $counter\") }\n        }\n    }\n}\n",[116,2965,2966,2972,2977,2993,2997,3003,3018,3022,3026,3031,3045,3051,3067,3071,3091,3095,3099],{"__ignoreMap":14},[338,2967,2968,2970],{"class":340,"line":24},[338,2969,344],{"class":343},[338,2971,348],{"class":347},[338,2973,2974],{"class":340,"line":15},[338,2975,2976],{"class":353},"    \u002F\u002F 'sustained' properties persist across script reloads.\n",[338,2978,2979,2981,2983,2985,2987,2989,2991],{"class":340,"line":235},[338,2980,360],{"class":359},[338,2982,363],{"class":347},[338,2984,367],{"class":366},[338,2986,370],{"class":343},[338,2988,373],{"class":347},[338,2990,377],{"class":376},[338,2992,380],{"class":347},[338,2994,2995],{"class":340,"line":383},[338,2996,386],{"emptyLinePlaceholder":23},[338,2998,2999,3001],{"class":340,"line":389},[338,3000,392],{"class":343},[338,3002,348],{"class":347},[338,3004,3005,3007,3009,3012,3014,3016],{"class":340,"line":397},[338,3006,400],{"class":343},[338,3008,373],{"class":347},[338,3010,3011],{"class":405},"\"Script loaded! Counter: ",[338,3013,409],{"class":347},[338,3015,412],{"class":405},[338,3017,380],{"class":347},[338,3019,3020],{"class":340,"line":417},[338,3021,420],{"class":347},[338,3023,3024],{"class":340,"line":423},[338,3025,386],{"emptyLinePlaceholder":23},[338,3027,3028],{"class":340,"line":428},[338,3029,3030],{"class":353},"    \u002F\u002F Fires every server tick while the script is enabled.\n",[338,3032,3033,3035,3037,3039,3042],{"class":340,"line":444},[338,3034,431],{"class":343},[338,3036,434],{"class":347},[338,3038,438],{"class":437},[338,3040,3041],{"class":347},"> { event ",[338,3043,3044],{"class":359},"->\n",[338,3046,3047,3049],{"class":340,"line":453},[338,3048,447],{"class":347},[338,3050,450],{"class":366},[338,3052,3053,3055,3057,3059,3061,3063,3065],{"class":340,"line":477},[338,3054,456],{"class":359},[338,3056,459],{"class":347},[338,3058,462],{"class":366},[338,3060,465],{"class":376},[338,3062,468],{"class":366},[338,3064,471],{"class":376},[338,3066,474],{"class":347},[338,3068,3069],{"class":340,"line":483},[338,3070,480],{"class":347},[338,3072,3073,3075,3077,3079,3081,3083,3085,3087,3089],{"class":340,"line":510},[338,3074,486],{"class":347},[338,3076,489],{"class":343},[338,3078,492],{"class":347},[338,3080,495],{"class":343},[338,3082,373],{"class":347},[338,3084,500],{"class":405},[338,3086,409],{"class":347},[338,3088,412],{"class":405},[338,3090,507],{"class":347},[338,3092,3093],{"class":340,"line":516},[338,3094,513],{"class":347},[338,3096,3097],{"class":340,"line":521},[338,3098,420],{"class":347},[338,3100,3102],{"class":340,"line":3101},17,[338,3103,524],{"class":347},[41,3105,814,3106,3108,3109,3111,3112,818],{},[116,3107,817],{},", share code through ",[116,3110,824],{}," utility scripts, define commands, build GUIs, and talk to each other through inter-script messaging, all hot-reloadable with ",[116,3113,791],{},[526,3115,528],{},{"title":14,"searchDepth":15,"depth":15,"links":3117},[3118,3119,3120],{"id":2607,"depth":15,"text":2608},{"id":2924,"depth":15,"text":2925},{"id":2956,"depth":15,"text":2957},{},"\u002Freadmes\u002Fbackbone",{"title":326,"description":2854},"readmes\u002Fbackbone","Auk1kA6z8ErXwZAmF-CzJSQ_2MNW-U01afU3arXCV7E",{"id":3127,"title":564,"body":3128,"description":3132,"extension":17,"meta":3479,"navigation":23,"path":3480,"seo":3481,"stem":3482,"__hash__":3483},"readmes\u002Freadmes\u002Fhelix.md",{"type":11,"value":3129,"toc":3465},[3130,3133,3137,3152,3156,3176,3180,3183,3187,3190,3194,3301,3305,3346,3350,3353,3357,3360,3364,3370,3429,3433,3440,3462],[41,3131,3132],{},"Helix is a QOL Mod that aims to improve your experience by adding various features.\nHelix is free and open source, forever.",[692,3134,3136],{"id":3135},"installation","Installation",[41,3138,3139,3140,3145,3146,3151],{},"Helix requires the ",[682,3141,3144],{"href":3142,"rel":3143},"https:\u002F\u002Fmodrinth.com\u002Fmod\u002Ffabric-language-kotlin",[685],"Kotlin language adapter"," and the ",[682,3147,3150],{"href":3148,"rel":3149},"https:\u002F\u002Fmodrinth.com\u002Fmod\u002Ffabric-api",[685],"Fabric API"," to work correctly.",[2610,3153,3155],{"id":3154},"how-to-install-step-by-step","How to install, step by step",[809,3157,3158,3161,3164,3167,3170,3173],{},[812,3159,3160],{},"Download the latest release of Helix, the matching Fabric API and Kotlin language adapter",[812,3162,3163],{},"Put all 3 mods in your mods folder",[812,3165,3166],{},"Make sure you have the correct java version installed (17)",[812,3168,3169],{},"Make sure you have the fabric loader installed",[812,3171,3172],{},"Launch the fabric loader",[812,3174,3175],{},"Have fun!",[692,3177,3179],{"id":3178},"accent-colours","Accent colours",[41,3181,3182],{},"Rgb, orange, red, green, yellow, pink, purple and blue.",[692,3184,3186],{"id":3185},"themes","Themes",[41,3188,3189],{},"Dark and light.",[692,3191,3193],{"id":3192},"in-game-features","In-Game features",[809,3195,3196,3202,3208,3214,3220,3226,3232,3238,3244,3250,3256,3262,3268,3274,3280,3286,3292],{},[812,3197,3198,3201],{},[872,3199,3200],{},"Crystal Optimizer"," Optimized the placing and breaking of crystals clientside to improve crystal speed (removing broken crystals on the client...)",[812,3203,3204,3207],{},[872,3205,3206],{},"Block Outline"," Changes your block outline and adds optional entity outlines",[812,3209,3210,3213],{},[872,3211,3212],{},"Armor Hud"," Shows you your armor on the screen without having to open your inventory",[812,3215,3216,3219],{},[872,3217,3218],{},"Autosprint"," Presses the sprint key for you",[812,3221,3222,3225],{},[872,3223,3224],{},"Better Arm"," Changes the rendering of your In-Game hand",[812,3227,3228,3231],{},[872,3229,3230],{},"Coordinates"," Shows you your coordinates in the world",[812,3233,3234,3237],{},[872,3235,3236],{},"Cosmetics"," Render cosmetics clientside, for free",[812,3239,3240,3243],{},[872,3241,3242],{},"Directions"," Shows in what direction you are facing",[812,3245,3246,3249],{},[872,3247,3248],{},"Fps Display"," Shows your current Fps",[812,3251,3252,3255],{},[872,3253,3254],{},"Fullbright"," See in the dark",[812,3257,3258,3261],{},[872,3259,3260],{},"Hotbar"," Changes several status bars to literal bars",[812,3263,3264,3267],{},[872,3265,3266],{},"Keystrokes"," Shows what keys are being pressed",[812,3269,3270,3273],{},[872,3271,3272],{},"Nametags"," See your own nametag and add information to it",[812,3275,3276,3279],{},[872,3277,3278],{},"No Armor"," Hides your armor clientside",[812,3281,3282,3285],{},[872,3283,3284],{},"No Render"," Disables the rendering of certain things",[812,3287,3288,3291],{},[872,3289,3290],{},"Ping Display"," Shows your current ping",[812,3293,3294,3297,3298],{},[872,3295,3296],{},"Chat Format"," Create gradients without leaving Minecraft. Can also solve simple math, for example ",[116,3299,3300],{},"\u003Csolve>1+2*(27-5)\u002F5\u003Csolve>",[692,3302,3304],{"id":3303},"commands","Commands",[809,3306,3307,3313,3322,3330,3338],{},[812,3308,3309,3312],{},[872,3310,3311],{},"\u002Fhelix"," Opens the main UI",[812,3314,3315,3321],{},[872,3316,3317,3318],{},"\u002Fgmc ",[338,3319,3320],{},"player"," Puts you or the optionally specified player in creative mode (only works if you have permission on the server since we are just redirecting commands)",[812,3323,3324,3329],{},[872,3325,3326,3327],{},"\u002Fgms ",[338,3328,3320],{}," Puts you or the optionally specified player in survival mode (only works if you have permission on the server since we are just redirecting commands)",[812,3331,3332,3337],{},[872,3333,3334,3335],{},"\u002Fgma ",[338,3336,3320],{}," Puts you or the optionally specified player in adventure mode (only works if you have permission on the server since we are just redirecting commands)",[812,3339,3340,3345],{},[872,3341,3342,3343],{},"\u002Fgmsp ",[338,3344,3320],{}," Puts you or the optionally specified player in spectator mode (only works if you have permission on the server since we are just redirecting commands)",[692,3347,3349],{"id":3348},"discord-presence","Discord Presence",[41,3351,3352],{},"Shows some information about the server or world you are on to your friends on discord",[692,3354,3356],{"id":3355},"for-developers-and-server-owners","For Developers and Server Owners",[41,3358,3359],{},"The following example code can be used to block modules from being used on your server.\nIn the future, there may be more options for configuring the mod via the server.",[2610,3361,3363],{"id":3362},"json-structure-for-the-payload","Json Structure for the payload",[41,3365,3366,3367,818],{},"This is the structure to use in the payload of the message sent to the player. Invalid json and incorrect module ids will be ignored. You can find the module ids in the respective modules.\nThe ids can always be found in the header of the module and will always be in the following scheme: ",[116,3368,3369],{},"moduleName",[330,3371,3375],{"className":3372,"code":3373,"language":3374,"meta":14,"style":14},"language-json shiki shiki-themes everforest-light everforest-dark","{\n  \"disabled\": [\n    \"armorHud\",\n    \"autoSprint\"\n  ]\n}\n","json",[116,3376,3377,3382,3397,3410,3420,3425],{"__ignoreMap":14},[338,3378,3379],{"class":340,"line":24},[338,3380,3381],{"class":347},"{\n",[338,3383,3384,3387,3390,3392,3394],{"class":340,"line":15},[338,3385,3386],{"class":2420},"  \"",[338,3388,3389],{"class":366},"disabled",[338,3391,412],{"class":2420},[338,3393,2421],{"class":2420},[338,3395,3396],{"class":347}," [\n",[338,3398,3399,3402,3405,3407],{"class":340,"line":235},[338,3400,3401],{"class":2420},"    \"",[338,3403,3404],{"class":343},"armorHud",[338,3406,412],{"class":2420},[338,3408,3409],{"class":2420},",\n",[338,3411,3412,3414,3417],{"class":340,"line":383},[338,3413,3401],{"class":2420},[338,3415,3416],{"class":343},"autoSprint",[338,3418,3419],{"class":2420},"\"\n",[338,3421,3422],{"class":340,"line":389},[338,3423,3424],{"class":347},"  ]\n",[338,3426,3427],{"class":340,"line":397},[338,3428,524],{"class":347},[2610,3430,3432],{"id":3431},"sending-the-configuration-json-in-your-plugin","Sending the configuration json in your plugin",[41,3434,3435,3436,3439],{},"This code can be put for example in the ",[116,3437,3438],{},"onJoin"," listener. Once disabled, modules stay disabled until the player rejoins the server.\nThen they need to be disabled again.",[330,3441,3445],{"className":3442,"code":3443,"language":3444,"meta":14,"style":14},"language-java shiki shiki-themes everforest-light everforest-dark","\u003Cplayer>.sendPluginMessage(\u003Cplugin-instance>, \"helix:config\",\n     \u003Cjson-payload>.toByteArray()\n);\n","java",[116,3446,3447,3452,3457],{"__ignoreMap":14},[338,3448,3449],{"class":340,"line":24},[338,3450,3451],{},"\u003Cplayer>.sendPluginMessage(\u003Cplugin-instance>, \"helix:config\",\n",[338,3453,3454],{"class":340,"line":15},[338,3455,3456],{},"     \u003Cjson-payload>.toByteArray()\n",[338,3458,3459],{"class":340,"line":235},[338,3460,3461],{},");\n",[526,3463,3464],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sXf0S, html code.shiki .sXf0S{--shiki-default:#5C6A72;--shiki-dark:#D3C6AA}html pre.shiki code .sMKMZ, html code.shiki .sMKMZ{--shiki-default:#939F91;--shiki-dark:#859289}html pre.shiki code .sOk1_, html code.shiki .sOk1_{--shiki-default:#F57D26;--shiki-dark:#E69875}html pre.shiki code .s4IWU, html code.shiki .s4IWU{--shiki-default:#8DA101;--shiki-dark:#A7C080}",{"title":14,"searchDepth":15,"depth":15,"links":3466},[3467,3470,3471,3472,3473,3474,3475],{"id":3135,"depth":15,"text":3136,"children":3468},[3469],{"id":3154,"depth":235,"text":3155},{"id":3178,"depth":15,"text":3179},{"id":3185,"depth":15,"text":3186},{"id":3192,"depth":15,"text":3193},{"id":3303,"depth":15,"text":3304},{"id":3348,"depth":15,"text":3349},{"id":3355,"depth":15,"text":3356,"children":3476},[3477,3478],{"id":3362,"depth":235,"text":3363},{"id":3431,"depth":235,"text":3432},{},"\u002Freadmes\u002Fhelix",{"title":564,"description":3132},"readmes\u002Fhelix","oumx3JX-ZT1LixbUPD7TWtMsY2bkpKcUnG-U2fUssY4",{"id":674,"title":675,"body":3485,"date":86,"description":846,"draft":847,"extension":17,"meta":3622,"navigation":23,"path":849,"seo":3623,"stem":851,"summary":852,"tags":3624,"__hash__":856},{"type":11,"value":3486,"toc":3617},[3487,3494,3496,3498,3584,3588,3590,3594,3596,3610,3615],[41,3488,680,3489,686,3492,690],{},[682,3490,326],{"href":536,"rel":3491},[685],[116,3493,689],{},[692,3495,695],{"id":694},[41,3497,698],{},[330,3499,3500],{"className":332,"code":701,"language":334,"meta":14,"style":14},[116,3501,3502,3508,3512,3528,3532,3538,3552,3556,3560,3570,3576,3580],{"__ignoreMap":14},[338,3503,3504,3506],{"class":340,"line":24},[338,3505,344],{"class":343},[338,3507,348],{"class":347},[338,3509,3510],{"class":340,"line":15},[338,3511,714],{"class":353},[338,3513,3514,3516,3518,3520,3522,3524,3526],{"class":340,"line":235},[338,3515,360],{"class":359},[338,3517,363],{"class":347},[338,3519,367],{"class":366},[338,3521,370],{"class":343},[338,3523,373],{"class":347},[338,3525,377],{"class":376},[338,3527,380],{"class":347},[338,3529,3530],{"class":340,"line":383},[338,3531,386],{"emptyLinePlaceholder":23},[338,3533,3534,3536],{"class":340,"line":389},[338,3535,392],{"class":343},[338,3537,348],{"class":347},[338,3539,3540,3542,3544,3546,3548,3550],{"class":340,"line":397},[338,3541,400],{"class":343},[338,3543,373],{"class":347},[338,3545,406],{"class":405},[338,3547,409],{"class":347},[338,3549,412],{"class":405},[338,3551,380],{"class":347},[338,3553,3554],{"class":340,"line":417},[338,3555,420],{"class":347},[338,3557,3558],{"class":340,"line":423},[338,3559,386],{"emptyLinePlaceholder":23},[338,3561,3562,3564,3566,3568],{"class":340,"line":428},[338,3563,431],{"class":343},[338,3565,434],{"class":347},[338,3567,438],{"class":437},[338,3569,441],{"class":347},[338,3571,3572,3574],{"class":340,"line":444},[338,3573,447],{"class":347},[338,3575,450],{"class":366},[338,3577,3578],{"class":340,"line":453},[338,3579,420],{"class":347},[338,3581,3582],{"class":340,"line":477},[338,3583,524],{"class":347},[41,3585,3586,792],{},[116,3587,791],{},[692,3589,796],{"id":795},[41,3591,799,3592,803],{},[116,3593,802],{},[692,3595,807],{"id":806},[809,3597,3598,3602,3606,3608],{},[812,3599,814,3600,818],{},[116,3601,817],{},[812,3603,821,3604,825],{},[116,3605,824],{},[812,3607,828],{},[812,3609,831],{},[41,3611,834,3612,838],{},[682,3613,538],{"href":539,"rel":3614},[685],[526,3616,528],{},{"title":14,"searchDepth":15,"depth":15,"links":3618},[3619,3620,3621],{"id":694,"depth":15,"text":695},{"id":795,"depth":15,"text":796},{"id":806,"depth":15,"text":807},{},{"title":675,"description":846},[854,334,855],{"id":858,"title":859,"body":3626,"date":86,"description":864,"draft":847,"extension":17,"meta":3678,"navigation":23,"path":942,"seo":3679,"stem":944,"summary":945,"tags":3680,"__hash__":949},{"type":11,"value":3627,"toc":3673},[3628,3630,3632,3636,3640,3642,3646,3648,3666,3668],[41,3629,864],{},[692,3631,868],{"id":867},[41,3633,3634],{},[872,3635,874],{},[41,3637,877,3638,881],{},[116,3639,880],{},[692,3641,885],{"id":884},[41,3643,888,3644,893],{},[890,3645,892],{},[692,3647,897],{"id":896},[809,3649,3650,3654,3662],{},[812,3651,3652,905],{},[872,3653,904],{},[812,3655,3656,911,3658,915,3660,919],{},[872,3657,910],{},[890,3659,914],{},[890,3661,918],{},[812,3663,3664,925],{},[872,3665,924],{},[41,3667,928],{},[41,3669,931,3670,818],{},[682,3671,935],{"href":75,"rel":3672},[685],{"title":14,"searchDepth":15,"depth":15,"links":3674},[3675,3676,3677],{"id":867,"depth":15,"text":868},{"id":884,"depth":15,"text":885},{"id":896,"depth":15,"text":897},{},{"title":859,"description":864},[104,947,948],1790686590494]