Implementation roadmap

Mesh: foundation plan & phased rollout.

Gillish Mesh is a parked Phase 0 skeleton. The directory layout, namespace, slug, and plugin identity are committed to disk and locked; no functional feature exists yet. This page is the forward plan, not a build history: why Mesh is a standalone plugin rather than a Node module, the six-phase rollout from Foundation to Polish, the re-entry checklist, the known risks, and an index of the in-repo plans/ corpus. The plans are mirrored here, not moved , gillish-mesh/plans/ stays the source of truth in the repo.

Where Mesh stands#

Mesh is at Phase 0: scaffolded skeleton. The scaffold shipped 2026-05-02: the full Gillish house architecture on disk, a PSR-4 src/ tree with Autoloader.php, a single Plugin.php hook registry, Core/{Installer,DbMigrator,HeaderCipher}, Shared/{Options,Hooks} constant facades, empty Crawl/ Graph/ Admin/ Privacy/ Integrations/ directories held by .gitkeep, plus templates/, assets/, uninstall.php, readme.txt and CHANGELOG.md. The directory layout, file naming, namespace (Gillish\Mesh\*), slug (gillish-mesh) and plugin identity are locked (plan §5); functional features are not. The project is deliberately parked until Gillish Cairnstone and Gillish Node ship, the skeleton plus the two specs exist so the design doesn’t drift and the re-entry cost stays near zero.

Why standalone, not a Node module#

A first draft scoped this work as a module inside Gillish Node. A peer review raised that crawling-other-sites is materially more controversial than the rest of Node, link management, content graphs, GSC integration are all “operate on your own site” use cases nobody flags ethically; a crawler is different. Three options were weighed: a standalone plugin, a Pro-gated Node module, or dropping the feature. The author chose standalone, for five reasons: reputational isolation (Node’s wp.org listing stays focused on the “snill” feature set), compliance posture (corporate / agency code scans of Node find no crawler regardless of toggle state), independent update cadence (Cloudflare-evasion fixes don’t force Node releases), pricing flexibility, and ethical positioning (“a specialist tool you opt into buying” reads differently from “a feature in your link manager”).

The accepted trade-off: shared services (PageRank, levels, graph build, the D3 canvas, dark-mode CSS, branded UI) cannot be imported from Node, they are re-implemented fresh (~1–2 weeks of one-time foundation work). No Composer package, no shared filesystem: wp.org plugins can’t rely on Composer at runtime, a shared package would couple two independent release schedules, and the shared surface (~430 lines of PageRank + Levels + GraphBuilder) is small enough that duplication is cheaper than the abstraction. The Better Together detection layer closes the gap for installs that have both.

The phased rollout#

Each phase ends with a manual verification pass on a real target (the author’s staging site or a friendly blogger who has given permission). When something works end-to-end, the version ships and a DONE-WORK entry is written. The calendar is “weeks of focused work”, while the project is parked, that calendar doesn’t tick.

Phase 0: skeleton (done, 2026-05-02)#

Directory layout, file naming, namespace, and plugin identity committed to disk and version-tracked; the plan and brief preserved alongside the empty shell. 0.1.0-skeleton.

Phase 1: Foundation → v0.9.0#

Plugin scaffold, autoloader, the real DbMigrator (dbDelta against the two-table §7 schema, DB_VERSION starting at 1), settings-page skeleton, uninstall. Empty admin pages. Verifies the activation / deactivation / uninstall round-trip on a real WP install.

Phase 2: Crawler MVP → v1.0.0#

SitemapFetcher, PageFetcher (realistic Chrome UA + headers, Cloudflare-challenge detect-and-explain), LinkExtractor (hardened DOMDocument, main / article / body scoping), CrawlJob, the WP-Cron-backed CrawlQueue, HeaderCipher (AES-256-CBC, keyed off wp_salt('auth')). A WP_List_Table of past crawls + a new-crawl form. No graph view yet.

Phase 3: Single-graph view → v1.1.0#

PageRankService (~80 lines, pure, no WP coupling), LevelsService (~150 lines, LCC discovery + L1..Ln BFS), GraphBuilder (~200 lines, reads the plugin’s own pages table, anchor text a first-class output), and the self-contained D3 v7 canvas (mesh-graph.js, ~400 lines). The Their site tab only.

Phase 4: Comparison + Better Together → v1.2.0#

The Your site tab (both the standalone-self-crawl path and the Gillish Node bridge), the Compare tab with the metrics table and clickable ⚠ insight chips, and GillishNodeBridge. v1 feature-complete. (Pricing model is decided at this phase entry.)

Phase 5: Polish → v1.2.x + launch#

Dark mode (mesh-dark.css + a color-scheme JS, own implementation, mirroring Node’s body-class pattern), CSV export, the re-crawl button, the retention sweep, the configurable param-blocklist UI. Then the wp.org listing + the Pro-tier sale page go live.

