WordPress plugin for NPS feedback surveys. All data stored locally — no third-party services. React admin SPA + public widget.
Entry: allfeedback.php → src/Plugin.php
# Frontend (pnpm 10.30.0, Node >=20)
pnpm dev # webpack watch + HMR
pnpm watch # webpack watch, no HMR
pnpm build # production build
pnpm lint # ESLint
pnpm format # prettier auto-fix TS/TSX
pnpm make-pot # regenerate translation POT
pnpm release # clean → build → POT → composer --no-dev → zip
# PHP
composer install
composer lint # phpcs
composer lint:fix # phpcbfNo test framework configured yet.
| Layer | Tech |
|---|---|
| PHP | PHP 8.2+ strict, WordPress 6.5+, PHP-DI 7.0 |
| React | React 18, TypeScript strict, TanStack Query v5 / Form v1 / Router v1 |
| Styling | Tailwind CSS v4, Radix UI, shadcn |
| Rich text | Tiptap v3 (form field editors) |
| Build | @wordpress/scripts (Webpack) |
| DB | WordPress wpdb, tables prefixed wp_af_ |
| Path | Purpose |
|---|---|
src/Core/ |
Bootstrap, DI container, service providers |
src/API/Controllers/V1/ |
REST controllers |
src/Survey/Manager.php |
Survey table gateway |
src/Infrastructure/Database/ |
Migrator + Migration base + repositories |
src/Modules/ |
Add-on system |
config/services.php |
PHP-DI bindings |
database/migrations/ |
Numbered migrations (0001_*.php) |
resources/scripts/admin/ |
React SPA entry (index.tsx) |
resources/scripts/frontend/ |
Widget entry (index.tsx) |
resources/scripts/blocks/ |
Gutenberg blocks (block.json + Edit.tsx + index.ts) |
| Table | Columns of note |
|---|---|
wp_af_surveys |
form_schema JSON, settings JSON, styling JSON, status, conflict_reason, response_count |
wp_af_responses |
response_data JSON, score, ip_hash, ip_address, guest_token, is_read, consent_given |
wp_af_survey_sessions |
session_id, survey_id, user_id, guest_id, status, started_at, submitted_at |
Base: /wp-json/allfeedback/v1/
Auth: write endpoints require manage_options; submission requires nonce only (allfeedback_submit).
Envelope: { success: bool, data: mixed }
Full spec: .claude/docs/api_reference.md
| Method | Path | Purpose |
|---|---|---|
POST |
/surveys |
Create survey (always draft) |
GET |
/surveys/{id} |
Load for editing |
PUT |
/surveys/{id} |
Autosave / save draft |
POST |
/surveys/{id}/publish |
Transition to published |
Auto-run on admin_init. WP-CLI is preferred in development:
wp allfeedback migrate # run pending
wp allfeedback migrate status # show all (name, batch, ran_at)
wp allfeedback migrate rollback # roll back last batch
wp allfeedback migrate rollback --step=2
wp allfeedback migrate reset # drop all plugin tables
wp allfeedback migrate refresh # reset + re-run allVerify tables: wp db query "SHOW TABLES LIKE 'wp_af%';"
- PHP-DI compiled container lives in
wp-content/uploads/allfeedback/di-cache/{version}/(path set inContainer::getCacheDir()). Changingconfig/services.phpor any DI-resolved class's constructor signature without clearing it crashes on boot withArgumentCountError:rm -rf "/c/Users/Themegrill/Local Sites/test/app/public/wp-content/uploads/allfeedback/di-cache" routeTree.gen.tsatresources/scripts/admin/routeTree.gen.tsis auto-generated by TanStack Router on every build. Never edit it manually.- WP JSON decoding — WordPress decodes JSON request bodies as
stdClass, not arrays. UsenormaliseJsonParam()helper and widen arg types to['object','array','string','null']. - Admin SPA routing — Hash-based (
#/dashboard,#/forms). Don't usehistorymode — it conflicts with WP admin URLs.
| Priority | Item | Target file |
|---|---|---|
| Next | Targeting engine | src/Survey/Targeting.php |
| Next | Frontend asset enqueue | src/Survey/Assets.php |
| Later | Cron / data retention | src/Cron.php |
| Later | Widget HTML renderer | src/Survey/Renderer.php |
| Later | FormRepository DB impl | src/Infrastructure/Form/WpdbFormRepository.php |
Form builder API (POST/GET/PUT/publish) — complete and validated.
- Architectural Patterns — DI, service providers, REST conventions, React Query, module system
- API Reference — All endpoints with params and example responses