[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"articles":3},{"data":4,"pagination":2191},[5,237,547,694,823,1051,1138,1371,1525,1600,1761,1960,2070],{"id":6,"attributes":7,"body":8,"description":26,"headline":216,"schema":26,"slug":217,"subHeadline":26,"publishedAt":218,"type":219,"categories":220,"images":221,"relationships":222,"tags":223,"permalink":224,"author":228},"article_01kwdmkzgte4bt27xfx6hc4hty",{},{"type":9,"content":10},"doc",[11,29,56,60,80,87,164,169,195,199,204,208,212],{"type":12,"content":13},"paragraph",[14,17,27],{"type":15,"text":16},"text","I open sourced ",{"type":15,"text":18,"marks":19},"Arc Work",[20],{"type":21,"attrs":22},"link",{"href":23,"target":24,"rel":25,"class":26,"title":26},"https:\u002F\u002Fgithub.com\u002Ftimhanlon\u002Farcwork","_blank","noopener noreferrer nofollow",null,{"type":15,"text":28},", my meta-harness, last week.",{"type":12,"content":30},[31,33,39,41,47,48,54],{"type":15,"text":32},"It’s one of a growing crowd - ",{"type":15,"text":34,"marks":35},"Solo",[36],{"type":21,"attrs":37},{"href":38,"target":24,"rel":25,"class":26,"title":26},"https:\u002F\u002Fsoloterm.com\u002F",{"type":15,"text":40},", ",{"type":15,"text":42,"marks":43},"Conductor",[44],{"type":21,"attrs":45},{"href":46,"target":24,"rel":25,"class":26,"title":26},"https:\u002F\u002Fwww.conductor.build\u002F",{"type":15,"text":40},{"type":15,"text":49,"marks":50},"Superset",[51],{"type":21,"attrs":52},{"href":53,"target":24,"rel":25,"class":26,"title":26},"https:\u002F\u002Fsuperset.sh\u002F",{"type":15,"text":55},", and no doubt many more.",{"type":12,"content":57},[58],{"type":15,"text":59},"I’ve been working on it for less than a month, so it’s still early days. I use it as my daily driver, to work on Arc Work and several other projects.",{"type":12,"content":61},[62,64,70,72,78],{"type":15,"text":63},"I’ve been yapping about what I’m up to on ",{"type":15,"text":65,"marks":66},"X",[67],{"type":21,"attrs":68},{"href":69,"target":24,"rel":25,"class":26,"title":26},"https:\u002F\u002Fx.com\u002Ftimhnln",{"type":15,"text":71},", but my friend and former colleague ",{"type":15,"text":73,"marks":74},"Dave Stewart",[75],{"type":21,"attrs":76},{"href":77,"target":24,"rel":25,"class":26,"title":26},"https:\u002F\u002Fdavestewart.co.uk\u002F",{"type":15,"text":79}," encouraged me to write more about the thinking behind it, and I’ve finally gotten around to it.",{"type":81,"attrs":82,"content":84},"heading",{"level":83},2,[85],{"type":15,"text":86},"Why I’m building this",{"type":88,"content":89},"bulletList",[90,97,110,116,122,146,152,158],{"type":91,"content":92},"listItem",[93],{"type":12,"content":94},[95],{"type":15,"text":96},"We’re nowhere near the end-game UI for agentic development, and I don’t want to wait around for someone else to figure it out.",{"type":91,"content":98},[99],{"type":12,"content":100},[101,103,108],{"type":15,"text":102},"TUIs are ",{"type":15,"text":104,"marks":105},"cool",[106],{"type":107},"italic",{"type":15,"text":109},", but I don’t want a single harness (or terminal multiplexer) to be my primary interface for work. Particularly not if it’s closed source, or attached to a particular model provider.",{"type":91,"content":111},[112],{"type":12,"content":113},[114],{"type":15,"text":115},"I’ve experimented with other meta-harnesses, as well as standalone tools for things like task tracking and storing your agent history, but I wanted to experiment with a unified way of doing things. Richer UI and better workflows for what needs it, with the PTY taking a back seat.",{"type":91,"content":117},[118],{"type":12,"content":119},[120],{"type":15,"text":121},"The Markdown-centric workflow I was using to keep track of work & decisions while working on Minima eventually collapsed under its own weight - 100s of long Markdown documents became impossible for me to reason with, and slow\u002Fcontext-heavy for agents to work with.",{"type":91,"content":123},[124],{"type":12,"content":125},[126,128,132,134,138,140,144],{"type":15,"text":127},"Work isn’t linear. Work is ",{"type":15,"text":129,"marks":130},"discovered",[131],{"type":107},{"type":15,"text":133}," while you’re doing other work, and git commits\u002FGitHub PRs only capture what ",{"type":15,"text":135,"marks":136},"did",[137],{"type":107},{"type":15,"text":139}," happen - what happened ",{"type":15,"text":141,"marks":142},"between",[143],{"type":107},{"type":15,"text":145}," them is just as important.",{"type":91,"content":147},[148],{"type":12,"content":149},[150],{"type":15,"text":151},"If Claude Code goes down, or I blow my Codex limits, I want to be able to seamlessly continue with another harness.",{"type":91,"content":153},[154],{"type":12,"content":155},[156],{"type":15,"text":157},"Open models, and cheaper proprietary ones like Cursor Composer 2.5, are improving rapidly - it should be easier to use them in tandem with the usual suspects.",{"type":91,"content":159},[160],{"type":12,"content":161},[162],{"type":15,"text":163},"It’s a great opportunity to get my hands dirty with a new stack - Electron, React, and Effect v4.",{"type":81,"attrs":165,"content":166},{"level":83},[167],{"type":15,"text":168},"The headline features",{"type":88,"content":170},[171,177,183,189],{"type":91,"content":172},[173],{"type":12,"content":174},[175],{"type":15,"text":176},"Supports Claude Code, Codex, Cursor CLI, and Pi",{"type":91,"content":178},[179],{"type":12,"content":180},[181],{"type":15,"text":182},"Agents can spawn other agents, with their own PTY, assign work to them, and communicate with each other",{"type":91,"content":184},[185],{"type":12,"content":186},[187],{"type":15,"text":188},"A built-in local work graph, to track tasks, progress, and dependencies",{"type":91,"content":190},[191],{"type":12,"content":192},[193],{"type":15,"text":194},"All your agent history is automatically ingested into a SQLite database - a goldmine of context for future agents",{"type":12,"content":196},[197],{"type":15,"text":198},"There’s also the quality-of-life stuff I’ve added like git worktrees, GitHub PRs, key bindings, and highlighting any sessions which need your input.",{"type":81,"attrs":200,"content":201},{"level":83},[202],{"type":15,"text":203},"What now",{"type":12,"content":205},[206],{"type":15,"text":207},"With a few key building blocks now in place, I can put them together, move them around, and see what falls out.",{"type":12,"content":209},[210],{"type":15,"text":211},"I’m currently experimenting with ways to manage context windows and compaction. Rather than dealing with degradation and waiting for a harness to auto-compact, I’d rather use the chat history and work graph we already have to do it proactively. Maybe an open model running in LM Studio can do it for free.",{"type":12,"content":213},[214],{"type":15,"text":215},"Less glamorous, but more important short-term: binary distribution, proper documentation, and generally making it easier to try. Right now it's early enough that running it means building from source, and I want to lower that bar.","Introducing Arc Work","introducing-arc-work",1782869421,"Article",[],[],{},[],{"path":225,"site":226},"\u002Fintroducing-arc-work",{"domain":227},"timhanlon.com",{"id":229,"name":230,"schema":26,"avatar":231,"bio":26,"title":26,"permalink":26},"user_01jak1yhhqen8ttr7e6qmm7316","Tim Hanlon",{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":234,"contentType":235,"path":236},256,"image_01jsbsj8wte8ms76bdsd048wg5",[],"image\u002Fpng","user_01jak1yhhqen8ttr7e6qmm7316\u002Favatar2-15b3859c.png",{"id":238,"attributes":239,"body":240,"description":26,"headline":530,"schema":26,"slug":531,"subHeadline":26,"publishedAt":532,"type":219,"categories":533,"images":538,"relationships":539,"tags":540,"permalink":541,"author":544},"article_01kg8p1ppgfvjazekce5eyxg3s",{},{"type":9,"content":241},[242,246,250,254,274,278,282,288,292,304,311,315,320,324,330,334,339,343,347,351,356,360,372,376,380,384,416,420,452,456,460,486,491,495,499,525,529],{"type":12,"content":243},[244],{"type":15,"text":245},"Minima is currently only a headless CMS, but I’ve been hard at work giving it a head.",{"type":12,"content":247},[248],{"type":15,"text":249},"It will launch with a small set of official themes, but after seeing how good Gemini 3 was at design, it was obvious the infrastructure also had to support AI-generated themes.",{"type":12,"content":251},[252],{"type":15,"text":253},"The original plan was a single, multi-tenant “customer” Nuxt application. It would pull a site’s theme from the database and compile the templates into Vue components at runtime, but otherwise be a relatively normal Nuxt app.",{"type":12,"content":255},[256,258,264,266,272],{"type":15,"text":257},"Nuxt excludes the Vue runtime compiler by default, but it can be enabled via ",{"type":15,"text":259,"marks":260},"vue.runtimeCompiler",[261],{"type":21,"attrs":262},{"href":263,"target":24,"rel":25,"class":26},"https:\u002F\u002Fnuxt.com\u002Fdocs\u002F4.x\u002Fapi\u002Fnuxt-config#runtimecompiler",{"type":15,"text":265},", and there are even ",{"type":15,"text":267,"marks":268},"tests covering what I was trying to do",[269],{"type":21,"attrs":270},{"href":271,"target":24,"rel":25,"class":26},"https:\u002F\u002Fgithub.com\u002Fnuxt\u002Fnuxt\u002Ftree\u002Fmain\u002Ftest\u002Ffixtures\u002Fruntime-compiler",{"type":15,"text":273},".",{"type":12,"content":275},[276],{"type":15,"text":277},"In local development, the entire pipeline worked flawlessly.",{"type":12,"content":279},[280],{"type":15,"text":281},"Then we deployed to Cloudflare.",{"type":12,"content":283},[284],{"type":15,"text":285,"marks":286},"On-the-fly template compilation is not supported in the ESM build of @vue\u002Fserver-renderer. All templates must be pre-compiled into render functions.",[287],{"type":107},{"type":12,"content":289},[290],{"type":15,"text":291},"Uh, what?",{"type":12,"content":293},[294,296,302],{"type":15,"text":295},"Here’s the relevant code in ",{"type":15,"text":297,"marks":298},"@vue\u002Fserver-renderer",[299],{"type":21,"attrs":300},{"href":301,"target":24,"rel":25,"class":26},"https:\u002F\u002Fgithub.com\u002Fvuejs\u002Fcore\u002Fblob\u002Fmain\u002Fpackages\u002Fserver-renderer\u002Fsrc\u002Fhelpers\u002FssrCompile.ts#L26",{"type":15,"text":303},", note the TODO:",{"type":305,"attrs":306,"content":308},"codeBlock",{"language":307},"ts",[309],{"type":15,"text":310},"\u002F\u002F TODO: this branch should now work in ESM builds, enable it in a minor\nif (!__CJS__) {\n  throw new Error(\n    `On-the-fly template compilation is not supported in the ESM build of ` +\n      `@vue\u002Fserver-renderer. All templates must be pre-compiled into ` +\n\t    `render functions.`,\n  )\n}",{"type":12,"content":312},[313],{"type":15,"text":314},"Armed with false hope and Claude Code, I eventually found a workaround – using a Nitro hook and a Rollup plugin to force Nuxt to bundle the CJS build of @vue\u002Fserver-renderer instead of the ESM one:",{"type":305,"attrs":316,"content":317},{"language":307},[318],{"type":15,"text":319},"export default defineNuxtConfig({\n  vue: {\n    runtimeCompiler: true,\n  },\n\n  experimental: {\n    externalVue: false,\n  },\n\n  hooks: {\n    \u002F\u002F Bundle the CJS build of @vue\u002Fserver-renderer\n    'nitro:config': (config) => {\n      config.rollupConfig = config.rollupConfig || {}\n      config.rollupConfig.plugins = config.rollupConfig.plugins || []\n      config.rollupConfig.plugins.push({\n        name: 'vue-server-renderer-cjs',\n        resolveId(id) {\n          if (id === '@vue\u002Fserver-renderer') {\n            const cjsPath = require.resolve('@vue\u002Fserver-renderer\u002Fdist\u002Fserver-renderer.cjs.js')\n            return { id: cjsPath, external: false }\n          }\n          return null\n        },\n      })\n    },\n  },\n})",{"type":12,"content":321},[322],{"type":15,"text":323},"This introduced us to the final boss:",{"type":12,"content":325},[326],{"type":15,"text":327,"marks":328},"Code generation from strings disallowed for this context.",[329],{"type":107},{"type":12,"content":331},[332],{"type":15,"text":333},"Here’s the line that triggers it:",{"type":305,"attrs":335,"content":336},{"language":307},[337],{"type":15,"text":338},"return (compileCache[cacheKey] =\n  Function('require', code)(fakeRequire))",{"type":12,"content":340},[341],{"type":15,"text":342},"Turns out, that is a complete non-starter on Cloudflare at the time of writing.",{"type":12,"content":344},[345],{"type":15,"text":346},"I built a minimal repro, confirmed the approach works fine when targeting Node, and concluded that the absolute best-case scenario on Cloudflare would be that we could make it work – without SSR.",{"type":12,"content":348},[349],{"type":15,"text":350},"That wasn’t acceptable.",{"type":81,"attrs":352,"content":353},{"level":83},[354],{"type":15,"text":355},"Back to the drawing board",{"type":12,"content":357},[358],{"type":15,"text":359},"SSR is non-negotiable, and I really didn’t want to host customer sites on a different platform just to make this work.",{"type":12,"content":361},[362,364,370],{"type":15,"text":363},"Eventually I remembered that Cloudflare had already solved a very similar problem in ",{"type":15,"text":365,"marks":366},"vibesdk",[367],{"type":21,"attrs":368},{"href":369,"target":24,"rel":25,"class":26},"https:\u002F\u002Fgithub.com\u002Fcloudflare\u002Fvibesdk",{"type":15,"text":371},": generating and running code on Workers.",{"type":12,"content":373},[374],{"type":15,"text":375},"So how did they do it?",{"type":12,"content":377},[378],{"type":15,"text":379},"I cloned the repo into .tmp and pointed Claude Code at it.",{"type":12,"content":381},[382],{"type":15,"text":383},"The answer involves a combination of:",{"type":88,"content":385},[386,396,406],{"type":91,"content":387},[388],{"type":12,"content":389},[390],{"type":15,"text":391,"marks":392},"Cloudflare Containers",[393],{"type":21,"attrs":394},{"href":395,"target":24,"rel":25,"class":26},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcontainers\u002F",{"type":91,"content":397},[398],{"type":12,"content":399},[400],{"type":15,"text":401,"marks":402},"Cloudflare Sandbox",[403],{"type":21,"attrs":404},{"href":405,"target":24,"rel":25,"class":26},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fsandbox\u002F",{"type":91,"content":407},[408],{"type":12,"content":409},[410],{"type":15,"text":411,"marks":412},"Workers for Platforms",[413],{"type":21,"attrs":414},{"href":415,"target":24,"rel":25,"class":26},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-for-platforms\u002Fworkers-for-platforms\u002F",{"type":12,"content":417},[418],{"type":15,"text":419},"The (somewhat simplified) flow looks like this:",{"type":88,"content":421},[422,428,434,440,446],{"type":91,"content":423},[424],{"type":12,"content":425},[426],{"type":15,"text":427},"Download a Nuxt app scaffold from R2",{"type":91,"content":429},[430],{"type":12,"content":431},[432],{"type":15,"text":433},"Retrieve the site’s theme from D1",{"type":91,"content":435},[436],{"type":12,"content":437},[438],{"type":15,"text":439},"Codegen the Vue components",{"type":91,"content":441},[442],{"type":12,"content":443},[444],{"type":15,"text":445},"Build the Nuxt application",{"type":91,"content":447},[448],{"type":12,"content":449},[450],{"type":15,"text":451},"Deploy the compiled app and assets to Workers for Platforms",{"type":12,"content":453},[454],{"type":15,"text":455},"The “customer app” no longer renders anything itself. It’s now a lightweight dispatch worker that routes requests to each customer’s isolated Nuxt application.",{"type":12,"content":457},[458],{"type":15,"text":459},"This supports both:",{"type":88,"content":461},[462,474],{"type":91,"content":463},[464],{"type":12,"content":465},[466,468],{"type":15,"text":467},"subdomains on ",{"type":15,"text":469,"marks":470},"onminima.com",[471],{"type":21,"attrs":472},{"href":473,"target":24,"rel":25,"class":26},"http:\u002F\u002Fonminima.com",{"type":91,"content":475},[476],{"type":12,"content":477},[478,480],{"type":15,"text":479},"custom domains via CNAME, using ",{"type":15,"text":481,"marks":482},"SSL for SaaS",[483],{"type":21,"attrs":484},{"href":485,"target":24,"rel":25,"class":26},"https:\u002F\u002Fwww.cloudflare.com\u002Fapplication-services\u002Fproducts\u002Fssl-for-saas-providers\u002F",{"type":81,"attrs":487,"content":488},{"level":83},[489],{"type":15,"text":490},"A blessing in disguise",{"type":12,"content":492},[493],{"type":15,"text":494},"Runtime compilation meant instant theme updates. Build-time compilation meant scary new infrastructure.",{"type":12,"content":496},[497],{"type":15,"text":498},"But looking at it now, the trade-off is actually an improvement:",{"type":88,"content":500},[501,507,513,519],{"type":91,"content":502},[503],{"type":12,"content":504},[505],{"type":15,"text":506},"Customer sites are fully isolated",{"type":91,"content":508},[509],{"type":12,"content":510},[511],{"type":15,"text":512},"The full build + deploy pipeline takes ~90 seconds on average, without any real optimization yet",{"type":91,"content":514},[515],{"type":12,"content":516},[517],{"type":15,"text":518},"The runtime compilation work still powers live previews inside the CMS",{"type":91,"content":520},[521],{"type":12,"content":522},[523],{"type":15,"text":524},"Dropping the Vue runtime compiler means smaller bundles for customer sites",{"type":12,"content":526},[527],{"type":15,"text":528},"Onwards.",{"type":12},"Giving a headless CMS a head on Cloudflare Workers","giving-a-headless-cms-a-head-on-cloudflare-workers",1769818952,[534],{"name":535,"slug":536,"path":537},"Minima","minima","\u002Fminima",[],{},[],{"path":542,"site":543},"\u002Fgiving-a-headless-cms-a-head-on-cloudflare-workers",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":545,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":546,"contentType":235,"path":236},[],{"id":548,"attributes":549,"body":550,"description":26,"headline":618,"schema":619,"slug":620,"subHeadline":26,"publishedAt":621,"type":219,"categories":622,"heroImage":623,"images":630,"relationships":633,"tags":687,"permalink":688,"author":691},"article_01kakkebjwfewtvh6mhmv1n09a",{},{"type":9,"content":551},[552,563,572,581,590,599,608,617],{"type":553,"attrs":554,"content":558},"entityEmbed",{"entityId":555,"entityName":556,"entityType":557},"entity_01kakjpy6xfaj9rzraaca3bje6","NEVER ENOUGH","MusicAlbum",[559],{"type":12,"content":560},[561],{"type":15,"text":562},"Top of my Spotify wrapped this year for good reason. Love a hardcore band not afraid to sound like The Police from time to time. Glad to be witnessing this, echoes of Refused. ",{"type":553,"attrs":564,"content":567},{"entityId":565,"entityName":566,"entityType":557},"entity_01kbpdw06yesg9kswadwe36j7d","I Don't Want to See You in Heaven",[568],{"type":12,"content":569},[570],{"type":15,"text":571},"I love this band for being so unapologetically themselves. This album proves they're talented enough to make more money making less weird music.",{"type":553,"attrs":573,"content":576},{"entityId":574,"entityName":575,"entityType":557},"entity_01kakkave7fewtvh5mkqdxq946","Outrun You All",[577],{"type":12,"content":578},[579],{"type":15,"text":580},"I'm not sure how I'd even start to describe what these guys are doing, but it rules.",{"type":553,"attrs":582,"content":585},{"entityId":583,"entityName":584,"entityType":557},"entity_01kakk01m1fewtvh5457r3bstk","BODIES",[586],{"type":12,"content":587},[588],{"type":15,"text":589},"The Dark Pool was incredible, but the follow up did nothing for me. The new direction has all come together with this one. One of the best guitar tones ever put to record.",{"type":553,"attrs":591,"content":594},{"entityId":592,"entityName":593,"entityType":557},"entity_01kakkdggwfewtvh61v78373md","Clockworked",[595],{"type":12,"content":596},[597],{"type":15,"text":598},"Another all time workout album from a band which put out a few all time workout albums. Sad it's over.",{"type":553,"attrs":600,"content":603},{"entityId":601,"entityName":602,"entityType":557},"entity_01kbpefzpbesg9ksxrrf4j3yy3","Tsunami Sea",[604],{"type":12,"content":605},[606],{"type":15,"text":607},"This album sounds like they wanted to do new things, but also make sure you knew they could still do the older sound. Perfect Soul is the standout, the opening riff is perfection.",{"type":553,"attrs":609,"content":612},{"entityId":610,"entityName":611,"entityType":557},"entity_01kbpeenenesg9ksxd3e712q3q","Tiles Whisper Dreams",[613],{"type":12,"content":614},[615],{"type":15,"text":616},"If you know, you know. Mathcore at its finest.",{"type":12},"Best heavy music of 2025",{},"best-heavy-music-of-2025",1765041406,[],{"attributes":26,"caption":624,"credit":26,"height":625,"id":626,"width":625,"tags":627,"contentType":628,"path":629},"Turnstile - Never Enough",1280,"image_01kbr4nka9fk6skmtfzsjzqw80",[],"image\u002Fjpeg","org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fnever-enough-12ba3309.jpg",[631],{"attributes":26,"caption":624,"credit":26,"height":625,"id":626,"width":625,"tags":632,"contentType":628,"path":629},[],{"mentions":634},[635,645,652,659,666,673,680],{"id":555,"attributes":636,"externalUrl":642,"name":556,"schema":26,"slug":643,"type":557,"permalinks":644},{"datePublished":637,"spotifyAlbumId":640,"appleMusicAlbumId":641},{"value":638,"precision":639},"2025-01-01","year","52yD51X7yDinwlg6tbCtpP","1805820903","","never-enough",[],{"id":565,"attributes":646,"externalUrl":642,"name":566,"schema":26,"slug":650,"type":557,"permalinks":651},{"datePublished":647,"spotifyAlbumId":648,"appleMusicAlbumId":649},{"value":638,"precision":639},"3jTNWEwxFDdNCuHjc3CuHi","1794618631","i-dont-want-to-see-you-in-heaven",[],{"id":583,"attributes":653,"externalUrl":642,"name":584,"schema":26,"slug":657,"type":557,"permalinks":658},{"datePublished":654,"spotifyAlbumId":655,"appleMusicAlbumId":656},{"value":638,"precision":639},"5bJeb7bvHrxNvZ6UskCoqm","1787004036","bodies",[],{"id":592,"attributes":660,"externalUrl":642,"name":593,"schema":26,"slug":664,"type":557,"permalinks":665},{"datePublished":661,"spotifyAlbumId":662,"appleMusicAlbumId":663},{"value":638,"precision":639},"2o9l5zN6SgYLCmL5dcsDfv","1816670397","clockworked",[],{"id":601,"attributes":667,"externalUrl":642,"name":602,"schema":26,"slug":671,"type":557,"permalinks":672},{"datePublished":668,"spotifyAlbumId":669,"appleMusicAlbumId":670},{"value":638,"precision":639},"79sg58t1vRpcxudpP9uPtg","1779147456","tsunami-sea",[],{"id":610,"attributes":674,"externalUrl":642,"name":611,"schema":26,"slug":678,"type":557,"permalinks":679},{"datePublished":675,"spotifyAlbumId":676,"appleMusicAlbumId":677},{"value":638,"precision":639},"1D18fRrjJWjLk6DSh2FD2v","1825273737","tiles-whisper-dreams",[],{"id":574,"attributes":681,"externalUrl":642,"name":575,"schema":26,"slug":685,"type":557,"permalinks":686},{"datePublished":682,"spotifyAlbumId":683,"appleMusicAlbumId":684},{"value":638,"precision":639},"3dy3BgU0SuF4YyHSCmQoYc","1795792611","outrun-you-all",[],[],{"path":689,"site":690},"\u002Fbest-heavy-music-of-2025",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":692,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":693,"contentType":235,"path":236},[],{"id":695,"attributes":26,"body":696,"description":26,"headline":805,"schema":806,"slug":807,"subHeadline":26,"publishedAt":808,"type":219,"categories":809,"images":811,"relationships":815,"tags":816,"permalink":817,"author":820},"article_01k879gv6besgsf8r4jpvmsf97",{"type":9,"content":697},[698,702,706,722,740,744,753,773,783,787,791,795,802],{"type":12,"content":699},[700],{"type":15,"text":701},"Absolutely monumental milestone on Minima today.",{"type":12,"content":703},[704],{"type":15,"text":705},"Months ago, when I first experimented with a chat UI for Minima, it was obvious I needed to improve the agent experience.",{"type":12,"content":707},[708,710,714,716,720],{"type":15,"text":709},"“Research this product, and add a Product entity” ",{"type":15,"text":711,"marks":712},"worked",[713],{"type":107},{"type":15,"text":715}," but anything beyond the name, slug, and external URL was hit and miss. Maybe not ",{"type":15,"text":717,"marks":718},"incorrect",[719],{"type":107},{"type":15,"text":721},", but inconsistent and un-queryable. Not good enough for a content management system, whether it's being used by a person or an LLM.",{"type":12,"content":723},[724,726,732,734,738],{"type":15,"text":725},"That's because I originally built attributes on top of ",{"type":15,"text":727,"marks":728},"schema.org",[729],{"type":21,"attrs":730},{"href":731,"target":24,"rel":25,"class":26},"https:\u002F\u002Fschema.org",{"type":15,"text":733},". You can validate the ",{"type":15,"text":735,"marks":736},"structure",[737],{"type":107},{"type":15,"text":739}," of the schema is correct, but you can't validate whether the data being represented is correct, or consistent with other entities in the database.",{"type":12,"content":741},[742],{"type":15,"text":743},"So I decided to hit the drawing board, and built my own schema registry.",{"type":12,"content":745},[746,748,752],{"type":15,"text":747},"It’s like a strongly-typed equivalent of ",{"type":15,"text":727,"marks":749},[750],{"type":21,"attrs":751},{"href":731,"target":24,"rel":25,"class":26},{"type":15,"text":273},{"type":12,"content":754},[755,757,761,763,766,768,772],{"type":15,"text":756},"Prices are ",{"type":15,"text":758,"marks":759},"always",[760],{"type":107},{"type":15,"text":762}," stored with a currency. Dates are ",{"type":15,"text":758,"marks":764},[765],{"type":107},{"type":15,"text":767}," stored with a precision. A USB port won't work with a DisplayPort connector...but in some cases it can support a DisplayPort ",{"type":15,"text":769,"marks":770},"protocol",[771],{"type":107},{"type":15,"text":273},{"type":12,"content":774},[775,777,781],{"type":15,"text":776},"I can generate forms, UI, types, and validation schemas from it. And map back to ",{"type":15,"text":727,"marks":778},[779],{"type":21,"attrs":780},{"href":731,"target":24,"rel":25,"class":26},{"type":15,"text":782}," where necessary.",{"type":12,"content":784},[785],{"type":15,"text":786},"Now my OpenAPI docs and tool calls for entities are fully typed, with specific attributes and relationships for each type of entity.",{"type":12,"content":788},[789],{"type":15,"text":790},"Just watched an LLM research and add an OLED monitor, which was the craziest stress-test for the schema registry that I could come up with.",{"type":12,"content":792},[793],{"type":15,"text":794},"It did it first try:",{"type":796,"attrs":797},"imageNode",{"src":798,"data-source-width":799,"data-source-height":800,"data-id":801},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fagent-3aefe4ed.png",1268,690,"image_01k879r7tkesgsf8rc1gxbhj3k",{"type":12,"content":803},[804],{"type":15,"text":528},"Minima progress: agent experience edition",{},"minima-progress-agent-experience-edition",1761182805,[810],{"name":535,"slug":536,"path":537},[812],{"attributes":26,"caption":26,"credit":26,"height":800,"id":801,"width":799,"tags":813,"contentType":235,"path":814},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fagent-3aefe4ed.png",{},[],{"path":818,"site":819},"\u002Fminima-progress-agent-experience-edition",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":821,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":822,"contentType":235,"path":236},[],{"id":824,"attributes":26,"body":825,"description":26,"headline":1037,"schema":1038,"slug":1039,"subHeadline":26,"publishedAt":1040,"type":219,"categories":1041,"images":1042,"relationships":1043,"tags":1044,"permalink":1045,"author":1048},"article_01k2d6vb51ecxv4f6s97fh5r7v",{"type":9,"content":826},[827,831,835,840,846,850,860,864,871,876,880,891,895,924,928,933,937,942,946,951,955,960,964,969,973,977,996,1008,1012,1017,1021,1025,1029,1033],{"type":12,"content":828},[829],{"type":15,"text":830},"Valve didn’t start selling the Steam Deck in Australia until late 2024, nearly three years after its initial release in the US, and by that stage I was prepared to wait for either a big sale or a big leap forward in performance.",{"type":12,"content":832},[833],{"type":15,"text":834},"Eventually, Lenovo had 50% off the 16GB RAM \u002F 512GB SSD \u002F Z2 Go \u002F Windows version of the Legion Go S, at which point I couldn’t help myself.",{"type":81,"attrs":836,"content":837},{"level":83},[838],{"type":15,"text":839},"What surprised me",{"type":81,"attrs":841,"content":843},{"level":842},3,[844],{"type":15,"text":845},"Windows isn’t even the best OS for running Windows games anymore",{"type":12,"content":847},[848],{"type":15,"text":849},"The modern Windows experience is bad enough, and then you try to use it on a handheld with a small touch screen.",{"type":12,"content":851},[852,854,858],{"type":15,"text":853},"Despite having an Xbox app which can be navigated with a controller, it still ",{"type":15,"text":855,"marks":856},"feels",[857],{"type":107},{"type":15,"text":859}," like a desktop application, unlike SteamOS which feels much closer to a dedicated console OS.",{"type":12,"content":861},[862],{"type":15,"text":863},"It gets worse though – many demanding 3D games run significantly better in SteamOS (i.e. Linux) via a compatibility layer than they do in their native Windows.",{"type":865,"attrs":866},"youtube",{"src":867,"start":868,"width":869,"height":870},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=PfQCgt2wa2Q",0,640,480,{"type":81,"attrs":872,"content":873},{"level":842},[874],{"type":15,"text":875},"SteamOS",{"type":12,"content":877},[878],{"type":15,"text":879},"SteamOS now officially supports the Legion Go S, with some newer variants having it pre-installed.",{"type":12,"content":881},[882,884,890],{"type":15,"text":883},"It runs on top of Linux, and plays Windows games using a compatibility layer called Proton, a collaboration between Valve and CodeWeavers which started as a fork of ",{"type":15,"text":885,"marks":886},"Wine",[887],{"type":21,"attrs":888},{"href":889,"target":24,"rel":25,"class":26},"https:\u002F\u002Fwww.winehq.org\u002F",{"type":15,"text":273},{"type":12,"content":892},[893],{"type":15,"text":894},"The experience is pretty slick, with some impressive QOL stuff:",{"type":88,"content":896},[897,912,918],{"type":91,"content":898},[899,911],{"type":12,"content":900},[901,903,909],{"type":15,"text":902},"There's an insane amount of ",{"type":15,"text":904,"marks":905},"controller configuration",[906],{"type":21,"attrs":907},{"href":908,"target":24,"rel":25,"class":26},"https:\u002F\u002Fsteamcommunity.com\u002Fsharedfiles\u002Ffiledetails\u002F?id=2804823261",{"type":15,"text":910}," available, including the ability to download community settings, so even older games with limited controller support can be tamed",{"type":12},{"type":91,"content":913},[914],{"type":12,"content":915},[916],{"type":15,"text":917},"You can play games via streaming from the Steam app running on a PC",{"type":91,"content":919},[920],{"type":12,"content":921},[922],{"type":15,"text":923},"Multiple devices running Steam on the same network can “download” installed games from each other, instead of via the Internet",{"type":12,"content":925},[926],{"type":15,"text":927},"The main catch is that pretty much any game which requires anti-cheat software won't run.",{"type":81,"attrs":929,"content":930},{"level":842},[931],{"type":15,"text":932},"Compared to the PlayStation Portal",{"type":12,"content":934},[935],{"type":15,"text":936},"The PlayStation Portal, which is only capable of streaming games from a PlayStation 5, holds up remarkably well in comparison here. I played through a lot of Death Stranding 2 on the Portal, where the latency didn’t impact the experience much at all, and the graphical experience was much better than a AAA game running on the Legion Go S.",{"type":81,"attrs":938,"content":939},{"level":842},[940],{"type":15,"text":941},"Game Pass",{"type":12,"content":943},[944],{"type":15,"text":945},"Game Pass is compelling enough that it’s worth keeping Windows installed here, warts and all. A good mix of indies and AAA games, including day-one releases, for a reasonable monthly subscription fee.",{"type":81,"attrs":947,"content":948},{"level":842},[949],{"type":15,"text":950},"More pixels, more problems",{"type":12,"content":952},[953],{"type":15,"text":954},"The Legion Go S has a 1900x1200 display with 120Hz and VRR support, which is nice, but arguably overkill for the underlying hardware. Most of the time, you’ll be dropping the resolution far below that to get games running well.",{"type":81,"attrs":956,"content":957},{"level":842},[958],{"type":15,"text":959},"A mixed bag of performance",{"type":12,"content":961},[962],{"type":15,"text":963},"On one hand, you can have something like Cyberpunk 2077 running at 60FPS, but then Clair Obscur: Expedition 33 struggling to hold 30, even with every possible graphics setting turned down as low as possible.",{"type":81,"attrs":965,"content":966},{"level":83},[967],{"type":15,"text":968},"A note about installing SteamOS",{"type":12,"content":970},[971],{"type":15,"text":972},"Don’t waste your time with the official SteamOS installer if you want to dual boot with an existing Windows installation.",{"type":12,"content":974},[975],{"type":15,"text":976},"The current SteamOS installer is a recovery image, which requires you to fully wipe the drive. You’ll find a ton of outdated information telling you otherwise, but just trust me.",{"type":12,"content":978},[979,981,987,989,995],{"type":15,"text":980},"Just install ",{"type":15,"text":982,"marks":983},"Bazzite",[984],{"type":21,"attrs":985},{"href":986,"target":24,"rel":25,"class":26},"https:\u002F\u002Fbazzite.gg\u002F",{"type":15,"text":988},", there's dual booting ",{"type":15,"text":990,"marks":991},"instructions here",[992],{"type":21,"attrs":993},{"href":994,"target":24,"rel":25,"class":26},"https:\u002F\u002Fdocs.bazzite.gg\u002FGeneral\u002FInstallation_Guide\u002Fdual_boot_setup_guide\u002F#manual-partitioning-to-the-same-drive-for-dual-boot-setups",{"type":15,"text":273},{"type":12,"content":997},[998,1000,1006],{"type":15,"text":999},"If you’re dual booting, you’ll probably want at least a 1TB SSD. You can upgrade the SSD in these things, but ",{"type":15,"text":1001,"marks":1002},"not easily",[1003],{"type":21,"attrs":1004},{"href":1005,"target":24,"rel":25,"class":26},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=3CZedMyMxMs",{"type":15,"text":1007},". I'm making do with the 512GB I have, though with plenty of modern games weighing in at over 100GB there's not a lot of breathing room.",{"type":12,"content":1009},[1010],{"type":15,"text":1011},"You can throw in a MicroSD card, but the big caveat here is that even if you cough up for a fast one, some games won’t run well when installed on it - even indies.",{"type":81,"attrs":1013,"content":1014},{"level":83},[1015],{"type":15,"text":1016},"Should you buy one?",{"type":12,"content":1018},[1019],{"type":15,"text":1020},"It depends.",{"type":12,"content":1022},[1023],{"type":15,"text":1024},"In general, I’m very happy with it at the price I paid, but probably wouldn’t be if I'd spent the full asking price.",{"type":12,"content":1026},[1027],{"type":15,"text":1028},"If you want to play all the latest AAA games at 60FPS, you'll need to lower your expectations or wait for better hardware.",{"type":12,"content":1030},[1031],{"type":15,"text":1032},"There are much faster AMD processors in the pipeline, and a rumored PlayStation handheld in the works which actually runs the games on the device rather than requiring a PlayStation 5 to stream from.",{"type":12,"content":1034},[1035],{"type":15,"text":1036},"The Switch 2 is probably a better fit for a lot of people, particularly if you don't like the idea of tinkering and tweaking settings.","Thoughts on gaming handhelds after buying a Lenovo Legion Go S",{},"thoughts-on-gaming-handhelds-lenovo-legion-go-s",1755889410,[],[],{},[],{"path":1046,"site":1047},"\u002Fthoughts-on-gaming-handhelds-lenovo-legion-go-s",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":1049,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":1050,"contentType":235,"path":236},[],{"id":1052,"attributes":26,"body":1053,"description":26,"headline":1123,"schema":1124,"slug":1125,"subHeadline":26,"publishedAt":1126,"type":219,"categories":1127,"images":1129,"relationships":1130,"tags":1131,"permalink":1132,"author":1135},"article_01jzh3g7ewexyvc0754204ahqs",{"type":9,"content":1054},[1055,1059,1070,1074,1078,1090,1101,1105,1110,1119],{"type":12,"content":1056},[1057],{"type":15,"text":1058},"Surprising no one, I'm working on a chat UI for Minima.",{"type":12,"content":1060},[1061,1063,1069],{"type":15,"text":1062},"Having already dealt with several major version upgrades across my dependencies during the last nine months of development, Vercel's AI SDK v5 is ",{"type":15,"text":1064,"marks":1065},"now in beta",[1066],{"type":21,"attrs":1067},{"href":1068,"target":24,"rel":25,"class":26},"https:\u002F\u002Fai-sdk.dev\u002Fdocs\u002Fannouncing-ai-sdk-5-beta",{"type":15,"text":273},{"type":12,"content":1071},[1072],{"type":15,"text":1073},"I've been investigating this issue since the v5 alpha, and while I haven't cracked the underlying cause, I'm happy with the solution, so I figured I'd share it while the v5 docs are catching up.",{"type":12,"content":1075},[1076],{"type":15,"text":1077},"Once the messages array I was sending from the client to the chat endpoint contained a tool call result, the endpoint would start throwing 500 errors before the event handler began executing. I originally figured it must have been something to do with the size of the post body, but that investigation went nowhere. It's something deep in H3\u002FNitro internals that I haven't been able to get to the bottom of.",{"type":12,"content":1079},[1080,1082,1088],{"type":15,"text":1081},"I eventually found the ",{"type":15,"text":1083,"marks":1084},"Sending only the last message",[1085],{"type":21,"attrs":1086},{"href":1087,"target":24,"rel":25,"class":26},"https:\u002F\u002Fai-sdk.dev\u002Fdocs\u002Fai-sdk-ui\u002Fchatbot-message-persistence#sending-only-the-last-message",{"type":15,"text":1089}," section in the docs around message persistence, but there's two issues here – it's React only, and it's for v4.",{"type":12,"content":1091},[1092,1094,1099],{"type":15,"text":1093},"Diving into the v5 internals, I found ",{"type":15,"text":1095,"marks":1096},"prepareSendMessagesRequest",[1097],{"type":1098},"code",{"type":15,"text":1100}," in the chat transport class.",{"type":12,"content":1102},[1103],{"type":15,"text":1104},"You can configure the chat transport to send only the last message to your endpoint like so:",{"type":305,"attrs":1106,"content":1107},{"language":307},[1108],{"type":15,"text":1109},"const chat = new Chat({\n  transport: new DefaultChatTransport({\n    api,\n    prepareSendMessagesRequest({ messages }) {\n      return {\n        body: {\n          messages: [messages[messages.length - 1]],\n        },\n      }\n    },\n  }),\n})",{"type":12,"content":1111},[1112,1114,1118],{"type":15,"text":1113},"Then, in your endpoint, retrieve the existing messages for the chat from your database before you ",{"type":15,"text":1115,"marks":1116},"convertToModelMessages",[1117],{"type":1098},{"type":15,"text":273},{"type":12,"content":1120},[1121],{"type":15,"text":1122},"Hope this helps.","How to send only the last message in AI SDK v5",{},"how-to-send-only-the-last-message-in-ai-sdk-v5",1751848738,[1128],{"name":535,"slug":536,"path":537},[],{},[],{"path":1133,"site":1134},"\u002Fhow-to-send-only-the-last-message-in-ai-sdk-v5",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":1136,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":1137,"contentType":235,"path":236},[],{"id":1139,"attributes":26,"body":1140,"description":26,"headline":1356,"schema":1357,"slug":1358,"subHeadline":26,"publishedAt":1359,"type":219,"categories":1360,"images":1362,"relationships":1363,"tags":1364,"permalink":1365,"author":1368},"article_01jzbrq9fxe48stvk0dwanqnwd",{"type":9,"content":1141},[1142,1146,1150,1160,1164,1176,1188,1192,1204,1225,1230,1234,1238,1270,1274,1278,1298,1308,1320,1350,1355],{"type":12,"content":1143},[1144],{"type":15,"text":1145},"I got frustrated with how slow the Minima API was recently, and figured I'd just need to add a couple of database indexes before I could move on to the next thing.",{"type":12,"content":1147},[1148],{"type":15,"text":1149},"That was not the case.",{"type":12,"content":1151},[1152,1158],{"type":15,"text":1153,"marks":1154},"Nuxt Hub",[1155],{"type":21,"attrs":1156},{"href":1157,"target":24,"rel":25,"class":26},"https:\u002F\u002Fhub.nuxt.com\u002F",{"type":15,"text":1159}," can be used to develop a Nuxt application running locally, against remote Cloudflare resources like D1. This is great for DX, but it also hid real-world performance issues from me until I started dogfooding Minima's public API.",{"type":12,"content":1161},[1162],{"type":15,"text":1163},"In short, everything in your server bundle comes at a cost to the time it takes your Worker to start, and therefore your TTFB.",{"type":12,"content":1165},[1166,1168,1174],{"type":15,"text":1167},"This is ",{"type":15,"text":1169,"marks":1170},"documented behavior",[1171],{"type":21,"attrs":1172},{"href":1173,"target":24,"rel":25,"class":26},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fplatform\u002Flimits\u002F#worker-size",{"type":15,"text":1175}," but I hadn't correctly internalized it. I was under the impression that for frameworks like Nuxt, which automatically code split your server bundle, you were only paying the startup time for the main server chunk plus whatever else an endpoint might need.",{"type":12,"content":1177},[1178,1180,1186],{"type":15,"text":1179},"Seeing ",{"type":15,"text":1181,"marks":1182},"this issue on GitHub",[1183],{"type":21,"attrs":1184},{"href":1185,"target":24,"rel":25,"class":26},"https:\u002F\u002Fgithub.com\u002Fcloudflare\u002Fworkerd\u002Fissues\u002F2372",{"type":15,"text":1187}," was what it took for me to get it.",{"type":12,"content":1189},[1190],{"type":15,"text":1191},"So how bad was it?",{"type":12,"content":1193},[1194,1196,1202],{"type":15,"text":1195},"I created a test endpoint which didn't touch the database, just returned a ",{"type":15,"text":1197,"marks":1198},"typeid",[1199],{"type":21,"attrs":1200},{"href":1201,"target":24,"rel":25,"class":26},"https:\u002F\u002Fgithub.com\u002Fjetify-com\u002Ftypeid-js",{"type":15,"text":1203},". It was taking between 700ms and 1,000ms to respond. Sad!",{"type":12,"content":1205},[1206,1208,1214,1218,1223],{"type":15,"text":1207},"The ",{"type":15,"text":1209,"marks":1210},"Nuxt CLI has an ",[1211],{"type":21,"attrs":1212},{"href":1213,"target":24,"rel":25,"class":26},"https:\u002F\u002Fnuxt.com\u002Fdocs\u002Fapi\u002Fcommands\u002Fanalyze",{"type":15,"text":1215,"marks":1216},"analyze",[1217],{"type":1098},{"type":15,"text":1219,"marks":1220}," command",[1221],{"type":21,"attrs":1222},{"href":1213,"target":24,"rel":25,"class":26},{"type":15,"text":1224}," which generates a treemap of your production client and server bundles (just make sure you don't accidentally deploy the resulting build):",{"type":305,"attrs":1226,"content":1227},{"language":26},[1228],{"type":15,"text":1229},"npx nuxt analyze",{"type":12,"content":1231},[1232],{"type":15,"text":1233},"Armed with this, I started ripping pieces of the app out, deploying to workers.dev, and running ApacheBench on my test endpoint.",{"type":12,"content":1235},[1236],{"type":15,"text":1237},"The main offenders were:",{"type":88,"content":1239},[1240,1246,1252,1258,1264],{"type":91,"content":1241},[1242],{"type":12,"content":1243},[1244],{"type":15,"text":1245},"Shiki, which I was using for code highlighting in Tiptap",{"type":91,"content":1247},[1248],{"type":12,"content":1249},[1250],{"type":15,"text":1251},"An endpoint which used a bunch of remark\u002Frehype dependencies for parsing HTML into Markdown",{"type":91,"content":1253},[1254],{"type":12,"content":1255},[1256],{"type":15,"text":1257},"The Vue REPL & Monaco Editor",{"type":91,"content":1259},[1260],{"type":12,"content":1261},[1262],{"type":15,"text":1263},"Cloudflare's fork of Puppeteer",{"type":91,"content":1265},[1266],{"type":12,"content":1267},[1268],{"type":15,"text":1269},"One massive (1.3MB) JSON file",{"type":12,"content":1271},[1272],{"type":15,"text":1273},"Each time one of these things got ripped out it made a measurable difference, and with all of them gone, I was seeing API responses in under 100ms consistently.",{"type":12,"content":1275},[1276],{"type":15,"text":1277},"Moral of the story: stay as close to 1MB gzipped as possible.",{"type":12,"content":1279},[1280,1282,1288,1290,1296],{"type":15,"text":1281},"The best way to do full-stack Cloudflare right now appears to be to use individual workers as services. Unfortunately there's no workable solution for doing ",{"type":15,"text":1283,"marks":1284},"RPC",[1285],{"type":21,"attrs":1286},{"href":1287,"target":24,"rel":25,"class":26},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Frpc\u002F",{"type":15,"text":1289}," or ",{"type":15,"text":1291,"marks":1292},"remote service bindings",[1293],{"type":21,"attrs":1294},{"href":1295,"target":24,"rel":25,"class":26},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fdevelopment-testing\u002F#remote-bindings",{"type":15,"text":1297}," with Nuxt Hub yet, so I'm using a hacky \"fetch in dev, RPC in prod\" workaround for the time being.",{"type":12,"content":1299},[1300,1302,1306],{"type":15,"text":1301},"One thing which was surprisingly challenging was getting code highlighting in Tiptap to work with a CDN build of ",{"type":15,"text":1303,"marks":1304},"any",[1305],{"type":107},{"type":15,"text":1307}," code highlighter.",{"type":12,"content":1309},[1310,1312,1318],{"type":15,"text":1311},"Eventually I figured out that Tiptap's ",{"type":15,"text":1313,"marks":1314},"CodeBlockLowlight",[1315],{"type":21,"attrs":1316},{"href":1317,"target":24,"rel":25,"class":26},"https:\u002F\u002Ftiptap.dev\u002Fdocs\u002Feditor\u002Fextensions\u002Fnodes\u002Fcode-block-lowlight",{"type":15,"text":1319}," extension allowed you to pass in an instance of Lowlight, rather than just importing it, so it didn't need to be in my bundle.",{"type":12,"content":1321},[1322,1324,1330,1332,1336,1338,1342,1344,1348],{"type":15,"text":1323},"I couldn't find anything on the web about using ",{"type":15,"text":1325,"marks":1326},"esm.sh",[1327],{"type":21,"attrs":1328},{"href":1329,"target":24,"rel":25,"class":26},"https:\u002F\u002Fesm.sh",{"type":15,"text":1331}," imports with Vue\u002FNuxt, but eventually figured it out with trial and error. Then after refactoring from ",{"type":15,"text":1333,"marks":1334},"useEditor",[1335],{"type":1098},{"type":15,"text":1337}," to ",{"type":15,"text":1339,"marks":1340},"new Editor",[1341],{"type":1098},{"type":15,"text":1343}," in ",{"type":15,"text":1345,"marks":1346},"onMounted",[1347],{"type":1098},{"type":15,"text":1349}," I had something working, that looked like this:",{"type":305,"attrs":1351,"content":1352},{"language":307},[1353],{"type":15,"text":1354},"onMounted(() => {\n  const { common, createLowlight } = await import('https:\u002F\u002Fesm.sh\u002Flowlight@3?bundle')\n  \u002F\u002F note: no .then(module => module.default) needed here\n\n  editor = new Editor({\n    extensions: [\n      CodeBlockLowlight.configure({\n        lowlight,\n      }),\n    ],\n    \u002F\u002F ...\n  })\n})",{"type":12},"On Cloudflare Workers, your TTFB grows with your server bundle",{},"on-cloudflare-workers-your-ttfb-grows-with-your-server-bundle",1751683227,[1361],{"name":535,"slug":536,"path":537},[],{},[],{"path":1366,"site":1367},"\u002Fon-cloudflare-workers-your-ttfb-grows-with-your-server-bundle",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":1369,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":1370,"contentType":235,"path":236},[],{"id":1372,"attributes":26,"body":1373,"description":26,"headline":1505,"schema":1506,"slug":1507,"subHeadline":26,"publishedAt":1508,"type":219,"categories":1509,"images":1510,"relationships":1517,"tags":1518,"permalink":1519,"author":1522},"article_01jw52aaa3fq8t66rz1c281d9e",{"type":9,"content":1374},[1375,1379,1383,1387,1397,1401,1406,1417,1421,1432,1442,1446,1456,1460,1464,1470,1480,1484,1490,1500,1504],{"type":12,"content":1376},[1377],{"type":15,"text":1378},"The music industry had a golden age thanks to the Compact Disc. Then came a perfect storm of technological advancements – the web, the MP3 format, Winamp, and Napster.",{"type":12,"content":1380},[1381],{"type":15,"text":1382},"Now, after thirty years of the banner ad, the ad-supported web is having its Napster moment.",{"type":12,"content":1384},[1385],{"type":15,"text":1386},"When I first sat down to write this, I felt this was disastrous. Probably echoes of a past life, when banner ads put a roof over my head.",{"type":12,"content":1388},[1389,1391,1395],{"type":15,"text":1390},"Then I remembered a time a bit further back. Being a nerdy kid completely awestruck by the early web. Making stuff to put on it, ",{"type":15,"text":1392,"marks":1393},"just because",[1394],{"type":107},{"type":15,"text":1396},". When every site looked different. When you'd link to someone's weird site from your weird site and they'd send you an email to say hi.",{"type":12,"content":1398},[1399],{"type":15,"text":1400},"Maybe a bit more of that isn't such a bad thing.",{"type":81,"attrs":1402,"content":1403},{"level":83},[1404],{"type":15,"text":1405},"How things worked, until they didn't",{"type":12,"content":1407},[1408,1410,1416],{"type":15,"text":1409},"Google crawled your site, sent you visitors, and likely served most of the ads on your site too. Not that ",{"type":15,"text":1411,"marks":1412},"you had any choice in the matter",[1413],{"type":21,"attrs":1414},{"href":1415,"target":24,"rel":25,"class":26},"https:\u002F\u002Fwww.justice.gov\u002Fopa\u002Fpr\u002Fdepartment-justice-prevails-landmark-antitrust-case-against-google",{"type":15,"text":273},{"type":12,"content":1418},[1419],{"type":15,"text":1420},"They told you how to be a good boy. Structured data, Accelerated Mobile Pages, Core Web Vitals...and you were a good boy, and hoped you would get a pat on the head.",{"type":12,"content":1422},[1423,1425,1431],{"type":15,"text":1424},"But now they summarize you at the top of the search results – and ",{"type":15,"text":1426,"marks":1427},"link to themselves in those summaries",[1428],{"type":21,"attrs":1429},{"href":1430,"target":24,"rel":25,"class":26},"https:\u002F\u002Fzyppy.com\u002Flist\u002Fai-overviews-to-google-ads\u002F",{"type":15,"text":273},{"type":12,"content":1433},[1434,1436,1440],{"type":15,"text":1435},"But, and I grit my teeth as I write this, this isn’t ",{"type":15,"text":1437,"marks":1438},"all",[1439],{"type":107},{"type":15,"text":1441}," Google’s fault.",{"type":12,"content":1443},[1444],{"type":15,"text":1445},"Google had to kill its business before someone else did.",{"type":12,"content":1447},[1448,1450,1454],{"type":15,"text":1449},"When I search for information the ",{"type":15,"text":1451,"marks":1452},"old",[1453],{"type":107},{"type":15,"text":1455}," way, it feels like I need to put on a hazmat suit.",{"type":12,"content":1457},[1458],{"type":15,"text":1459},"Have you tried finding trustworthy information about what the best [product] is recently?",{"type":12,"content":1461},[1462],{"type":15,"text":1463},"Do you want to come back to this recipe site?",{"type":796,"attrs":1465},{"src":1466,"data-source-width":1467,"data-source-height":1468,"data-id":1469},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Frecipe-c67dbc42.jpg",1170,1934,"image_01jw53bfatfq8t66s6wxze0zta",{"type":12,"content":1471},[1472,1478],{"type":15,"text":1473,"marks":1474},"Brave Search",[1475],{"type":21,"attrs":1476},{"href":1477,"target":24,"rel":25,"class":26},"https:\u002F\u002Fsearch.brave.com\u002F",{"type":15,"text":1479}," has been kicking Google’s ass for years, and I find the AI summaries useful more often than not.",{"type":12,"content":1481},[1482],{"type":15,"text":1483},"They actually link to sites too:",{"type":796,"attrs":1485},{"src":1486,"data-source-width":1487,"data-source-height":1488,"data-id":1489},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002FScreenshot 2025-05-26 at 5.41.37 AM-9a1776ba.png",1434,1432,"image_01jw5cfg8me8h9gff0m2qayn44",{"type":12,"content":1491},[1492,1494,1498],{"type":15,"text":1493},"Back when I was still in publishing, it was obvious that things had become zero sum. We went from a few sites writing the same story to a few ",{"type":15,"text":1495,"marks":1496},"thousand",[1497],{"type":107},{"type":15,"text":1499}," sites writing the same story. The end game here was never going to be pretty.",{"type":12,"content":1501},[1502],{"type":15,"text":1503},"I have no idea whether a new, viable way to reward people for publishing high quality information on the web will emerge – despite it being essential for every new training run.",{"type":12},"The web is dead, and we have killed it",{},"the-web-is-dead-and-we-have-killed-it",1748234355,[],[1511,1514],{"attributes":26,"caption":26,"credit":26,"height":1468,"id":1469,"width":1467,"tags":1512,"contentType":628,"path":1513},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Frecipe-c67dbc42.jpg",{"attributes":26,"caption":26,"credit":26,"height":1488,"id":1489,"width":1487,"tags":1515,"contentType":235,"path":1516},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002FScreenshot 2025-05-26 at 5.41.37 AM-9a1776ba.png",{},[],{"path":1520,"site":1521},"\u002Fthe-web-is-dead-and-we-have-killed-it",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":1523,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":1524,"contentType":235,"path":236},[],{"id":1526,"attributes":26,"body":1527,"description":26,"headline":1576,"schema":1587,"slug":1588,"subHeadline":26,"publishedAt":1589,"type":219,"categories":1590,"images":1591,"relationships":1592,"tags":1593,"permalink":1594,"author":1597},"article_01jsav1s20fexadqzjphxp5mcf",{"type":9,"content":1528},[1529,1540,1560,1571,1579,1583],{"type":12,"content":1530},[1531,1533,1539],{"type":15,"text":1532},"You can write a code-editing agent in ",{"type":15,"text":1534,"marks":1535},"fewer than 400 LOC",[1536],{"type":21,"attrs":1537},{"href":1538,"target":24,"rel":25,"class":26},"https:\u002F\u002Fampcode.com\u002Fhow-to-build-an-agent",{"type":15,"text":273},{"type":12,"content":1541},[1542,1544,1550,1552,1558],{"type":15,"text":1543},"You can ",{"type":15,"text":1545,"marks":1546},"download these models",[1547],{"type":21,"attrs":1548},{"href":1549,"target":24,"rel":25,"class":26},"https:\u002F\u002Fhuggingface.co\u002F",{"type":15,"text":1551},", and ",{"type":15,"text":1553,"marks":1554},"run them",[1555],{"type":21,"attrs":1556},{"href":1557,"target":24,"rel":25,"class":26},"https:\u002F\u002Flmstudio.ai\u002F",{"type":15,"text":1559}," on any recent consumer Mac or gaming PC.",{"type":12,"content":1561},[1562,1564,1570],{"type":15,"text":1563},"The system prompts of some of the fastest growing companies in the world have been leaked, ",{"type":15,"text":1565,"marks":1566},"and are available on GitHub",[1567],{"type":21,"attrs":1568},{"href":1569,"target":24,"rel":25,"class":26},"https:\u002F\u002Fgithub.com\u002Fx1xhlol\u002Fsystem-prompts-and-models-of-ai-tools",{"type":15,"text":273},{"type":12,"content":1572},[1573,1575],{"type":15,"text":1574},"Every software company is building a text input, underneath another variation of ",{"type":15,"text":1576,"marks":1577},"What do you want to build?",[1578],{"type":107},{"type":12,"content":1580},[1581],{"type":15,"text":1582},"There's billions to be made, but there's no moat, and the incumbents are coming.",{"type":12,"content":1584},[1585],{"type":15,"text":1586},"My advice is to go deep on something you care about.",{},"what-do-you-want-to-build",1745285744,[],[],{},[],{"path":1595,"site":1596},"\u002Fwhat-do-you-want-to-build",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":1598,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":1599,"contentType":235,"path":236},[],{"id":1601,"attributes":26,"body":1602,"description":26,"headline":1746,"schema":1747,"slug":1748,"subHeadline":26,"publishedAt":1749,"type":219,"categories":1750,"images":1752,"relationships":1753,"tags":1754,"permalink":1755,"author":1758},"article_01jjfq83s2f269tqq1ma6ypm0z",{"type":9,"content":1603},[1604,1608,1668,1673,1681,1686],{"type":12,"content":1605},[1606],{"type":15,"text":1607},"Just got through a monster upgrade\u002Frefactor.",{"type":88,"content":1609},[1610,1616,1623,1637,1656,1662],{"type":91,"content":1611},[1612],{"type":12,"content":1613},[1614],{"type":15,"text":1615},"Upgraded Nuxt Hub to the latest version",{"type":91,"content":1617},[1618,1622],{"type":12,"content":1619},[1620],{"type":15,"text":1621},"Migrated to a pnpm workspace with a separate customer app for CNAMEs, and a shared Nuxt layer",{"type":12},{"type":91,"content":1624},[1625],{"type":12,"content":1626},[1627,1629,1635],{"type":15,"text":1628},"Migrated to Cloudflare Static Assets dir (",{"type":15,"text":1630,"marks":1631},"docs",[1632],{"type":21,"attrs":1633},{"href":1634,"target":24,"rel":25,"class":26},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fstatic-assets\u002F",{"type":15,"text":1636},")",{"type":91,"content":1638},[1639,1655],{"type":12,"content":1640},[1641,1643,1647,1649,1654],{"type":15,"text":1642},"Migrated to ",{"type":15,"text":1644,"marks":1645},"wrangler.json",[1646],{"type":1098},{"type":15,"text":1648}," (",{"type":15,"text":1630,"marks":1650},[1651],{"type":21,"attrs":1652},{"href":1653,"target":24,"rel":25,"class":26},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fwrangler\u002Fconfiguration\u002F",{"type":15,"text":1636},{"type":12},{"type":91,"content":1657},[1658],{"type":12,"content":1659},[1660],{"type":15,"text":1661},"Rewrote the Prosemirror to Vue SSR renderer (Cursor was an absolute beast here)",{"type":91,"content":1663},[1664],{"type":12,"content":1665},[1666],{"type":15,"text":1667},"Ripped out the Vue REPL embed as it was causing too much pain for a “nice to have” feature...if\u002Fwhen I come back to this, figure out a way to do a CDN-only implementation",{"type":81,"attrs":1669,"content":1670},{"level":83},[1671],{"type":15,"text":1672},"Next Steps",{"type":88,"content":1674},[1675],{"type":91,"content":1676},[1677],{"type":12,"content":1678},[1679],{"type":15,"text":1680},"Rebuild [REDACTED] with Minima as the headless CMS to dogfood the API, and think about a TypeScript API client package",{"type":81,"attrs":1682,"content":1683},{"level":83},[1684],{"type":15,"text":1685},"Gotchas",{"type":88,"content":1687},[1688,1698,1716,1728],{"type":91,"content":1689},[1690],{"type":12,"content":1691},[1692,1696],{"type":15,"text":1693,"marks":1694},"Couldn't resolve component \"default\" at \"\u002F:path(.*)*\"",[1695],{"type":1098},{"type":15,"text":1697}," was not, in fact, an issue with paths",{"type":91,"content":1699},[1700],{"type":12,"content":1701},[1702,1704,1708,1710,1715],{"type":15,"text":1703},"Nitro has a separate ",{"type":15,"text":1705,"marks":1706},"compatibilityDate",[1707],{"type":1098},{"type":15,"text":1709}," which needed updating for the Cloudflare Static Assets directory to work (",{"type":15,"text":1630,"marks":1711},[1712],{"type":21,"attrs":1713},{"href":1714,"target":24,"rel":25,"class":26},"https:\u002F\u002Fnitro.build\u002Fdeploy\u002Fproviders\u002Fcloudflare#cloudflare-module-workers",{"type":15,"text":1636},{"type":91,"content":1717},[1718],{"type":12,"content":1719},[1720,1722,1726],{"type":15,"text":1721},"Used ",{"type":15,"text":1723,"marks":1724},"wrangler secret put",[1725],{"type":1098},{"type":15,"text":1727}," to deal with the self-hosted Nuxt Hub env stuff rather than patching the dependency like I did last time",{"type":91,"content":1729},[1730],{"type":12,"content":1731},[1732,1734,1738,1740,1744],{"type":15,"text":1733},"Cloudflare SSL for SaaS routes tripped me up again, fix was using ",{"type":15,"text":1735,"marks":1736},"*.*",[1737],{"type":1098},{"type":15,"text":1739}," for the fallback origin route and ",{"type":15,"text":1741,"marks":1742},"minima.ltd\u002F*",[1743],{"type":1098},{"type":15,"text":1745}," for the app route","Minima progress, January 2025 edition",{},"minima-progress-january-2025-edition",1737841970,[1751],{"name":535,"slug":536,"path":537},[],{},[],{"path":1756,"site":1757},"\u002Fminima-progress-january-2025-edition",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":1759,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":1760,"contentType":235,"path":236},[],{"id":1762,"attributes":26,"body":1763,"description":26,"headline":1907,"schema":1908,"slug":1909,"subHeadline":26,"publishedAt":1910,"type":219,"categories":1911,"heroImage":1916,"images":1921,"relationships":1952,"tags":1953,"permalink":1954,"author":1957},"article_01je2g7y1fe8gajckmj8gzs2dr",{"type":9,"content":1764},[1765,1770,1774,1778,1783,1787,1791,1796,1800,1804,1809,1819,1823,1828,1832,1836,1841,1845,1849,1854,1858,1862,1867,1871,1875,1880,1884,1888,1893,1902,1906],{"type":81,"attrs":1766,"content":1767},{"level":83},[1768],{"type":15,"text":1769},"Knocked Loose - You Won't Go Before You're Supposed To",{"type":12,"content":1771},[1772],{"type":15,"text":1773},"Hard to believe that the latest band to break out from the genre into the mainstream is so heavy. Pig squeals on late night TV, let's go.",{"type":796,"attrs":1775},{"src":1776,"data-source-width":869,"data-source-height":869,"data-id":1777},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fyou wont go before youre supposed to-a45ab5b6.jpeg","image_01jpe61kpzfvkb5rat0vnp79n2",{"type":81,"attrs":1779,"content":1780},{"level":83},[1781],{"type":15,"text":1782},"ERRA - CURE",{"type":12,"content":1784},[1785],{"type":15,"text":1786},"If this album doesn't make you want to pick up a guitar there's something wrong with you.",{"type":796,"attrs":1788},{"src":1789,"data-source-width":869,"data-source-height":869,"data-id":1790},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fcure-0c4e6b28.jpeg","image_01jpe5epxje4etxax3bgtfxak1",{"type":81,"attrs":1792,"content":1793},{"level":83},[1794],{"type":15,"text":1795},"Cane Hill - a piece of me i never let you find.",{"type":12,"content":1797},[1798],{"type":15,"text":1799},"I think this is the freshest sound in metalcore right now.",{"type":796,"attrs":1801},{"src":1802,"data-source-width":869,"data-source-height":869,"data-id":1803},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fa piece of me i never let you find-3e954570.jpeg","image_01jpe62sjbfvkb5rbcrfsd6wse",{"type":81,"attrs":1805,"content":1806},{"level":83},[1807],{"type":15,"text":1808},"Poppy - Negative Spaces",{"type":12,"content":1810},[1811,1813,1817],{"type":15,"text":1812},"If ",{"type":15,"text":1814,"marks":1815},"they're all around us ",[1816],{"type":107},{"type":15,"text":1818},"doesn't get used in a zombie film soundtrack I'll be disappointed.",{"type":796,"attrs":1820},{"src":1821,"data-source-width":869,"data-source-height":869,"data-id":1822},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fnegative spaces-0f0ba392.jpeg","image_01jpe63pv9fvkb5rbtqz2zhzd1",{"type":81,"attrs":1824,"content":1825},{"level":83},[1826],{"type":15,"text":1827},"Better Lovers - Highly Irresponsible",{"type":12,"content":1829},[1830],{"type":15,"text":1831},"One of the best opening tracks to an album ever.",{"type":796,"attrs":1833},{"src":1834,"data-source-width":869,"data-source-height":869,"data-id":1835},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fhighly irresponsible-00b56815.jpeg","image_01jpe5j814e4etxay4mvw1nvf3",{"type":81,"attrs":1837,"content":1838},{"level":83},[1839],{"type":15,"text":1840},"Alpha Wolf - Half Living Things",{"type":12,"content":1842},[1843],{"type":15,"text":1844},"Nu metal vibes, if you couldn't tell from the cover.",{"type":796,"attrs":1846},{"src":1847,"data-source-width":869,"data-source-height":869,"data-id":1848},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fhalf living things-f92b6713.jpeg","image_01jpe4dsxye4d9vc8kj8az7d2g",{"type":81,"attrs":1850,"content":1851},{"level":83},[1852],{"type":15,"text":1853},"Speed - ONLY ONE MODE",{"type":12,"content":1855},[1856],{"type":15,"text":1857},"In which the frontman being a classically-trained flutist leads to the crossover we didn't know we needed.",{"type":796,"attrs":1859},{"src":1860,"data-source-width":869,"data-source-height":869,"data-id":1861},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fonly one mode-303e484d.jpeg","image_01jpe5qp54e4etxazgy4c6f93n",{"type":81,"attrs":1863,"content":1864},{"level":83},[1865],{"type":15,"text":1866},"Night Verses - Every Sound Has A Color In The Valley Of Night",{"type":12,"content":1868},[1869],{"type":15,"text":1870},"Guys who can really play their instruments, with no singing (or screaming). Kind of like a heavier Animals as Leaders.",{"type":796,"attrs":1872},{"src":1873,"data-source-width":869,"data-source-height":869,"data-id":1874},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fevery sound has a color-5b51bb9f.jpeg","image_01jpe5rj3we4etxb07qwn6sf7r",{"type":81,"attrs":1876,"content":1877},{"level":83},[1878],{"type":15,"text":1879},"House of Protection - GALORE",{"type":12,"content":1881},[1882],{"type":15,"text":1883},"Late addition. Members of The Chariot and Night Verses, but doesn't sound like it.",{"type":796,"attrs":1885},{"src":1886,"data-source-width":869,"data-source-height":869,"data-id":1887},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fgalore-eff0d9ab.jpeg","image_01jpe5rwpae4etxb0hm4zpwa07",{"type":81,"attrs":1889,"content":1890},{"level":83},[1891],{"type":15,"text":1892},"Ocean Grove - ODDWORLD",{"type":12,"content":1894},[1895,1897,1901],{"type":15,"text":1896},"Another late addition, which has grown on me a lot. By far the best work since their incredible debut album ",{"type":15,"text":1898,"marks":1899},"The Rhapsody Tapes",[1900],{"type":107},{"type":15,"text":273},{"type":796,"attrs":1903},{"src":1904,"data-source-width":869,"data-source-height":869,"data-id":1905},"\u002Fapi\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Fblob\u002Forg_01jakhtww5fk6b0jmxj0qfp9rf\u002Foddworld-855698fc.jpeg","image_01jpe5sbkze4etxb15bmh5qag7",{"type":12},"My picks for best heavy music of 2024",{},"my-picks-for-best-heavy-music-of-2024",1733103450,[1912],{"name":1913,"slug":1914,"path":1915},"Music","music","\u002Fmusic",{"attributes":26,"caption":26,"credit":26,"height":1917,"id":1918,"width":1917,"tags":1919,"contentType":628,"path":1920},1200,"image_01jdyy3j2ge00t5x5ctf9j0dhq",[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fyou-wont-go-before-youre-supposed-to-886e726f.jpg",[1922,1925,1928,1931,1934,1937,1940,1943,1946,1949],{"attributes":26,"caption":26,"credit":26,"height":869,"id":1848,"width":869,"tags":1923,"contentType":628,"path":1924},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fhalf living things-f92b6713.jpeg",{"attributes":26,"caption":26,"credit":26,"height":869,"id":1790,"width":869,"tags":1926,"contentType":628,"path":1927},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fcure-0c4e6b28.jpeg",{"attributes":26,"caption":26,"credit":26,"height":869,"id":1835,"width":869,"tags":1929,"contentType":628,"path":1930},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fhighly irresponsible-00b56815.jpeg",{"attributes":26,"caption":26,"credit":26,"height":869,"id":1861,"width":869,"tags":1932,"contentType":628,"path":1933},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fonly one mode-303e484d.jpeg",{"attributes":26,"caption":26,"credit":26,"height":869,"id":1874,"width":869,"tags":1935,"contentType":628,"path":1936},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fevery sound has a color-5b51bb9f.jpeg",{"attributes":26,"caption":26,"credit":26,"height":869,"id":1887,"width":869,"tags":1938,"contentType":628,"path":1939},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fgalore-eff0d9ab.jpeg",{"attributes":26,"caption":26,"credit":26,"height":869,"id":1905,"width":869,"tags":1941,"contentType":628,"path":1942},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Foddworld-855698fc.jpeg",{"attributes":26,"caption":26,"credit":26,"height":869,"id":1777,"width":869,"tags":1944,"contentType":628,"path":1945},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fyou wont go before youre supposed to-a45ab5b6.jpeg",{"attributes":26,"caption":26,"credit":26,"height":869,"id":1803,"width":869,"tags":1947,"contentType":628,"path":1948},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fa piece of me i never let you find-3e954570.jpeg",{"attributes":26,"caption":26,"credit":26,"height":869,"id":1822,"width":869,"tags":1950,"contentType":628,"path":1951},[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fnegative spaces-0f0ba392.jpeg",{},[],{"path":1955,"site":1956},"\u002Fmy-picks-for-best-heavy-music-of-2024",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":1958,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":1959,"contentType":235,"path":236},[],{"id":1961,"attributes":26,"body":1962,"description":26,"headline":2047,"schema":2048,"slug":2049,"subHeadline":26,"publishedAt":2050,"type":219,"categories":2051,"heroImage":2056,"images":2061,"relationships":2062,"tags":2063,"permalink":2064,"author":2067},"article_01jbqjckkpe4fagc6q5hksbze8",{"type":9,"content":1963},[1964,1968,1972,1976,1980,1984,2043],{"type":12,"content":1965},[1966],{"type":15,"text":1967},"A long time ago, I identified as a music producer. While I've long since left that world, I still tinker with music for fun.",{"type":12,"content":1969},[1970],{"type":15,"text":1971},"When I realised how much of a barrier it was to be reliant on a laptop and Ableton Live to make electronic music, I started piecing together a DAWless setup, and I've amassed quite a collection of little noise makers from Teenage Engineering, Korg, and Behringer. It's been a ton of fun, for me and my young kids.",{"type":12,"content":1973},[1974],{"type":15,"text":1975},"I've been on the lookout for bit of kit which allowed me to sample\u002Frecord what I was doing, sans computer. The Zoom LiveTrak L6 mixer was looking good, but the Ableton Move got announced before I hit the button.",{"type":12,"content":1977},[1978],{"type":15,"text":1979},"After a week or so, the GAS was too much.",{"type":12,"content":1981},[1982],{"type":15,"text":1983},"Here are my thoughts after about a week of tinkering.",{"type":88,"content":1985},[1986,1992,1999,2010,2024,2031,2037],{"type":91,"content":1987},[1988],{"type":12,"content":1989},[1990],{"type":15,"text":1991},"The I\u002FO is very limited. 2-in\u002F2-out over 3.5mm jacks, and MIDI over USB, which itself is limited – it can't send and receive MIDI simultaneously. This also rules out syncing gear via CV, though I'd bet we'll see an affordable solution for that, either from Ableton itself or a third party.",{"type":91,"content":1993},[1994,1998],{"type":12,"content":1995},[1996],{"type":15,"text":1997},"The only bit of kit I have which handles USB MIDI is the Behringer Edge, [heavily inspired by\u002Fa clone of] the Moog DFAM. Getting them playing nicely together was quick and easy, and the ability to easily record its output is exactly what I was looking for.",{"type":12},{"type":91,"content":2000},[2001],{"type":12,"content":2002},[2003,2005,2009],{"type":15,"text":2004},"The killer feature for me so far has been the capture functionality. If you're noodling on the pads and something works, you just hit the dedicated button to capture what you played to a clip ",{"type":15,"text":2006,"marks":2007},"even if you weren't recording at the time",[2008],{"type":107},{"type":15,"text":273},{"type":91,"content":2011},[2012],{"type":12,"content":2013},[2014,2016,2022],{"type":15,"text":2015},"To say the Ableton Live workflow integration is in its infancy right now is putting it lightly. Getting Drift patches from Live onto the Move is painful, starting with a ",{"type":15,"text":2017,"marks":2018},"template",[2019],{"type":21,"attrs":2020},{"href":2021,"target":24,"rel":25,"class":26},"https:\u002F\u002Fhelp.ableton.com\u002Fhc\u002Fen-us\u002Farticles\u002F15616909965596-Presets-on-Move",{"type":15,"text":2023},", exporting the patch as an \"ablbundle\" (which can't currently be loaded back into Live), and then loading it onto the Move using the Move Manager software. This isn't possible for Wavetable patches. You also can't take a Live project and export it for use on Move, only vice versa. This will no doubt improve over time, but it's a bummer right now.",{"type":91,"content":2025},[2026,2030],{"type":12,"content":2027},[2028],{"type":15,"text":2029},"On that note, you can't access all the parameters of the onboard synths (Drift & Wavetable). Only the parameters which have been mapped to the macro controls for that particular patch.",{"type":12},{"type":91,"content":2032},[2033],{"type":12,"content":2034},[2035],{"type":15,"text":2036},"While you can use the \"Control Live\" mode of the Move with Live 11, you will want to own Live 12 to make the most of it, so factor that into the price. I upgraded from Live 11 at the same time.",{"type":91,"content":2038},[2039],{"type":12,"content":2040},[2041],{"type":15,"text":2042},"You will have to swallow your pride and read the manual (and likely watch a few YouTube videos) in order to get much out of the device, as the panel is 100% icons, and there's plenty of functionality which requires menu diving.",{"type":12,"content":2044},[2045],{"type":15,"text":2046},"Limitations aside, it's a nice piece of gear. It feels solid, and it ticks some big boxes for me – its comfortable to use on the couch, it can fill drum machine duties with other gear, and it can sample other gear.","I bought an Ableton Move",{},"i-bought-an-ableton-move",1730589118,[2052],{"name":2053,"slug":2054,"path":2055},"Music Production","music-production","\u002Fcategory\u002Fmusic-production",{"attributes":26,"caption":26,"credit":26,"height":625,"id":2057,"width":2058,"tags":2059,"contentType":628,"path":2060},"image_01jcr4awghenf8d8xvvbsdkyj4",1920,[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Fableton-move-7775c36c.jpg",[],{},[],{"path":2065,"site":2066},"\u002Fi-bought-an-ableton-move",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":2068,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":2069,"contentType":235,"path":236},[],{"id":2071,"attributes":26,"body":2072,"description":26,"headline":2171,"schema":2172,"slug":2173,"subHeadline":26,"publishedAt":2174,"type":219,"categories":2175,"heroImage":2177,"images":2182,"relationships":2183,"tags":2184,"permalink":2185,"author":2188},"article_01jb33rcjse8jbrh20b41svrf2",{"type":9,"content":2073},[2074,2080,2085,2089,2093,2097,2101,2105,2114,2119,2123,2127,2131,2136,2140,2144,2148,2154,2159,2163,2167],{"type":81,"attrs":2075,"content":2077},{"level":2076},1,[2078],{"type":15,"text":2079},"Why?",{"type":81,"attrs":2081,"content":2082},{"level":83},[2083],{"type":15,"text":2084},"There's a piece of my soul in publishing",{"type":12,"content":2086},[2087],{"type":15,"text":2088},"In a way, Minima is my love letter to the web.",{"type":12,"content":2090},[2091],{"type":15,"text":2092},"A big chunk of my life and career has been in and around publishing – after helping grow New Atlas into one of the biggest independent news publishers on the web, I started a managed programmatic advertising business with my wife.",{"type":12,"content":2094},[2095],{"type":15,"text":2096},"The model we ended up with there was effectively playing a fractional CTO role at the publisher we managed advertising for, growing the pie itself as well as the advertising revenue.",{"type":12,"content":2098},[2099],{"type":15,"text":2100},"That's left me with a unique perspective on how just how bad things can get under the hood – from fully custom solutions, to WordPress, to expensive enterprise solutions with five figure monthly fees and multi-year lock in contracts.",{"type":12,"content":2102},[2103],{"type":15,"text":2104},"In short, putting words and pictures on the internet shouldn't be as painful or as expensive as it is.",{"type":81,"attrs":2106,"content":2107},{"level":2076},[2108,2110],{"type":15,"text":2109},"Why ",{"type":15,"text":2111,"marks":2112},"now?",[2113],{"type":107},{"type":81,"attrs":2115,"content":2116},{"level":83},[2117],{"type":15,"text":2118},"The costs are too damn high",{"type":12,"content":2120},[2121],{"type":15,"text":2122},"Publishing is, frankly, an awful business.",{"type":12,"content":2124},[2125],{"type":15,"text":2126},"You can lose 90% or more of your traffic overnight, at the whims of an algorithm.",{"type":12,"content":2128},[2129],{"type":15,"text":2130},"Yet decent WordPress hosting, plus the yearly plugin subscriptions to do essentials like SEO\u002Fnews markup, adds up very quickly.",{"type":81,"attrs":2132,"content":2133},{"level":83},[2134],{"type":15,"text":2135},"Technology is going through a paradigm shift",{"type":12,"content":2137},[2138],{"type":15,"text":2139},"Firstly, Cloudflare's developer platform is driving down the cost of hosting software.",{"type":12,"content":2141},[2142],{"type":15,"text":2143},"Secondly, AI is driving down the cost of building software.",{"type":12,"content":2145},[2146],{"type":15,"text":2147},"It's about time for publishers to see the benefits of these changes.",{"type":12,"content":2149},[2150],{"type":15,"text":2151,"marks":2152},"Disclosure: I'm a Cloudflare shareholder.",[2153],{"type":107},{"type":81,"attrs":2155,"content":2156},{"level":83},[2157],{"type":15,"text":2158},"WordPress is self-destructing",{"type":12,"content":2160},[2161],{"type":15,"text":2162},"I take no pleasure in this, and started working on Minima long before this happened, but there's now an unprecedented need for alternatives.",{"type":12,"content":2164},[2165],{"type":15,"text":2166},"There are countless developer-oriented solutions, but that's not what Minima is.",{"type":12,"content":2168},[2169],{"type":15,"text":2170},"Where we're going, you won't need developers.","Why I'm building another CMS",{},"why-im-building-another-cms",1729902686,[2176],{"name":535,"slug":536,"path":537},{"attributes":26,"caption":26,"credit":26,"height":2178,"id":2179,"width":625,"tags":2180,"contentType":628,"path":2181},853,"image_01jqwg09t3ect9c23qyxrqjmeb",[],"org_01jakhtww5fk6b0jmxj0qfp9rf\u002Foc-gonzalez-xg8z_KhSorQ-unsplash-small-5ddab33f.jpg",[],{},[],{"path":2186,"site":2187},"\u002Fwhy-im-building-another-cms",{"domain":227},{"id":229,"name":230,"schema":26,"avatar":2189,"bio":26,"title":26,"permalink":26},{"attributes":26,"caption":26,"credit":26,"height":232,"id":233,"width":232,"tags":2190,"contentType":235,"path":236},[],{"total":2192,"limit":2193,"offset":868,"page":2076,"totalPages":2076},13,20]