Discovery before file names

I ask who touches the system daily: marketing, operations, support, external authors? I map inputs and outputs—CSV imports, CRM webhooks, PDFs, inventory feeds—not just “we need a settings page.” I also confirm hosting reality: managed WP, bedrock-style deploys, Redis object cache, headless frontends. Those choices decide whether I lean on transients, Action Scheduler, custom tables, or external queues.

Plugin versus theme: a hard line

Functionality that survives a redesign belongs in a plugin. Presentation—templates, layout, brand-specific CSS—stays in the child theme or block theme. When that line blurs, clients pay twice: once to rebuild the look, again to untangle logic that was never portable. I document the split in README so the next agency does not “helpfully” merge everything into functions.php.

Scope in phases, not fantasies

I ship a minimum viable workflow first: the path that removes the worst manual pain. Nice-to-haves—extra reports, secondary integrations, granular roles—go on a phase list with estimates. Business plugins fail when v1 tries to be Salesforce; they succeed when v1 reliably does one job every weekday.

Structure I can still read in two years

Namespaces, Composer autoloading, and a clear split between bootstrap/hooks and domain classes are non-negotiable for anything I expect to maintain or hand off. For the full pattern—PSR-4, adapters, public API surface—I point people to Structuring WordPress plugins for long-term maintenance; here the point is simple: if only one file is doing everything, the business logic will rot.

Data: CPTs, meta, or custom tables

Custom post types and meta are fine for editorial and listable content. When the client needs high-volume events, relational reporting, or strict constraints, I model storage deliberately—sometimes custom tables with activation migrations, sometimes external systems the plugin integrates with. The wrong storage shows up as slow admin screens and “mysterious” timeouts under load.

Admin UX editors will actually use

Capabilities and nonces are table stakes. Beyond that, I optimize for obvious labels, sane defaults, validation messages that sound human, and screens that do not require a training PDF. If the business needs Block Editor integration, I plan for blocks or block variations instead of dumping shortcodes that only I remember.

Living with page builders and caching

Real sites run Elementor, Divi, WP Rocket, Cloudflare, and cookie consent banners. I avoid assumptions about query timing, output buffering, and fragment caching. When dynamic data must show on cached pages, I design AJAX or edge-friendly endpoints and document cache exclusions instead of blaming “the host.”

Updates, compatibility, and ownership

I version semantically, keep a changelog business stakeholders can skim, and test against the next WordPress release before clients see white screens. For public directory plugins, review guidelines and support load matter; for private client plugins, update contracts and backup discipline matter more than star ratings.

What “done” means

A plugin is done when the client can execute the workflow without me on Slack, when permissions match the org chart, and when I would not be embarrassed to open the repo in six months. Everything else is a workshop exercise.

WordPress is still a brilliant glue layer for businesses that live on content and integrations. Plugins done right are operational software, not theme ornaments—and I build them accordingly.