Clone
1
Architecture
David Keane edited this page 2026-06-09 02:24:53 +01:00

Architecture

RangerHQ Buddy is hand-rolled PHP — no frameworks, no Composer dependencies, no build step. The whole plugin is ~6 PHP files, one stylesheet, and zero JavaScript. Currently ~28 KB packaged.

High-level component map

   wp-admin
   ┌────────────────────────────────────────────────────────────────┐
   │  WP Dashboard                                                  │
   │  ┌──────────────────────────────────┐                          │
   │  │  Buddy Dashboard Widget          │  inc/dashboard-widget.php│
   │  │  - sprite (sm)                   │                          │
   │  │  - name + mood                   │                          │
   │  │  - four stat bars (h/h/h/e)      │                          │
   │  └──────────────────────────────────┘                          │
   │                                                                │
   │  Sidebar: 🐾 Buddy ▾                                           │
   │  ├─ My Buddy       inc/admin-page.php                          │
   │  ├─ Settings       inc/settings.php   (rename Buddy)           │
   │  └─ About          inc/about.php      (roadmap + version)      │
   └────────────────────────────────────────────────────────────────┘
                            │
                            │ buddy_get_state / buddy_update_state
                            ▼
   ┌────────────────────────────────────────────────────────────────┐
   │  inc/state.php — per-user storage in wp_usermeta               │
   │  Key: 'buddy_state'                                            │
   │  Shape: { name, species, hunger, happiness, health, energy,    │
   │           born_at, last_tick }                                 │
   └────────────────────────────────────────────────────────────────┘
                            │
                            │ values feed → mood label + tone selection
                            ▼
   ┌────────────────────────────────────────────────────────────────┐
   │  inc/sprite.php — inline-SVG renderer                          │
   │  buddy_render_sprite( $tone, $size )                           │
   │  - tones: happy / neutral / sad / wink (cheeky surprise)       │
   │  - sizes: sm / md / lg                                         │
   │  - no image files, no GIFs — every pixel is SVG                │
   │  - CSS keyframes drive bobbing + blinking, NOT JS              │
   └────────────────────────────────────────────────────────────────┘

The four load-bearing decisions

1. Per-user state in wp_usermeta (not wp_options)

Each WP admin user gets their own Buddy. Storage is update_user_meta( $user_id, 'buddy_state', $state ). This means multi-admin sites work perfectly — Alice's Buddy is independent of Bob's. Nothing is shared between accounts.

The alternative (a single wp_options row for the whole site) would have meant either everyone shares one Buddy or a complex multi-row schema. wp_usermeta makes per-user a one-liner.

2. Inline-SVG character (no GIFs, no sprite sheets, no PNGs)

inc/sprite.php outputs an <svg> element directly into the page HTML. Eye shapes, mouth curves, cheek dots — all paths/circles in SVG, all parameterised by the $tone and $size arguments. Switching mood doesn't change the image; it changes a couple of SVG element attributes.

Why: zero asset weight, zero HTTP requests for the character, infinite scalability, easy to extend (add a new mood by adding a few SVG elements, not by drawing a new sprite sheet).

3. CSS-only animations (no JavaScript)

Bobbing motion and periodic blinking are CSS keyframes in assets/css/buddy.css. The wink animation that landed in v0.1.3 is also a CSS animation, not a JS timer. The plugin ships zero JavaScript for the character itself.

The only JS in the whole plugin is the WP-native admin form scaffolding (the rename form on the Settings page uses standard WordPress nonces and a POST submission — no AJAX).

4. Tier-1 admin discipline

Carried forward from the broader RangerHQ family submission discipline (see Family):

  • Single <h1> per admin page (accessibility + WordPress conventions)
  • No nested toggle boxes
  • No duplicate sections
  • Output escaping on every user-facing string (esc_html_e, esc_attr_e, etc.)
  • Text-domain alignment across every translation call ('rangerhq-buddy')
  • wp_rand() instead of mt_rand() for any randomness
  • All CSS in enqueued stylesheets — no inline <style> blocks, no inline style="..." attributes (lesson hard-won in v0.1.5 after wp.org reviewer flagged it)

File-by-file walkthrough

If you've cloned the repo and want to understand the flow, read these files in order:

  1. buddy.php — the entry point WordPress sees. Plugin header (Plugin Name, version, text domain), constants (BUDDY_VERSION, paths), require_once for the inc/*.php files, admin_menu registration, admin_enqueue_scripts enqueue, activation hook.
  2. inc/state.phpbuddy_default_state(), buddy_get_state(), buddy_update_state(). The data layer.
  3. inc/sprite.phpbuddy_render_sprite( $tone, $size ). The SVG character renderer.
  4. inc/dashboard-widget.php — registers the WP Dashboard widget via wp_add_dashboard_widget(). Calls buddy_get_state() + buddy_render_sprite('happy', 'sm') + renders stat bars.
  5. inc/admin-page.php — the dedicated "My Buddy" page in the sidebar. Larger sprite + same data.
  6. inc/about.php — the About page (intro, "what Buddy does today", roadmap, version history). All inline styles removed in v0.1.5.
  7. inc/settings.php — the rename-Buddy form. Nonce + POST handling.

Total reading time end-to-end: about 15 minutes.

Permission profile (deliberately narrow)

Buddy is a wp-admin-only plugin. It:

  • Does NOT register front-end shortcodes
  • Does NOT enqueue assets on the public site
  • Does NOT create custom post types, taxonomies, or REST API endpoints
  • Does NOT call any external service (no API requests, no telemetry, no CDN fonts)
  • Only loads its CSS on the four admin pages it owns (Dashboard, My Buddy, Settings, About)
  • Stores everything in wp_usermeta on the user's own WP site

What's coming (Phase B onwards)

See Roadmap for the full phase plan. Architectural changes anticipated:

  • Phase B (Interactions): Feed / Play / Clean / Sleep buttons — will add a small inc/actions.php with cooldown timer logic, AJAX endpoints, and a single new JS file (the first JS the plugin will ever ship).
  • Phase C (Decay): WP-cron event that lowers stats over time when the user is away. Pure server-side, no JS.
  • Phase D (Species): Multi-species sprite renderer. inc/sprite.php will grow species-specific path libraries.
  • Phase E (Site health): wp_get_site_health() results feed into mood/stat calculations. Pure server-side hook.
  • Phase F (Pro): Custom skins, multi-pet farm, social visits.

The core architecture (per-user state, inline-SVG, CSS animations) is locked and won't change across phases.