[{"data":1,"prerenderedAt":1104},["ShallowReactive",2],{"gate-notes":3,"layout-site":467,"layout-footer":489,"gate-uses":497,"gate-gallery":657,"post-\u002Fblog\u002Fcode-review-is-the-skill-now":672,"blog-siblings":817,"post-site":1092,"author-site":1098},[4,258,355],{"id":5,"title":6,"body":7,"cover":235,"date":240,"description":241,"draft":242,"extension":243,"meta":244,"navigation":245,"path":246,"placeholder":242,"readingMinutes":247,"seo":248,"stem":249,"summary":250,"tags":251,"__hash__":257},"blog\u002Fblog\u002Fcode-review-is-the-skill-now.md","Code review is the skill now: programming after AI",{"type":8,"value":9,"toc":222},"minimark",[10,15,38,42,46,49,52,56,59,80,83,92,96,99,102,110,113,143,146,150,153,156,163,166,170,173,176,179,183,186,212,216,219],[11,12,14],"h2",{"id":13},"the-short-version","The short version",[16,17,18,26,32],"ul",{},[19,20,21,25],"li",{},[22,23,24],"strong",{},"AI changed who writes the code."," Planning and implementation now happen with\nAI. Reviewing is still my job.",[19,27,28,31],{},[22,29,30],{},"Accepting AI code without reading it is vibe coding."," It runs, it looks\nright, and nobody has checked it.",[19,33,34,37],{},[22,35,36],{},"How fast you can review correctly is the new measure of a programmer."," Code\nreview is the skill worth training.",[11,39,41],{"id":40},"how-programming-used-to-work","How programming used to work",[43,44,45],"p",{},"For most of my career, programming meant one person holding the whole problem.\nYou read the requirement, worked out the logic, picked the algorithm, decided how\nthe pieces would talk to each other, and then typed every line of it. The thinking\nand the typing were the same job, done by the same person, usually at the same\ntime.",[43,47,48],{},"Skill was easy to see in that model. A good programmer wrote correct code faster\nand needed fewer tries to get there. How much you could produce was how you were\njudged.",[43,50,51],{},"That model is gone from my own work, and I don't think it's coming back.",[11,53,55],{"id":54},"the-ai-workflow-plan-implement-review","The AI workflow: plan, implement, review",[43,57,58],{},"A feature on one of my plugins goes like this now:",[60,61,62,68,74],"ol",{},[19,63,64,67],{},[22,65,66],{},"Planning with AI."," I describe the problem, the constraints, and what already\nexists. We go back and forth on the approach: which hook, which data shape,\nwhat could break for installs that already exist. The plan comes out of that\nconversation. It isn't something I write alone and then hand over.",[19,69,70,73],{},[22,71,72],{},"Implementation by AI."," The code gets written, most of it not by me. Files,\nfunctions, tests, the migration if there is one.",[19,75,76,79],{},[22,77,78],{},"Review by me."," I read all of it and decide what ships.",[43,81,82],{},"The first two steps got dramatically faster. The third one didn't, and it\nshouldn't. It's where the job moved to.",[43,84,85,86,91],{},"A few weeks ago I wrote that ",[87,88,90],"a",{"href":89},"\u002Fblog\u002Fthe-future-of-programming-learn-to-think-not-just-code","programmers should learn to think, not just\ncode",". This is the\npractical side of that. Thinking about systems is how you plan well. Reviewing is\nhow you prove the plan actually got built.",[11,93,95],{"id":94},"accepting-ai-code-isnt-reviewing-it-thats-vibe-coding","Accepting AI code isn't reviewing it: that's vibe coding",[43,97,98],{},"There's a version of this workflow that skips step three. The AI writes it, it\nruns, the page loads, the test is green. Merge.",[43,100,101],{},"That's vibe coding. It isn't a moral failing. It's a description. You're shipping\ncode on the strength of how it feels, because nobody actually read it. For a\nthrowaway script, fine. For a plugin running on someone else's live site, with a\nvisitor's data going through it, it's a bet you're making with other people's\nstuff.",[43,103,104,105,109],{},"The trouble is that AI-written code is very good at ",[106,107,108],"em",{},"looking"," right. It's\nformatted well, the names make sense, the comments sound confident. The mistakes\naren't typos. They're plausible decisions that happen to be wrong, and plausible\nwrong code gets past a skim every time.",[43,111,112],{},"In WordPress work, these are the ones I keep catching:",[16,114,115,123,134,137,140],{},[19,116,117,118,122],{},"A REST route registered with ",[119,120,121],"code",{},"'permission_callback' => '__return_true'","\non an endpoint that writes data. It works in testing because you're logged in\nas admin anyway.",[19,124,125,126,129,130,133],{},"A ",[119,127,128],{},"$wpdb->query()"," with a variable dropped straight into the SQL string instead\nof going through ",[119,131,132],{},"$wpdb->prepare()",".",[19,135,136],{},"Output echoed without escaping, or input saved without sanitizing, because the\nhappy path never sent anything strange.",[19,138,139],{},"A nonce that gets created and never checked.",[19,141,142],{},"A migration that runs on every page load instead of once, because nothing\nrecords that it already ran.",[43,144,145],{},"Every one of those runs. Every one passes a quick manual test. None of them\nannounce themselves. You only find them if you're reading on purpose.",[11,147,149],{"id":148},"review-speed-is-the-new-measure","Review speed is the new measure",[43,151,152],{},"In the old model you could see a programmer's skill in what they wrote. Now you\ncan see it in how fast they can review correctly.",[43,154,155],{},"Both words matter. Fast and wrong is worse than useless, because it gives\nconfidence to code that hasn't earned it. Slow and right still works, but you\nlose most of what AI gave you, and the queue of unreviewed changes piles up.",[43,157,158,159,162],{},"What makes someone fast ",[106,160,161],{},"and"," right is the same thing that used to make someone a\ngood writer of code: they already know what correct looks like. An experienced\nreviewer doesn't read a permission check and wonder whether it matters. They know\nwhere the authorization should be and notice when it's missing. They don't trace\nevery loop from scratch. They recognize the shape and look straight at the edge\ncase the shape usually gets wrong.",[43,164,165],{},"So all the fundamentals still count: logic, data structures, how the platform\nbehaves, security basics. They just get used in a different place. You used to\nspend them typing. Now you spend them reading.",[11,167,169],{"id":168},"reading-for-whats-missing","Reading for what's missing",[43,171,172],{},"The hardest part of reviewing AI code isn't spotting a bad line. It's noticing the\nline that isn't there.",[43,174,175],{},"AI does what you asked, and usually does it thoroughly. What it misses is whatever\nyou didn't think to ask about: what happens on an install that already has old\ndata, what happens when two requests land at once, what happens when the user\nisn't who the code assumes they are, what happens to the thing this change quietly\ndepends on.",[43,177,178],{},"So I read against the plan, not only against the diff. Did it handle the case we\nsaid mattered? Did it touch anything the plan never mentioned? Is there a code\npath we talked about that just isn't in there? The diff only shows you what got\nwritten. The plan tells you what should have been.",[11,180,182],{"id":181},"how-to-get-better-at-code-review","How to get better at code review",[43,184,185],{},"If review is the main skill, it deserves practice, the same way writing code\nused to get practice. What I actually do:",[16,187,188,194,200,206],{},[19,189,190,193],{},[22,191,192],{},"Predict before reading."," Before opening the diff, I guess roughly how I'd have\nbuilt it. Where the real code differs, either it knows something I missed or\nit's wrong. Both are worth knowing.",[19,195,196,199],{},[22,197,198],{},"Keep a list of what AI gets wrong."," The list above started as notes. The same\nmistakes come back, so a written list makes the next review faster.",[19,201,202,205],{},[22,203,204],{},"Read other people's code."," Open-source plugins, pull requests, core itself.\nReading code you didn't commission, with no plan in your head, is the hard\nversion of the exercise.",[19,207,208,211],{},[22,209,210],{},"Still write some things by hand."," Not for speed. So I keep an instinct for\nwhat correct feels like. You can't recognize the right shape if you've\nforgotten how to make it.",[11,213,215],{"id":214},"the-name-on-the-commit","The name on the commit",[43,217,218],{},"I said in that earlier post that even code review will probably need less human\ninvolvement over time. I still think that's where this is heading. But it isn't\nwhere we are now, and right now the review is where responsibility sits. The AI\ndoesn't answer the support ticket. The AI isn't the one a client calls when a form\nstops sending. My name is on the commit, so my reading is what signs it off.",[43,220,221],{},"Writing code got cheap. Knowing whether code is right didn't, and that's the skill\nI'm working on now.",{"title":223,"searchDepth":224,"depth":224,"links":225},"",3,[226,228,229,230,231,232,233,234],{"id":13,"depth":227,"text":14},2,{"id":40,"depth":227,"text":41},{"id":54,"depth":227,"text":55},{"id":94,"depth":227,"text":95},{"id":148,"depth":227,"text":149},{"id":168,"depth":227,"text":169},{"id":181,"depth":227,"text":182},{"id":214,"depth":227,"text":215},{"src":236,"alt":237,"width":238,"height":239},"\u002Fimages\u002Fblog\u002Fcode-review-is-the-skill-now.webp","An AI-assisted workflow of plan, implement, review and ship, with a developer reviewing AI-written WordPress code that flags a missing permission check, SQL injection risk and unescaped output",1536,1024,"2026-09-27","AI writes most of the code now. Accepting it unread is vibe coding. Why code review became the core programming skill, and how I practise it.",false,"md",{},true,"\u002Fblog\u002Fcode-review-is-the-skill-now",6,{"title":6,"description":241},"blog\u002Fcode-review-is-the-skill-now","AI now plans with me and writes most of the implementation. The part it hasn't taken is reading that code and deciding whether it ships. Accepting it unread is vibe coding. Reviewing it well, and quickly, is where the programming skill lives now.",[252,253,254,255,256],"ai","code-review","vibe-coding","engineering","wordpress","9e-9a5kt2HzdQhfpo43HgycHBvnilkMe-tDNbjViyH8",{"id":259,"title":260,"body":261,"cover":342,"date":347,"description":265,"draft":242,"extension":243,"meta":348,"navigation":245,"path":89,"placeholder":242,"readingMinutes":224,"seo":349,"stem":350,"summary":351,"tags":352,"__hash__":354},"blog\u002Fblog\u002Fthe-future-of-programming-learn-to-think-not-just-code.md","The Future of Programming: Learn to Think, Not Just Code",{"type":8,"value":262,"toc":340},[263,266,269,272,275,278,281,284,287,290,293,296,319,322,325,328,331,334,337],[43,264,265],{},"The era of writing every line of code by hand is slowly coming to an end.",[43,267,268],{},"AI can already generate code faster than most developers, and it is becoming\nsurprisingly capable at finding bugs, reviewing implementations, and suggesting\nimprovements. As these systems continue to evolve, even traditional code review\nwill require less human involvement.",[43,270,271],{},"So, does that mean we no longer need to learn programming?",[43,273,274],{},"Quite the opposite.",[43,276,277],{},"We still need to understand programming—but the way we learn it has to change.",[43,279,280],{},"For years, learning programming meant spending countless hours writing syntax,\nmemorizing APIs, debugging errors, and building things line by line. That\napproach made sense when humans were responsible for producing the code.",[43,282,283],{},"But if AI is going to handle much of the implementation, our focus needs to move\nfrom writing code to understanding systems.",[43,285,286],{},"Think about an architect. An architect doesn't need to personally lay every\nbrick, install every pipe, or wire every electrical connection. Their job is to\nunderstand the entire structure—how different parts fit together, where problems\nmight occur, what materials should be used, and how everything should work\ntogether.",[43,288,289],{},"They understand the system so they can make the right decisions.",[43,291,292],{},"The same shift is happening in software development.",[43,294,295],{},"AI may write the implementation, but someone still needs to decide:",[16,297,298,301,304,307,310,313,316],{},[19,299,300],{},"What should be built?",[19,302,303],{},"Why should it be built this way?",[19,305,306],{},"How should the system behave?",[19,308,309],{},"Which architecture makes sense?",[19,311,312],{},"What trade-offs are acceptable?",[19,314,315],{},"How should different components interact?",[19,317,318],{},"What could go wrong?",[43,320,321],{},"That person needs to understand programming deeply enough to make those\ndecisions—even if they aren't personally typing every line.",[43,323,324],{},"In other words, the developer of the future may look less like a traditional\ncoder and more like a technical strategist or team lead.",[43,326,327],{},"So don't stop learning programming.",[43,329,330],{},"Instead, change what you are learning programming for.",[43,332,333],{},"Learn the logic, architecture, systems, patterns, trade-offs, and problem-solving\nbehind the code.",[43,335,336],{},"Because the future may not belong to the people who can write the most code.",[43,338,339],{},"It may belong to the people who understand what code needs to exist—and why.",{"title":223,"searchDepth":224,"depth":224,"links":341},[],{"src":343,"alt":344,"width":345,"height":346,"caption":223},"\u002Fimages\u002Fblog\u002Fthe-future-of-programming-learn-to-think-not-just-code.webp","A developer at a whiteboard of system decisions beside a robot writing code on a laptop, captioned \"not just a coder, a technical strategist\"",1600,900,"2026-09-05",{},{"title":260,"description":265},"blog\u002Fthe-future-of-programming-learn-to-think-not-just-code","AI is getting good enough at implementation that writing every line by hand is ending. That is not a reason to stop learning programming — it is a reason to change what you are learning it for.",[252,353,255],"career","Id7FK6pS1qhGW_lDGNt5ThD6jL1sjywZu573G5SV908",{"id":356,"title":357,"body":358,"cover":454,"date":457,"description":223,"draft":242,"extension":243,"meta":458,"navigation":245,"path":459,"placeholder":242,"readingMinutes":247,"seo":460,"stem":461,"summary":462,"tags":463,"__hash__":466},"blog\u002Fblog\u002Fwhat-renaming-a-plugin-actually-touches.md","What renaming a plugin actually touches",{"type":8,"value":359,"toc":447},[360,364,367,370,373,377,384,414,417,421,424,427,430,434,437,440,444],[11,361,363],{"id":362},"the-second-rename-was-not-my-idea","The second rename was not my idea",[43,365,366],{},"Defer Forms for Contact Form 7 has had two names before this one. The first rename\nwas mine — the old name said nothing about what the plugin did, and its folder name\nbroke a wordpress.org naming rule I'd rather have caught earlier. That one I chose,\non my own schedule.",[43,368,369],{},"The second was not a choice. It went into wordpress.org review under its new name\nand came back rejected: the name led with a generic word and sat too close to an\nexisting plugin's. Review doesn't negotiate. You get a reason and a rename.",[43,371,372],{},"The part worth writing down isn't the naming — plenty has been written about naming\nthings. It's that a rename looks like a one-line change and isn't one, the moment\nthe plugin has been installed anywhere.",[11,374,376],{"id":375},"a-name-is-not-just-a-label","A name is not just a label",[43,378,379,380,383],{},"The visible rename — the string in the plugin header, the text in the admin menu —\ntook an afternoon. Everywhere else the old name was actually ",[106,381,382],{},"encoded"," took four\nmore releases to find and fix, one at a time:",[16,385,386,392,402,408],{},[19,387,388,391],{},[22,389,390],{},"The database table."," Submissions, roles, everything the plugin stores lived\nunder a table prefixed with the old internal short name.",[19,393,394,397,398,401],{},[22,395,396],{},"The developer hooks."," Seven of them, documented, with real signatures — anyone\nwho had already filtered on ",[119,399,400],{},"old_prefix_submission_created"," needed to know it was\nnow something else, not silently stop firing.",[19,403,404,407],{},[22,405,406],{},"The REST namespace."," Every request the builder makes goes through it. Miss one\nreference and the admin looks fine until you open the one screen that calls it.",[19,409,410,413],{},[22,411,412],{},"Post meta keys, script and style handles, admin page URLs."," The last one meant\ntelling people to update their own bookmarks — a genuinely small cost, and still\na cost, and still something I had to remember to say.",[43,415,416],{},"None of this shows up in a diff of the plugin's header comment. All of it is the\nactual rename.",[11,418,420],{"id":419},"the-migration-has-to-run-once-and-only-once","The migration has to run once, and only once",[43,422,423],{},"The database table was the one that mattered most, because it's the one with a\nvisitor's data in it. Renaming a table isn't a decision you make in code and walk\naway from — every install that already has the old table needs something to run,\nonce, that moves its data to the new one before anything tries to read from the new\nname and finds nothing there.",[43,425,426],{},"That migration shipped in the same release as the prefix change. It checked for the\nold table, moved what it found, and got out of the way — the kind of code that is\neasy to write defensively and easy to forget about afterward, because once it's\nshipped it mostly just sits there working correctly for installs that need it and\ndoing nothing for installs that don't.",[43,428,429],{},"Sitting there is not free, though. Every release after that carried one more piece\nof logic whose entire job was reasoning about a table name nothing was going to use\ngoing forward. That's a real, if small, tax — one more thing to read when you're\ntrying to understand what a fresh install actually does, one more thing that could\nin principle misfire against data it was never meant to touch.",[11,431,433],{"id":432},"knowing-when-its-safe-to-delete","Knowing when it's safe to delete",[43,435,436],{},"The migration came out four releases later, and the reason it was safe to remove is\nthe part I'd actually recommend paying attention to: not \"it's probably fine by\nnow,\" but a specific, checkable claim — this plugin has never been distributed\nunder its old internal prefix. Every install anyone could download from that point\non was already past the rename. There was no table for the migration to ever find,\non any install that didn't already exist before the code was written, and there\nnever would be one again.",[43,438,439],{},"That's a different thing from \"nobody's complained.\" It's a claim about the\ndistribution history, and it's the kind of claim you can actually check rather than\nassume. Dead code that runs a permission check first and does nothing is safe. Dead\ncode you're only fairly sure is dead is a liability wearing the same clothes.",[11,441,443],{"id":442},"what-id-do-differently","What I'd do differently",[43,445,446],{},"Rename the internal prefix in the same release as the visible name, not four\nreleases later. Splitting them meant the plugin spent a stretch of its life with a\npublic name that didn't match anything in its own codebase — which is confusing to\nread, and is exactly the kind of gap a second, unplanned rename can catch you\nin the middle of. The visible name is the one wordpress.org reviews. The internal\none is the one that actually has to be right, and it deserves to move on the same\nday.",{"title":223,"searchDepth":224,"depth":224,"links":448},[449,450,451,452,453],{"id":362,"depth":227,"text":363},{"id":375,"depth":227,"text":376},{"id":419,"depth":227,"text":420},{"id":432,"depth":227,"text":433},{"id":442,"depth":227,"text":443},{"src":455,"alt":456,"width":345,"height":346},"\u002Fimages\u002Fblog\u002Fwhat-renaming-a-plugin-actually-touches.webp","Abstract illustration for an article about renaming a WordPress plugin and migrating its internal identity","2026-09-03",{},"\u002Fblog\u002Fwhat-renaming-a-plugin-actually-touches",{"title":357,"description":223},"blog\u002Fwhat-renaming-a-plugin-actually-touches","A wordpress.org review rejected the name once. The rename itself was the easy part — the database table, the hooks API, and the REST namespace all had to move too, for a plugin that already had real installs.",[256,464,465],"php","products","yyGeKgB7V-MTe1mpjFtKFNbd162HcN-P5NvkBD-dNpA",{"id":468,"booking":469,"email":470,"extension":471,"meta":472,"name":473,"role":474,"socials":475,"stem":485,"summary":486,"whatsapp":487,"__hash__":488},"site\u002Fglobal\u002Fsite.json","https:\u002F\u002Fcal.com\u002Frupash\u002F30min","rupash.das.40@gmail.com","json",{},"Rupash Das","WordPress developer & systems engineer",[476,479,482],{"label":477,"url":478},"GitHub","https:\u002F\u002Fgithub.com\u002FRupashdas",{"label":480,"url":481},"WordPress.org","https:\u002F\u002Fprofiles.wordpress.org\u002Frupash\u002F",{"label":483,"url":484},"Fiverr","https:\u002F\u002Fwww.fiverr.com\u002Frupash_das","global\u002Fsite","I take a business problem from requirements to a WordPress system that runs it — architecture, custom plugins, integrations, performance and security, and the upkeep after launch. Eight years of client work, with Laravel and Vue when a CMS is the wrong tool.","https:\u002F\u002Fwa.me\u002F8801873139202","uy6RMn-wEZfo4zzWR3K9xre0PyN0-x0CfUFQ_Y_gVdE",{"id":490,"colophon":491,"ctaLabel":492,"extension":471,"meta":493,"stem":494,"tagline":495,"__hash__":496},"footer\u002Fglobal\u002Ffooter.json","Rupash Das · Built with Nuxt","Start a project",{},"global\u002Ffooter","WordPress systems — planned, built, connected and kept running. From Bangladesh, shipped worldwide.","U2ki7hPjtCWq-aVsL0Hf79eawJna8bsPQfdAUXvSyI0",[498,527,552,574,606,631],{"id":499,"category":500,"extension":471,"items":501,"meta":522,"order":523,"stem":524,"summary":525,"__hash__":526},"uses\u002Fpages\u002Fuses\u002F01-applications.json","Beyond WordPress",[502,506,510,514,518],{"name":503,"url":504,"note":505,"key":245},"Laravel","https:\u002F\u002Flaravel.com","The framework for anything that has outgrown a CMS. Prices and stock decided on the server, and feature tests that run against the real database rather than a mock of it.",{"name":507,"url":508,"note":509,"key":245},"Vue 3, Composition API","https:\u002F\u002Fvuejs.org","Composition over Options for anything non-trivial. Logic that belongs together lives together, and it can be pulled out into a composable the day a second screen needs it.",{"name":511,"url":512,"note":513},"Vite","https:\u002F\u002Fvite.dev","The build for everything — applications and plugin interfaces both. Fast enough that a React panel inside wp-admin stops feeling like a compromise.",{"name":515,"url":516,"note":517},"Tailwind","https:\u002F\u002Ftailwindcss.com","Tokens in one file, utilities everywhere else. The token layer is the part that matters; the utilities are only how it gets applied.",{"name":519,"url":520,"note":521},"Nuxt","https:\u002F\u002Fnuxt.com","This site. Prerendered, with a bundle budget that fails the build rather than being admired in a readme.",{},4,"pages\u002Fuses\u002F01-applications","What I reach for when a project outgrows a CMS and needs to be an application of its own.","AYQQ46_MRZtaMpLllg18x-vIKFwTOCQVKFrDv3xY7F4",{"id":528,"category":529,"extension":471,"items":530,"meta":548,"order":227,"stem":549,"summary":550,"__hash__":551},"uses\u002Fpages\u002Fuses\u002F02-local.json","Local development",[531,535,539,542,545],{"name":532,"url":533,"note":534,"key":245},"LocalWP","https:\u002F\u002Flocalwp.com","One throwaway site per plugin. A plugin has to be installed on a clean WordPress before I believe it works.",{"name":536,"url":537,"note":538,"key":245},"Laragon","https:\u002F\u002Flaragon.org","Where the Laravel side lives. Apache, PHP and MySQL without an afternoon of configuration.",{"name":540,"note":541},"MySQL","The database under both stacks. Enough of it that a data migration can be a query rather than a plugin.",{"name":543,"note":544,"key":245},"A test suite that runs locally","Just over a hundred suites on the form plugin alone. They exist because it ships to sites I will never see, and no amount of clicking replaces that.",{"name":546,"note":547},"A guarded release script","Building a release by hand is how a stray development file ends up in a zip. The script refuses rather than reminds me.",{},"pages\u002Fuses\u002F02-local","Two stacks, kept apart. WordPress work and application work do not share an environment.","jjnVioJgu2KQ94wsXA4f4vcf7TDjMf1p0nKZskI2C6k",{"id":553,"category":554,"extension":471,"items":555,"meta":570,"order":224,"stem":571,"summary":572,"__hash__":573},"uses\u002Fpages\u002Fuses\u002F03-terminal.json","Version control and terminal",[556,559,562,564,567],{"name":557,"note":558,"key":245},"Git","Every project is a repository, including the client sites that were never supposed to have one. It is also the reason I can work on a live site and still have a way back.",{"name":560,"note":561,"key":245},"Git Bash on Windows Terminal","POSIX habits on a Windows machine. Most tooling assumes a Unix shell, and it is less work to bring one than to translate every command.",{"name":477,"url":478,"note":563},"Public for the plugins, private for client work. Actions for anything that has to happen on a schedule.",{"name":565,"note":566},"Composer","PHP dependencies, and increasingly the autoloader inside plugins that used to get by without one.",{"name":568,"note":569},"npm","The other half of every build. Kept boring on purpose — a dependency in a plugin is a dependency in somebody's site.",{},"pages\u002Fuses\u002F03-terminal","The layer underneath everything else. Unglamorous, and the part I would miss first.","T-s-xcuuGET_9dm2M0uVTuhlZPPSeCAvRAiH65e1P4w",{"id":575,"category":576,"extension":471,"items":577,"meta":601,"order":602,"stem":603,"summary":604,"__hash__":605},"uses\u002Fpages\u002Fuses\u002F04-wordpress.json","The WordPress side",[578,582,586,589,593,597],{"name":579,"url":580,"note":581,"key":245},"React with @wordpress\u002Fcomponents","https:\u002F\u002Fdeveloper.wordpress.org\u002Fblock-editor\u002Freference-guides\u002Fcomponents\u002F","Plugin interfaces are applications mounted inside wp-admin. Using the WordPress components is why they look like they belong there rather than like something bolted on.",{"name":583,"url":584,"note":585,"key":245},"dnd-kit","https:\u002F\u002Fdndkit.com","Dragging that works from a keyboard and announces itself to a screen reader. Retrofitting that is far more expensive than choosing it.",{"name":587,"note":588,"key":245},"The WordPress REST API","The only seam between a plugin's PHP and its interface. It is what makes the PHP testable without a browser anywhere near it.",{"name":590,"url":591,"note":592},"Advanced Custom Fields Pro","https:\u002F\u002Fwww.advancedcustomfields.com","For client sites, where the content model lives. Fields named in the client's vocabulary, not the database's.",{"name":594,"url":595,"note":596},"Elementor","https:\u002F\u002Felementor.com","Not a compromise — the right answer when an in-house team edits weekly. Locked templates, a small palette, global styles set once.",{"name":598,"url":599,"note":600},"WooCommerce","https:\u002F\u002Fwoocommerce.com","With as few extension plugins as the requirement genuinely needs. Every add-on is a licence somebody has to keep paying.",{},1,"pages\u002Fuses\u002F04-wordpress","What goes into a plugin, and what goes onto a client site. Two different lists with two different standards.","j-NSUhkpvsb9v4-rYLa2FhTlS18t8gWF99Jgv4J-yDg",{"id":607,"category":608,"extension":471,"items":609,"meta":626,"order":627,"stem":628,"summary":629,"__hash__":630},"uses\u002Fpages\u002Fuses\u002F05-services.json","Hosting and delivery",[610,613,616,620,623],{"name":611,"note":612,"key":245},"The client's own hosting","Shared hosting, a control panel, no staging environment and no deploy pipeline. That is the honest description of most WordPress work, and pretending otherwise is how a rebuild gets quoted when a fix was needed.",{"name":614,"note":615,"key":245},"FTP against production","Not a preference, a constraint of agency work. It teaches one discipline above all: change one thing, verify it, keep a way back.",{"name":617,"url":618,"note":619,"key":245},"Cloudflare","https:\u002F\u002Fcloudflare.com","DNS, CDN and Pages. This site is prerendered and served from it.",{"name":621,"note":622},"A transactional email provider","Site mail leaves through a real provider, never the web host's PHP mail. This is the single most common reason a contact form fails silently.",{"name":624,"note":625},"Backups the client owns","To storage in their account, not mine. Leaving me should never mean leaving their data.",{},5,"pages\u002Fuses\u002F05-services","Mostly other people's infrastructure. The skill is working inside constraints I did not choose.","FbmQ8ReFvSj2JxfK-J7EKTve-3XXK3FlX2rLGYsSX4s",{"id":632,"category":633,"extension":471,"items":634,"meta":653,"order":247,"stem":654,"summary":655,"__hash__":656},"uses\u002Fpages\u002Fuses\u002F06-working.json","How I work",[635,638,641,644,647,650],{"name":636,"note":637,"key":245},"Model the data before the interface","The fastest way to make something expensive to own is to build the screens first and discover the shape of the data afterwards. True of a Laravel schema and of an ACF field group alike.",{"name":639,"note":640,"key":245},"Read the source before the documentation","Learned in two years of having nobody to ask. It is still the fastest route into an unfamiliar framework, and it is why picking up a new one is a week rather than a season.",{"name":642,"note":643,"key":245},"Ask who maintains it, before choosing how to build it","The same question opens every project. It decides page builder or custom theme, and it decides how much of an application belongs in its API rather than its front end.",{"name":645,"note":646},"Deep work in the morning, calls at night","US clients, Bangladesh time zone. The overlap is my evening, which leaves the mornings uninterrupted.",{"name":648,"note":649},"A repeated complaint is a specification","The same request from four unrelated clients is not an inconvenience. It is the only market research a one-person shop gets for free, and every plugin I have finished started there.",{"name":651,"note":652},"Write the handover in the maintainer's language","One of my plugins ships its maintainer notes in Bengali. Documentation somebody has to translate before using is documentation that will not be used.",{},"pages\u002Fuses\u002F06-working","Process rather than software. Most of it was learned the expensive way.","iaojSZmCa_ecT-IzSH3TzkN6K5Heshb2TELxA0DygII",[658],{"id":659,"title":660,"category":661,"extension":471,"image":662,"meta":668,"order":669,"stem":670,"__hash__":671},"gallery\u002Fpages\u002Fgallery\u002F06-plugin-settings.json","Settings, after the cuts","Plugins",{"src":663,"alt":664,"width":665,"height":666,"caption":667},"\u002Fimages\u002Fgallery\u002Fplugin-settings.webp","The spam settings screen in Defer Forms, with toggles for honeypot protection, a time-trap and duplicate-submission blocking",1400,1050,"Most of what a settings page wants to be belongs in the hooks API instead.",{},0,"pages\u002Fgallery\u002F06-plugin-settings","FnORlGVc8CiwZiDTKn47gc0jX559WJXPefZDoT_dpyA",{"id":5,"title":6,"body":673,"cover":813,"date":240,"description":241,"draft":242,"extension":243,"meta":814,"navigation":245,"path":246,"placeholder":242,"readingMinutes":247,"seo":815,"stem":249,"summary":250,"tags":816,"__hash__":257},{"type":8,"value":674,"toc":803},[675,677,691,693,695,697,699,701,703,717,719,723,725,727,729,733,735,753,755,757,759,761,765,767,769,771,773,775,777,779,797,799,801],[11,676,14],{"id":13},[16,678,679,683,687],{},[19,680,681,25],{},[22,682,24],{},[19,684,685,31],{},[22,686,30],{},[19,688,689,37],{},[22,690,36],{},[11,692,41],{"id":40},[43,694,45],{},[43,696,48],{},[43,698,51],{},[11,700,55],{"id":54},[43,702,58],{},[60,704,705,709,713],{},[19,706,707,67],{},[22,708,66],{},[19,710,711,73],{},[22,712,72],{},[19,714,715,79],{},[22,716,78],{},[43,718,82],{},[43,720,85,721,91],{},[87,722,90],{"href":89},[11,724,95],{"id":94},[43,726,98],{},[43,728,101],{},[43,730,104,731,109],{},[106,732,108],{},[43,734,112],{},[16,736,737,741,747,749,751],{},[19,738,117,739,122],{},[119,740,121],{},[19,742,125,743,129,745,133],{},[119,744,128],{},[119,746,132],{},[19,748,136],{},[19,750,139],{},[19,752,142],{},[43,754,145],{},[11,756,149],{"id":148},[43,758,152],{},[43,760,155],{},[43,762,158,763,162],{},[106,764,161],{},[43,766,165],{},[11,768,169],{"id":168},[43,770,172],{},[43,772,175],{},[43,774,178],{},[11,776,182],{"id":181},[43,778,185],{},[16,780,781,785,789,793],{},[19,782,783,193],{},[22,784,192],{},[19,786,787,199],{},[22,788,198],{},[19,790,791,205],{},[22,792,204],{},[19,794,795,211],{},[22,796,210],{},[11,798,215],{"id":214},[43,800,218],{},[43,802,221],{},{"title":223,"searchDepth":224,"depth":224,"links":804},[805,806,807,808,809,810,811,812],{"id":13,"depth":227,"text":14},{"id":40,"depth":227,"text":41},{"id":54,"depth":227,"text":55},{"id":94,"depth":227,"text":95},{"id":148,"depth":227,"text":149},{"id":168,"depth":227,"text":169},{"id":181,"depth":227,"text":182},{"id":214,"depth":227,"text":215},{"src":236,"alt":237,"width":238,"height":239},{},{"title":6,"description":241},[252,253,254,255,256],[818,963,1024],{"id":5,"title":6,"body":819,"cover":959,"date":240,"description":241,"draft":242,"extension":243,"meta":960,"navigation":245,"path":246,"placeholder":242,"readingMinutes":247,"seo":961,"stem":249,"summary":250,"tags":962,"__hash__":257},{"type":8,"value":820,"toc":949},[821,823,837,839,841,843,845,847,849,863,865,869,871,873,875,879,881,899,901,903,905,907,911,913,915,917,919,921,923,925,943,945,947],[11,822,14],{"id":13},[16,824,825,829,833],{},[19,826,827,25],{},[22,828,24],{},[19,830,831,31],{},[22,832,30],{},[19,834,835,37],{},[22,836,36],{},[11,838,41],{"id":40},[43,840,45],{},[43,842,48],{},[43,844,51],{},[11,846,55],{"id":54},[43,848,58],{},[60,850,851,855,859],{},[19,852,853,67],{},[22,854,66],{},[19,856,857,73],{},[22,858,72],{},[19,860,861,79],{},[22,862,78],{},[43,864,82],{},[43,866,85,867,91],{},[87,868,90],{"href":89},[11,870,95],{"id":94},[43,872,98],{},[43,874,101],{},[43,876,104,877,109],{},[106,878,108],{},[43,880,112],{},[16,882,883,887,893,895,897],{},[19,884,117,885,122],{},[119,886,121],{},[19,888,125,889,129,891,133],{},[119,890,128],{},[119,892,132],{},[19,894,136],{},[19,896,139],{},[19,898,142],{},[43,900,145],{},[11,902,149],{"id":148},[43,904,152],{},[43,906,155],{},[43,908,158,909,162],{},[106,910,161],{},[43,912,165],{},[11,914,169],{"id":168},[43,916,172],{},[43,918,175],{},[43,920,178],{},[11,922,182],{"id":181},[43,924,185],{},[16,926,927,931,935,939],{},[19,928,929,193],{},[22,930,192],{},[19,932,933,199],{},[22,934,198],{},[19,936,937,205],{},[22,938,204],{},[19,940,941,211],{},[22,942,210],{},[11,944,215],{"id":214},[43,946,218],{},[43,948,221],{},{"title":223,"searchDepth":224,"depth":224,"links":950},[951,952,953,954,955,956,957,958],{"id":13,"depth":227,"text":14},{"id":40,"depth":227,"text":41},{"id":54,"depth":227,"text":55},{"id":94,"depth":227,"text":95},{"id":148,"depth":227,"text":149},{"id":168,"depth":227,"text":169},{"id":181,"depth":227,"text":182},{"id":214,"depth":227,"text":215},{"src":236,"alt":237,"width":238,"height":239},{},{"title":6,"description":241},[252,253,254,255,256],{"id":259,"title":260,"body":964,"cover":1020,"date":347,"description":265,"draft":242,"extension":243,"meta":1021,"navigation":245,"path":89,"placeholder":242,"readingMinutes":224,"seo":1022,"stem":350,"summary":351,"tags":1023,"__hash__":354},{"type":8,"value":965,"toc":1018},[966,968,970,972,974,976,978,980,982,984,986,988,1004,1006,1008,1010,1012,1014,1016],[43,967,265],{},[43,969,268],{},[43,971,271],{},[43,973,274],{},[43,975,277],{},[43,977,280],{},[43,979,283],{},[43,981,286],{},[43,983,289],{},[43,985,292],{},[43,987,295],{},[16,989,990,992,994,996,998,1000,1002],{},[19,991,300],{},[19,993,303],{},[19,995,306],{},[19,997,309],{},[19,999,312],{},[19,1001,315],{},[19,1003,318],{},[43,1005,321],{},[43,1007,324],{},[43,1009,327],{},[43,1011,330],{},[43,1013,333],{},[43,1015,336],{},[43,1017,339],{},{"title":223,"searchDepth":224,"depth":224,"links":1019},[],{"src":343,"alt":344,"width":345,"height":346,"caption":223},{},{"title":260,"description":265},[252,353,255],{"id":356,"title":357,"body":1025,"cover":1088,"date":457,"description":223,"draft":242,"extension":243,"meta":1089,"navigation":245,"path":459,"placeholder":242,"readingMinutes":247,"seo":1090,"stem":461,"summary":462,"tags":1091,"__hash__":466},{"type":8,"value":1026,"toc":1081},[1027,1029,1031,1033,1035,1037,1041,1061,1063,1065,1067,1069,1071,1073,1075,1077,1079],[11,1028,363],{"id":362},[43,1030,366],{},[43,1032,369],{},[43,1034,372],{},[11,1036,376],{"id":375},[43,1038,379,1039,383],{},[106,1040,382],{},[16,1042,1043,1047,1053,1057],{},[19,1044,1045,391],{},[22,1046,390],{},[19,1048,1049,397,1051,401],{},[22,1050,396],{},[119,1052,400],{},[19,1054,1055,407],{},[22,1056,406],{},[19,1058,1059,413],{},[22,1060,412],{},[43,1062,416],{},[11,1064,420],{"id":419},[43,1066,423],{},[43,1068,426],{},[43,1070,429],{},[11,1072,433],{"id":432},[43,1074,436],{},[43,1076,439],{},[11,1078,443],{"id":442},[43,1080,446],{},{"title":223,"searchDepth":224,"depth":224,"links":1082},[1083,1084,1085,1086,1087],{"id":362,"depth":227,"text":363},{"id":375,"depth":227,"text":376},{"id":419,"depth":227,"text":420},{"id":432,"depth":227,"text":433},{"id":442,"depth":227,"text":443},{"src":455,"alt":456,"width":345,"height":346},{},{"title":357,"description":223},[256,464,465],{"id":468,"booking":469,"email":470,"extension":471,"meta":1093,"name":473,"role":474,"socials":1094,"stem":485,"summary":486,"whatsapp":487,"__hash__":488},{},[1095,1096,1097],{"label":477,"url":478},{"label":480,"url":481},{"label":483,"url":484},{"id":468,"booking":469,"email":470,"extension":471,"meta":1099,"name":473,"role":474,"socials":1100,"stem":485,"summary":486,"whatsapp":487,"__hash__":488},{},[1101,1102,1103],{"label":477,"url":478},{"label":480,"url":481},{"label":483,"url":484},1790468642891]