Add documentation for content system, newsletter plugin, petition

system, and templates

Add content system documentation

Add newsletter plugin documentation

Add petition system documentation

Add templates documentation
This commit is contained in:
Ruben 2026-02-06 19:15:29 +01:00
parent 2f024e28be
commit a142b0562f
4 changed files with 521 additions and 0 deletions

94
docs/newsletter-plugin.md Normal file
View file

@ -0,0 +1,94 @@
# Newsletter Plugin Reference
For LLM agents working on the newsletter signup. Read when modifying newsletter functionality.
## Overview
Modular newsletter signup that can be embedded on any page. Uses Listmonk's public subscription API for double opt-in. Located in `custom/plugins/page/newsletter-signup.php`.
## How It Activates
Add to a page's `metadata.ini`:
```ini
plugins = "newsletter-signup"
```
Then call from PHP content files:
```php
<?= newsletter_signup('Your custom intro text here', 'hero') ?>
<?= newsletter_signup('Short text here', 'small') ?>
```
## Themes
| Theme | Description | HTML Element |
|---|---|---|
| `hero` | Full-width gradient background section (green->blue). Centered form with pill-shaped inputs. | `<section>` |
| `small` | Compact inline box with green border. Fits between paragraphs. | `<aside>` |
## Function Signature
```php
newsletter_signup(string $introText, string $theme = 'hero', string $formId = 'newsletter'): string
```
- `$introText` - Displayed above the form
- `$theme` - `'hero'` or `'small'`
- `$formId` - HTML id for the section (for anchor links)
## How It Works
1. Form submits via JavaScript `fetch()` (AJAX) - this is the ONE place JS is used on the site
2. Server validates: CSRF token, rate limit (30s), name/email
3. Calls Listmonk public subscription API
4. Returns JSON response
5. Button shows success/error state with animation
## Listmonk Integration
Config: `custom/listmonk-config.php` (not in repo, see `listmonk-config.example.php`)
```php
return [
'enabled' => true,
'url' => 'https://your-listmonk-instance.com',
'list_uuids' => ['uuid-1', 'uuid-2'],
];
```
Uses Listmonk's **public** subscription API (`/api/public/subscription`). No authentication needed. Listmonk handles its own double opt-in flow.
## Anti-Spam
1. **CSRF token** - Separate from petition (`newsletter_csrf_token`)
2. **Rate limit** - 30 seconds between submissions (session-based)
3. **Input validation** - Name 2-100 chars, valid email, max 100 chars
## Translation Keys
All use `newsletter.*` prefix in language files:
- `newsletter.name_label`, `newsletter.name_placeholder`
- `newsletter.email_label`, `newsletter.email_placeholder`
- `newsletter.notice` (e.g., "We send about 12 emails per year")
- `newsletter.submit_button`
- `newsletter.success_message`, `newsletter.error_message`
## Static Resources
CSS and JS are inlined in the output via static helper functions:
- `newsletterGetStyles()` - Included once per page (static flag)
- `newsletterGetScript()` - Included once per page (static flag)
This means multiple `newsletter_signup()` calls on one page share a single copy of CSS/JS.
## Critical: Do Not Break
1. **AJAX submission** - The form uses `fetch()` with JSON response. The `newsletterHandleSubmission()` function runs early (before any output) and calls `exit` after sending JSON.
2. **CSRF separate from petition** - Uses `newsletter_csrf_token` session key, not the petition's `csrf_token`.
3. **Static inclusion guards** - `$stylesIncluded` and `$scriptIncluded` static vars prevent duplicate CSS/JS. Do not reset these.
4. **Button states** - CSS classes `is-loading`, `is-success`, `is-error` control button feedback. The JS depends on these class names and `data-*` attributes.
5. **`escape` class on hero** - The hero section uses class `escape` to break out of the content container width. This is defined in `base.css`.
## Currently Used On
- Homepage (`content/index.php`) - hero theme with custom intro text