WP Manifestindependent plugin directory
manifest / integrations / wp-static-interactivity

Static Interactivity

This plugin adds interactivity to static WordPress sites

by DarkMatter-999 · github.com/darkmatter-999/wp-static-interactivity · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/darkmatter-999/wp-static-interactivity/archive/refs/heads/master.zip

Readme

Static Interactivity

Static Interactivity offloads dynamic WordPress features to Supabase, a PostgreSQL-based BaaS. When your WordPress site is exported to static HTML (e.g. with Simply Static), visitors still get full-text search and threaded comments powered by direct client-side calls to Supabase.

The plugin replaces the WordPress native search and comment blocks with custom web components (<dmsi-search> and <dmsi-comments>) that query Supabase directly from the browser. No page reloads needed.

Features

  • Supabase Full-Text Search — PostgreSQL tsvector with weighted title/excerpt, prefix matching, pagination.
  • Search Suggestions — Show recent posts when no results are found.
  • Custom Search Slug — Configurable URL (default /search/) backed by a real WordPress page.
  • Live Comments — Visitors read and submit comments directly via Supabase REST API.
  • Comment Template — Uses the active theme's comment block HTML, extracted at render time.
  • Bidirectional Comment Sync — Daily cron + manual sync keeps WordPress and Supabase in sync.
  • Status Sync — Approve, hold, spam, or trash from WordPress admin; status updates propagate to Supabase.
  • Post Sync — Published posts are pushed to the search index on save (async, non-blocking).
  • Static Site Ready — All dynamic operations happen client-side; no PHP required after export.
  • No Framework Runtime — Vanilla web components, zero JavaScript framework overhead.

Requirements

  • WordPress 6.9+
  • PHP 8.1+
  • A Supabase project (free tier works)

Installation

  1. Upload the wp-static-interactivity folder to /wp-content/plugins/.
  2. Activate the plugin via Plugins.
  3. Go to Settings > Static Interactivity.
  4. Enter your Supabase project URL, anon (publishable) key, and service_role (secret) key.
  5. Create the required tables in Supabase SQL Editor (schema is displayed on the settings page).
  6. Create a WordPress page with the slug matching your configured search slug (default: search).

Setup Guide

1. Supabase Tables

Run these statements in the Supabase SQL Editor.

Search index table:

CREATE TABLE public.search_index (
    post_id BIGINT PRIMARY KEY,
    title TEXT,
    excerpt TEXT,
    featured_image_url TEXT,
    permalink TEXT,
    search_vector tsvector GENERATED ALWAYS AS (
        setweight(to_tsvector('simple', coalesce(title, '')), 'A') ||
        setweight(to_tsvector('simple', coalesce(excerpt, '')), 'B')
    ) STORED
);

CREATE INDEX search_index_search_vector_idx ON public.search_index USING GIN (search_vector);

ALTER TABLE public.search_index ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow public read-only access to search_index" ON public.search_index FOR SELECT USING (true);

Comments table:

CREATE TABLE public.comments (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    post_id BIGINT NOT NULL,
    author_name TEXT,
    author_email TEXT,
    content TEXT NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
    status TEXT DEFAULT 'pending'::text
);

ALTER TABLE public.comments ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Anyone can read approved comments" ON public.comments
    FOR SELECT TO anon USING (status = 'approved');

CREATE POLICY "Anyone can insert comments" ON public.comments
    FOR INSERT TO anon WITH CHECK (true);

GRANT USAGE ON SCHEMA public TO anon;
GRANT SELECT, INSERT ON public.comments TO anon;

2. Supabase Keys

  • Publishable Key — The anon/public key from your Supabase project (Settings > API). Sent to the browser.
  • Secret Key — The service_role key. Kept server-side. Used for sync operations that bypass RLS.

3. Search Page

Create a standard WordPress page with the slug you configure (default: search). The page can be empty. The plugin overrides its template to search.php and replaces the main query block with the search web component.

Configuration

Navigate to Settings > Static Interactivity.

Setting Description
Supabase URL Your Supabase project URL (e.g. https://xxxxx.supabase.co)
Supabase Publishable Key Anon key sent to the frontend for client-side Supabase queries
Supabase Secret Key Service role key used server-side for write operations
Search Slug URL slug for the search page (must match an existing WordPress page)
Search Suggestions Show recent posts when a search yields no results

Admin Tools

  • Replace All Search Data — Clears and rebuilds the entire search index.
  • Test Connection — Verifies Supabase connectivity and table existence.
  • Check Health — Compares WordPress post count vs Supabase row count.
  • Sync Comments Now — Two-phase sync: push WP comments to Supabase, pull new Supabase comments into WP.

Frontend Web Components

<dmsi-search>

Rendered on the search results page. Features:

  • Full-text search with PostgreSQL fts query
  • Pagination with Previous/Next buttons
  • Featured images, titles, excerpts rendered using the theme's post template HTML
  • Search suggestions on no results (optional)
  • Auto-populates the search input from query parameters

<dmsi-comments>

Rendered on singular posts where comments are open. Features:

  • Loads approved comments from Supabase ordered by date
  • Renders comments using the theme's comment block HTML (extracted at render time)
  • Avatar images via Gravatar (SHA-256 hashed email)
  • Load More pagination
  • Inline comment submission (status: pending)
  • No page reload for any operation

Development

Build

npm install
npm run build

Dev server (hot reload)

npm start

Linting

npm run lint:js        # ESLint
npm run lint:css       # Stylelint
npm run lint:php       # PHPCS

Type checking

npm run type-check     # PHPStan

Tests

npm run test:js        # Vitest
npm run test:php       # Pest PHP

Project structure

assets/
├── src/
│   ├── js/
│   │   ├── main.ts           # Search redirect logic
│   │   ├── search.ts         # <dmsi-search> web component
│   │   ├── comments.ts       # <dmsi-comments> web component
│   │   └── admin-sync.ts     # Admin sync AJAX interactions
│   └── css/
│       └── main.scss
include/
├── helpers/
│   └── autoloader.php        # PSR-4-like autoloader
├── traits/
│   └── trait-singleton.php   # Singleton pattern
└── classes/
    ├── class-plugin.php      # Plugin bootstrap
    ├── class-assets.php      # Script/style enqueuing
    ├── class-options.php     # Centralized option accessor
    ├── class-settings.php    # Admin settings page + AJAX handlers
    ├── class-search.php      # Search sync + frontend logic
    ├── class-comments.php    # Comments sync + frontend logic
    └── class-supabase-api.php # Supabase REST client

How It Works

Search

  1. When a post is saved, an async cron event pushes it to Supabase search_index.
  2. On the search page, the core/query block is replaced with <dmsi-search>.
  3. The JS component executes a full-text search via Supabase REST API using fts on the search_vector column.
  4. Results are rendered by cloning the theme's post template HTML from a `

Read the full README on GitHub →