[{"data":1,"prerenderedAt":490},["ShallowReactive",2],{"field-notes-teaser":3},[4,178,329],{"id":5,"title":6,"body":7,"date":165,"description":166,"extension":167,"meta":168,"navigation":169,"path":170,"seo":171,"stem":172,"tags":173,"__hash__":177},"content\u002Ffield-notes\u002Fbuilding-my-own-site-with-claude-agents.md","Building my own site with Claude agents",{"type":8,"value":9,"toc":156},"minimark",[10,14,17,83,88,91,98,102,105,108,112,115,118,122,125,128,132,135,138,142,145,149,152],[11,12,13],"p",{},"I rebuilt maxdevos.be with Claude agents doing most of the typing. Not a demo — the site you're reading this on. This is the build log: what the setup looked like, what worked, and what bit.",[11,15,16],{},"The pipeline, end to end:",[18,19,24],"pre",{"className":20,"code":21,"language":22,"meta":23,"style":23},"language-mermaid shiki shiki-themes github-light github-dark","flowchart LR\n  BB[\"Brand bible kit\"] --> TK[\"tokens.css\"]\n  TK --> PG[\"Nuxt pages\u003Cbr\u002F>parallel agents\"]\n  PG --> VR[\"Verify by rendering\"]\n  VR --> ST[\"Staging\u003Cbr\u002F>non-indexed\"]\n  classDef n fill:#FBFCFD,stroke:#231F20,color:#231F20;\n  classDef hl fill:#F58D61,stroke:#231F20,color:#231F20;\n  class BB,TK,PG,ST n;\n  class VR hl;\n","mermaid","",[25,26,27,35,41,47,53,59,65,71,77],"code",{"__ignoreMap":23},[28,29,32],"span",{"class":30,"line":31},"line",1,[28,33,34],{},"flowchart LR\n",[28,36,38],{"class":30,"line":37},2,[28,39,40],{},"  BB[\"Brand bible kit\"] --> TK[\"tokens.css\"]\n",[28,42,44],{"class":30,"line":43},3,[28,45,46],{},"  TK --> PG[\"Nuxt pages\u003Cbr\u002F>parallel agents\"]\n",[28,48,50],{"class":30,"line":49},4,[28,51,52],{},"  PG --> VR[\"Verify by rendering\"]\n",[28,54,56],{"class":30,"line":55},5,[28,57,58],{},"  VR --> ST[\"Staging\u003Cbr\u002F>non-indexed\"]\n",[28,60,62],{"class":30,"line":61},6,[28,63,64],{},"  classDef n fill:#FBFCFD,stroke:#231F20,color:#231F20;\n",[28,66,68],{"class":30,"line":67},7,[28,69,70],{},"  classDef hl fill:#F58D61,stroke:#231F20,color:#231F20;\n",[28,72,74],{"class":30,"line":73},8,[28,75,76],{},"  class BB,TK,PG,ST n;\n",[28,78,80],{"class":30,"line":79},9,[28,81,82],{},"  class VR hl;\n",[84,85,87],"h2",{"id":86},"kit-first-pages-second","Kit first, pages second",[11,89,90],{},"Before any site code existed, we built a brand bible: one HTML document that holds the design tokens — colours pulled from the logo, type scale, spacing, motion — plus every component rendered live on the page. Nav, cards, buttons, code blocks, all documented once.",[11,92,93,94,97],{},"That file turned out to be the most important piece of infrastructure in the project. ",[25,95,96],{},"tokens.css"," is the single source of truth; the Nuxt app imports it unchanged. When a page needed a card or a CTA, the answer was \"assemble it from the bible\", never \"design something new\". That constraint did more for visual consistency than any review pass.",[84,99,101],{"id":100},"a-deliberately-boring-stack","A deliberately boring stack",[11,103,104],{},"Nuxt 4. Marketing pages prerender to static HTML. Field notes are Markdown files rendered by Nuxt Content. The whole thing runs on the shared hosting I already pay for — a Node instance at my existing host, no new infrastructure, no platform to learn.",[11,106,107],{},"The tempting move was a shiny edge platform. The honest move was using what was already there and spending the energy on content instead.",[84,109,111],{"id":110},"agents-in-parallel","Agents in parallel",[11,113,114],{},"Once the kit existed, pages became independent jobs. One subagent built the services page while another built the about page, each reading the same tokens and the same component CSS. They didn't step on each other, because they didn't share anything except the kit.",[11,116,117],{},"That's the real lesson about parallel agents: parallelism works when the shared contract is strong. Where the contract is vague, agents invent — and two agents inventing independently diverge fast.",[84,119,121],{"id":120},"verify-by-rendering","Verify by rendering",[11,123,124],{},"The single most useful habit we adopted: never trust a description of visual work. Every change got screenshotted against the actual rendered page and looked at with human eyes.",[11,126,127],{},"More than once, an animation that sounded right in prose read completely differently on screen — a letter-scramble effect described as \"subtle\" was anything but. If we had merged on the description, it would have shipped. Screenshots are cheap; un-shipping an ugly animation is not.",[84,129,131],{"id":130},"what-bit-drift","What bit: drift",[11,133,134],{},"The brand bible contains a mock of the site navigation; the site has the real nav component. Two files, one design — and they drifted. A CTA changed in one and not the other. Nothing broke; it was just quietly wrong until a screenshot comparison caught it.",[11,136,137],{},"The rule since then: nav changes land in both files in the same commit, and the rule is written down where the agents read it. Duplicated truth needs a written rule, or it rots.",[84,139,141],{"id":140},"staging-that-cant-leak","Staging that can't leak",[11,143,144],{},"The site lived on a staging subdomain while content landed, and I didn't want a half-finished site in a search index. One noindex meta tag felt thin, so the staging build flips three layers at once: a robots.txt that disallows everything, a noindex injected by the SEO module, and a hardcoded robots meta as belt-and-braces. A refactor might silently drop one layer; it's unlikely to drop all three.",[84,146,148],{"id":147},"if-youre-doing-the-same","If you're doing the same",[11,150,151],{},"Build the kit before the pages — agents are only as consistent as the contract you hand them. Keep the dynamic parts few and boring. And render everything: an agent's summary of what it built is a claim, not evidence.",[153,154,155],"style",{},"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":23,"searchDepth":37,"depth":37,"links":157},[158,159,160,161,162,163,164],{"id":86,"depth":37,"text":87},{"id":100,"depth":37,"text":101},{"id":110,"depth":37,"text":111},{"id":120,"depth":37,"text":121},{"id":130,"depth":37,"text":131},{"id":140,"depth":37,"text":141},{"id":147,"depth":37,"text":148},"2026-07-03","A build log from rebuilding maxdevos.be with Claude agents — the brand bible as the kit, pages built in parallel, and why we screenshot everything.","md",{},true,"\u002Ffield-notes\u002Fbuilding-my-own-site-with-claude-agents",{"title":6,"description":166},"field-notes\u002Fbuilding-my-own-site-with-claude-agents",[174,175,176],"ai","agents","web","rVHXqe-q9J-tFDcjwZnHlYplYuBi27pc0r3BvYFnJfU",{"id":179,"title":180,"body":181,"date":319,"description":320,"extension":167,"meta":321,"navigation":169,"path":322,"seo":323,"stem":324,"tags":325,"__hash__":328},"content\u002Ffield-notes\u002Ffive-layer-ai-native-erp.md","A 5-layer way to think about AI-native ERP",{"type":8,"value":182,"toc":313},[183,191,195,202,208,214,220,226,229,232,286,290,297,301,304,308,311],[11,184,185,186,190],{},"The framing comes from Andrew Cooper of P3M and his \"AI-native ERP architecture\" piece. His claim: in the next generation of ERP, AI isn't bolted onto a legacy core — it ",[187,188,189],"em",{},"is"," the core. He draws it as five layers, each with one job. I keep coming back to it, so here's my working copy.",[84,192,194],{"id":193},"the-five-layers","The five layers",[11,196,197,201],{},[198,199,200],"strong",{},"1 · Generative AI — the interface."," Natural language in, natural language out: conversational queries, AI-generated reports, document generation. This is the layer everyone can picture, because it's the layer today's copilots already occupy.",[11,203,204,207],{},[198,205,206],{},"2 · Agentic AI — domain agents."," Autonomous agents that each own a domain — finance, procurement, supply chain, HR, sales — and execute within it. The design principle is collaboration, not competition: agents work through well-defined interfaces and share context instead of fighting over it.",[11,209,210,213],{},[198,211,212],{},"3 · Symbolic AI — deterministic compliance."," Not a model: rules. SOX controls, GAAP\u002FIFRS, tax and regulatory logic, the audit trail. Every action from the layers above passes through this checkpoint before anything is persisted.",[11,215,216,219],{},[198,217,218],{},"4 · Unified data."," One converged layer — transactional database, knowledge graph, vector store, event stream — instead of the silo sprawl that produces the integration tax every traditional ERP estate pays.",[11,221,222,225],{},[198,223,224],{},"5 · Integration."," The connectors to the outside world: banking APIs, supplier APIs, tax authorities, third-party SaaS.",[11,227,228],{},"A request flows top to bottom: the generative layer takes the question, the agent that owns the domain picks it up, the symbolic layer validates it, unified data persists it, and integration reaches out when the outside world is involved.",[11,230,231],{},"The stack, sketched — coral marks the deterministic checkpoint and today's system of record:",[18,233,235],{"className":20,"code":234,"language":22,"meta":23,"style":23},"flowchart TB\n  L1[\"1 · Generative AI\u003Cbr\u002F>natural-language interface\"] --> L2[\"2 · Agentic AI\u003Cbr\u002F>domain agents\"]\n  L2 --> L3[\"3 · Symbolic AI\u003Cbr\u002F>deterministic compliance\"]\n  L3 --> L4[\"4 · Unified data\"]\n  L4 --> L5[\"5 · Integration\u003Cbr\u002F>outside world\"]\n  BC[\"Business Central\u003Cbr\u002F>system of record\"] -.-> L4\n  classDef n fill:#FBFCFD,stroke:#231F20,color:#231F20;\n  classDef hl fill:#F58D61,stroke:#231F20,color:#231F20;\n  class L1,L2,L4,L5 n;\n  class L3,BC hl;\n",[25,236,237,242,247,252,257,262,267,271,275,280],{"__ignoreMap":23},[28,238,239],{"class":30,"line":31},[28,240,241],{},"flowchart TB\n",[28,243,244],{"class":30,"line":37},[28,245,246],{},"  L1[\"1 · Generative AI\u003Cbr\u002F>natural-language interface\"] --> L2[\"2 · Agentic AI\u003Cbr\u002F>domain agents\"]\n",[28,248,249],{"class":30,"line":43},[28,250,251],{},"  L2 --> L3[\"3 · Symbolic AI\u003Cbr\u002F>deterministic compliance\"]\n",[28,253,254],{"class":30,"line":49},[28,255,256],{},"  L3 --> L4[\"4 · Unified data\"]\n",[28,258,259],{"class":30,"line":55},[28,260,261],{},"  L4 --> L5[\"5 · Integration\u003Cbr\u002F>outside world\"]\n",[28,263,264],{"class":30,"line":61},[28,265,266],{},"  BC[\"Business Central\u003Cbr\u002F>system of record\"] -.-> L4\n",[28,268,269],{"class":30,"line":67},[28,270,64],{},[28,272,273],{"class":30,"line":73},[28,274,70],{},[28,276,277],{"class":30,"line":79},[28,278,279],{},"  class L1,L2,L4,L5 n;\n",[28,281,283],{"class":30,"line":282},10,[28,284,285],{},"  class L3,BC hl;\n",[84,287,289],{"id":288},"why-the-symbolic-layer-is-the-one-that-matters","Why the symbolic layer is the one that matters",[11,291,292,293,296],{},"Layer 3 is what separates this from \"wrap an LLM around your ERP\". Finance and compliance can't hallucinate. A VAT rule is not a probability, and an audit trail that's ",[187,294,295],{},"mostly"," right is worthless. Making the deterministic rule layer first-class architecture — rather than bolted-on configuration — means every AI action is validated before it touches the books and auditable afterwards. Compliance built in, not bolted on. That's the part of the model I'd defend hardest.",[84,298,300],{"id":299},"where-business-central-sits","Where Business Central sits",[11,302,303],{},"BC today is the system of record — the transactional core and most of layer 4, carrying decades of accounting discipline. Microsoft's Copilot story maps roughly onto layer 1. The interesting gap is the middle: I haven't seen anyone building public agentic and symbolic layers on top of BC yet. So the five layers aren't a product you can buy. They're a map of where the value in ERP work is moving — away from screens, towards agents governed by deterministic rules.",[84,305,307],{"id":306},"what-im-still-chewing-on","What I'm still chewing on",[11,309,310],{},"Does the model survive scaling down? On an enterprise D365 footprint, a full symbolic compliance layer plainly earns its keep. On a small or midsize BC tenant, I'm not sure whether Symbolic AI stays a distinct layer or collapses into what we already call configuration — posting groups, VAT setup, approval workflows. If it collapses, then the deterministic layer already exists in every well-implemented BC tenant, and the missing piece isn't compliance at all — it's the agentic middle. I don't have the answer yet. That's what this note is for.",[153,312,155],{},{"title":23,"searchDepth":37,"depth":37,"links":314},[315,316,317,318],{"id":193,"depth":37,"text":194},{"id":288,"depth":37,"text":289},{"id":299,"depth":37,"text":300},{"id":306,"depth":37,"text":307},"2026-07-01","Andrew Cooper's five-layer model for ERP where AI is the core rather than a bolt-on — and why the deterministic compliance layer is the part that matters most.",{},"\u002Ffield-notes\u002Ffive-layer-ai-native-erp",{"title":180,"description":320},"field-notes\u002Ffive-layer-ai-native-erp",[174,326,327],"erp","business-central","2moIPKriEvkfTjPWnhBieYRKoIfq6J6AE469NBcpZfY",{"id":330,"title":331,"body":332,"date":480,"description":481,"extension":167,"meta":482,"navigation":169,"path":483,"seo":484,"stem":485,"tags":486,"__hash__":489},"content\u002Ffield-notes\u002Fboms-dont-survive-contact-with-the-shop-floor.md","BOMs don't survive contact with the shop floor",{"type":8,"value":333,"toc":475},[334,337,341,347,353,359,362,366,372,378,384,388,391,397,403,409,412,470,473],[11,335,336],{},"Every manufacturing ERP project I've been close to has the same gap: the bill of materials in the system, and the thing the shop floor actually makes. The two start out identical and drift apart from day one. That's not carelessness — it's structural.",[84,338,340],{"id":339},"why-the-drift-is-inevitable","Why the drift is inevitable",[11,342,343,346],{},[198,344,345],{},"Substitutions."," A material runs short mid-batch, an experienced operator swaps in the approved equivalent from the next shelf, production doesn't stop, the customer never notices. The paperwork rarely follows. From the floor's point of view nothing happened — the product got made.",[11,348,349,352],{},[198,350,351],{},"Batch-size reality."," The BOM is modelled at a clean theoretical quantity. The actual kettle, mixer or line has a minimum fill, startup scrap, and losses that don't scale linearly. Halve the batch and consumption per unit quietly changes; the modelled BOM has one number for all of it.",[11,354,355,358],{},[198,356,357],{},"Undocumented steps."," The rework loop after the forming step. The extra sieve pass \"we always do in summer\". The manual quality check that eats ten minutes and a consumable. Everyone on the floor knows these; nobody has written them down, so nobody costs them.",[11,360,361],{},"None of this feels like a \"change\" to the people doing it — it's just how the product gets made. So nothing ever triggers an update in the ERP.",[84,363,365],{"id":364},"how-it-quietly-breaks-the-system","How it quietly breaks the system",[11,367,368,371],{},[198,369,370],{},"Costing."," Standard cost is built on the modelled BOM. If the floor consumes six percent more of an ingredient than the recipe says, margin is overstated on every unit — and you find out at year-end through an inventory write-down, not through a report during the year.",[11,373,374,377],{},[198,375,376],{},"Planning."," MRP explodes the modelled BOM to plan purchases. It buys the wrong quantities of the wrong things: stockouts of what you actually consume, a slow-building mountain of what you don't.",[11,379,380,383],{},[198,381,382],{},"Trust."," Production variances get so noisy that people stop reading them. That's the quiet death: once variance reporting is noise, the ERP has lost the floor, and every number downstream of it is decoration.",[84,385,387],{"id":386},"the-fix-is-honesty-not-discipline","The fix is honesty, not discipline",[11,389,390],{},"The instinct is to demand that the floor \"follow the BOM\". In my experience that fails, because the floor's deviations usually exist for good reasons. What works:",[11,392,393,396],{},[198,394,395],{},"Walk the floor before you model."," Watch a real batch end to end. Weigh what actually goes in. An operator narrating what they do is worth more than the spec sheet from the design office — the spec is the intention; the floor is the fact.",[11,398,399,402],{},[198,400,401],{},"Model the recipe people actually cook."," Capture the as-made BOM first, even if it's ugly: with the substitutions, the scrap, the extra steps. You can improve towards the ideal recipe later. You cannot plan or cost from fiction.",[11,404,405,408],{},[198,406,407],{},"Build the feedback loop."," Make deviations cheap to report — a scan at the station, one line on the batch record that flows into a weekly review. Give the BOM an owner. Review variances on a cadence, and when the floor turns out to be right — it often is — change the BOM, not the floor.",[11,410,411],{},"The whole loop in one picture:",[18,413,415],{"className":20,"code":414,"language":22,"meta":23,"style":23},"flowchart TB\n  M[\"Modelled BOM\"] --> F[\"Floor reality\u003Cbr\u002F>substitutions · batch sizes · undocumented steps\"]\n  F --> D[\"Drift\"]\n  D --> X[\"Costing and planning break\"]\n  X --> W[\"Walk the floor\"]\n  W --> L[\"Living BOM\"]\n  L -->|feeds back into| M\n  classDef n fill:#FBFCFD,stroke:#231F20,color:#231F20;\n  classDef hl fill:#F58D61,stroke:#231F20,color:#231F20;\n  class M,F,D,X,W n;\n  class L hl;\n",[25,416,417,421,426,431,436,441,446,451,455,459,464],{"__ignoreMap":23},[28,418,419],{"class":30,"line":31},[28,420,241],{},[28,422,423],{"class":30,"line":37},[28,424,425],{},"  M[\"Modelled BOM\"] --> F[\"Floor reality\u003Cbr\u002F>substitutions · batch sizes · undocumented steps\"]\n",[28,427,428],{"class":30,"line":43},[28,429,430],{},"  F --> D[\"Drift\"]\n",[28,432,433],{"class":30,"line":49},[28,434,435],{},"  D --> X[\"Costing and planning break\"]\n",[28,437,438],{"class":30,"line":55},[28,439,440],{},"  X --> W[\"Walk the floor\"]\n",[28,442,443],{"class":30,"line":61},[28,444,445],{},"  W --> L[\"Living BOM\"]\n",[28,447,448],{"class":30,"line":67},[28,449,450],{},"  L -->|feeds back into| M\n",[28,452,453],{"class":30,"line":73},[28,454,64],{},[28,456,457],{"class":30,"line":79},[28,458,70],{},[28,460,461],{"class":30,"line":282},[28,462,463],{},"  class M,F,D,X,W n;\n",[28,465,467],{"class":30,"line":466},11,[28,468,469],{},"  class L hl;\n",[11,471,472],{},"A BOM is a living document. Treat it as a snapshot from the design office and it starts dying the day you post it. Keep it fed from the floor and it becomes the one thing in the ERP everyone actually believes.",[153,474,155],{},{"title":23,"searchDepth":37,"depth":37,"links":476},[477,478,479],{"id":339,"depth":37,"text":340},{"id":364,"depth":37,"text":365},{"id":386,"depth":37,"text":387},"2026-06-28","Why the modelled bill of materials always drifts from what the floor actually does, how that quietly corrupts costing and planning, and what to do about it.",{},"\u002Ffield-notes\u002Fboms-dont-survive-contact-with-the-shop-floor",{"title":331,"description":481},"field-notes\u002Fboms-dont-survive-contact-with-the-shop-floor",[487,326,488],"operations","manufacturing","ZyjBK8-wh4CaiF-amBDvvYw077XpfHItgch2g8f3p7g",1784027584202]