Phase 6: Deferred (demand-driven)#

Topical-NLP overlap, scheduled recurring crawls, multi-competitor overlay, true synchronised side-by-side D3, a REST API, SERP-API integration, CSV import (a strong v2 candidate, sidesteps Cloudflare entirely). Each becomes its own plan if and when prioritised, after Phase 5 ships and gets used.

When picking this up#

The plan’s §21 re-entry checklist, verbatim in intent:

  • The name is locked: Gillish Mesh, slug gillish-mesh, namespace Gillish\Mesh\*. Don’t second-guess it, renaming a WP slug after release is painful, and the Node + Mesh pairing is the right brand call.
  • Set up a Git repo (Mesh is currently Dropbox-durable, not version-controlled). The plan is the seed; on resume it moves into the new repo’s plans and out of any holding location.
  • Start with Phase 1 scaffolding, the §6.1 directory layout is ready to instantiate.
  • Don’t share code with Gillish Node directly. The Better Together bridge (plan §14) is the only contact surface: a one-way read of one transient + a class_exists check. That is the whole API contract.
  • The algorithm services (PageRankService, LevelsService, GraphBuilder) can be lifted as starting points from Node’s src/Graph/Services/, but they need de-WP-coupling; write fresh implementations against Mesh’s own data sources.
  • Set up the build / zip pipeline early, mirror Node’s make-zip hygiene (exclude markdown, dotfiles, plans/, CHANGELOG.md per Plugin Check).

Risks & open questions#

  • WP-Cron reliability: the same problem Node has; low-traffic sites stall crawls. Mitigation: a detect-and-warn admin notice with a “Force tick” button; Action Scheduler is a Phase 6 candidate.
  • Performance at 1,000 pages: ~17 min per crawl at 1 req / sec; acceptable as background work, the UI must communicate it.
  • Sitemap quality: some sites have broken or no sitemaps; v1 fails gracefully with a paste-the-URL message; v2 is an HTML-crawl fallback.
  • Cloudflare success rate: the realistic-UA path slips through ~70–80% of free-tier configs; paid WAF / Turnstile / “I’m Under Attack” is not solvable from PHP, the clear-error path is honest graceful degradation, not a pretended bypass.
  • GDPR / data-controller exposure: specified in plan §16; the tool-provider model (the WP site owner is the controller) is the framing; custom_headers is encrypted at rest, an exporter / eraser is wired, retention defaults to 90 days, and a first-use disclaimer names the controller role before any crawl can start.
  • No shared services: ~430 lines of fresh PageRank / Levels / GraphBuilder that must be correct first time; mitigation: lift the proven Node algorithms as a starting point and de-WP-couple.
  • Keeping the plugin focused: the non-goals are load-bearing; a single-purpose tool that does structural comparison well beats a half-baked SEO suite. The biggest standing risk is simply that the project stays parked, the skeleton + plan + brief keep the re-entry cost low precisely for that reason.

The plans corpus#

The plans/ folder is excluded from the build zip , these documents never reach end users, but it is the strategic working surface. This page mirrors its shape; the folder itself is not relocated. At Phase 0 the corpus is deliberately small, two canonical specs:

  • GILLISH-MESH-PLAN.md: how to build it: 21 sections covering the why-standalone reasoning, the architecture and the fresh-write services, the two-table schema, the crawl-pipeline state machine, the Cloudflare strategy, link extraction, the Better Together bridge, privacy / GDPR, the phased rollout, and the re-entry checklist.
  • PRODUCT-BRIEF.md: what / who / why / pricing / distribution / metrics: the strategic counterpart, with the OPEN questions consolidated in §16. Surfaced on the Product brief page.

When Phase 1 starts, the corpus grows the Node way, active plans in plans/, a DONE-WORK.md the finished plans summarise into, holding tanks for deferred / polish ideas, but that structure is intentionally not pre-built while parked.

Ecosystem position#

Mesh is one tool in the Gillish network (Core · Node · Cairnstone · Feed · Mesh). It stands fully on its own and gets better together with Gillish Node: when both are installed, the Your site tab auto-loads from Node’s gn_graph_data_cache transient instead of requiring a redundant self-crawl, saving the user ~15 minutes and making the comparison internally consistent with the graph they already see in Node. Cross-navigation buttons and a shared dark-mode default round it out. The boundary is deliberate and one-way: no data-write into Node, no shared option keys, no Node-side hooks invoked, a small Node-side change (a Content-Graph card, a bento card) is its own Node-roadmap item for when Mesh actually ships. Ecosystem-spanning infrastructure (this docs network, global memory) is owned by Gillish Core, not lodged in whichever plugin created it first.