diff --git a/%plugin_name%.php b/%plugin_name%.php
index cdcec18..5eaf8d4 100644
--- a/%plugin_name%.php
+++ b/%plugin_name%.php
@@ -8,9 +8,9 @@
* Author URI: %plugin_author_uri%
* Text Domain: %plugin_name%
* Domain Path: /languages
- * Requires at least: 6.0
- * Tested up to: 6.9
- * Requires PHP: 8.2
+ * Requires at least: 7.1
+ * Tested up to: 7.1
+ * Requires PHP: 8.4
* Network: false
* License: MIT
* License URI: https://opensource.org/licenses/MIT
diff --git a/.github/README.md b/.github/README.md
new file mode 100644
index 0000000..1d56325
--- /dev/null
+++ b/.github/README.md
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+The plugin template that `php artisan pollora:make:plugin` downloads: a WordPress plugin registered with [Pollora](https://pollora.dev), with a PSR-4 `app/` directory, service providers, hooks declared with PHP attributes, Blade views and an optional Vite build. You start from a plugin that already loads, instead of wiring `add_action()` calls and a bootstrap file by hand.
+
+## Installation
+
+```bash
+php artisan pollora:make:plugin my-plugin
+```
+
+The command downloads the latest tag of this template, replaces its placeholders with your plugin's name, namespace and header, and offers to activate the plugin. With assets (`--asset`), it also runs `npm install` and `npm run build`; without them, the Vite files are left out.
+
+Requirements: a Pollora project (PHP 8.4+ and WordPress 7.1+ for a new one; the framework itself runs on PHP 8.3+), and Node.js 20.19+ or 22.12+ (Vite 8) when the plugin has assets.
+
+## Structure
+
+```
+%plugin_name%/
+├── app/ # Application code (PSR-4 autoloaded)
+│ ├── Providers/ # Service providers (plugin, assets)
+│ └── %plugin_namespace%Plugin.php # Main plugin class: activation, hooks
+├── config/plugin.php # Name, version, text domain, assets path
+├── resources/
+│ ├── assets/ # CSS, JS files (Vite)
+│ └── views/ # Blade templates
+└── %plugin_name%.php # Main plugin file: header, pollora_register()
+```
+
+The main class declares its hooks with attributes, which Pollora discovers on its own:
+
+```php
+#[Action('init', priority: 10)]
+public function onInit(): void
+{
+ // …
+}
+```
+
+## Development
+
+```bash
+npm install # once
+npm run dev # Vite dev server with hot reload
+npm run build # production build
+```
+
+## Documentation
+
+- [Plugins](https://pollora.dev/advanced/plugins/): creating a plugin, its architecture, the command's options and asset management
+- [Hooks](https://pollora.dev/hooks/actions-filters/), [post types](https://pollora.dev/content/post-types/) and the rest of the framework at [pollora.dev](https://pollora.dev)
+
+## Template development
+
+This repository is a template: its files carry placeholders that `pollora:make:plugin` substitutes, and the PHP classes in `app/` are `.stub` files, so it does not run as is. Develop on a plugin generated under the code name set in `bin/package-plugin.sh`, then copy it back with `./bin/package-plugin.sh /path/to/the/plugin`, which turns the names back into placeholders. `php bin/tests/run.php` checks the result.
+
+## Contributing
+
+Contributions are welcome: see the [contributing guide](https://github.com/Pollora/.github/blob/main/CONTRIBUTING.md). Report security issues privately, as described in the [security policy](https://github.com/Pollora/.github/blob/main/SECURITY.md).
+
+## License
+
+The Pollora plugin template is open-source software licensed under the [MIT license](../LICENSE). © [RuBee group](https://rubee.group)
diff --git a/LICENSE b/LICENSE
index 4c0ea40..bc3cb93 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2025 RuBee group
+Copyright (c) 2025 RuBee group (https://rubee.group)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 79bb647..8c604f6 100644
--- a/README.md
+++ b/README.md
@@ -2,47 +2,51 @@
%plugin_description%
-## Description
+Built with [Pollora](https://pollora.dev) from the [plugin-default](https://github.com/Pollora/plugin-default) template.
-This plugin is built using the Pollora Framework, which provides a modern development experience by bridging Laravel and WordPress.
-
-## Requirements
-
-- WordPress 6.0 or higher
-- PHP 8.2 or higher
-- Pollora Framework
-
-## Directory Structure
+## What's inside
```
%plugin_name%/
-├── app/ # Application code (PSR-4 autoloaded)
-│ ├── Providers/ # Service providers
-│ └── %plugin_namespace%Plugin.php # Main plugin class
-├── config/ # Configuration files
+├── app/ # PHP classes, namespace Plugin\%plugin_namespace%
+│ ├── Providers/ # Service providers (plugin, assets)
+│ └── %plugin_namespace%Plugin.php # Main class: activation, hooks declared with attributes
+├── config/plugin.php # Name, version, text domain, assets path
├── resources/
-│ ├── assets/ # CSS, JS files (Vite)
-│ └── views/ # Blade templates
-└── %plugin_name%.php # Main plugin file
+│ ├── assets/ # CSS and JS, built with Vite (when generated with assets)
+│ └── views/ # Blade templates
+└── %plugin_name%.php # Plugin header, registers the plugin with Pollora
```
-## Development
+Hooks are declared on methods with attributes and discovered by Pollora, no `add_action()` needed:
-```bash
-# Install dependencies
-npm install
+```php
+#[Action('init', priority: 10)]
+public function onInit(): void
+{
+ // …
+}
+```
-# Development with HMR
-npm run dev
+## Commands
-# Production build
-npm run build
+Run from the plugin's directory, when it has assets:
+
+```bash
+npm run dev # Vite dev server with hot reload
+npm run build # production assets
```
-## License
+From the project root:
-MIT — see [LICENSE](LICENSE).
+```bash
+php artisan pollora:make:block my-block --plugin=%plugin_name% # a new Gutenberg block
+php artisan discovery:clear # after adding attribute-based classes
+php artisan pollora:doctor # when something fails without an error
+```
-## Credits
+## Read more
-- Built with [Pollora Framework](https://pollora.dev)
+- [Plugins](https://pollora.dev/advanced/plugins/): architecture, namespaces, discovery, assets
+- [Actions and filters](https://pollora.dev/hooks/actions-filters/)
+- [Gutenberg blocks](https://pollora.dev/blocks/gutenberg-blocks/)
diff --git a/bin/package-plugin.sh b/bin/package-plugin.sh
index b722aa3..89ddeab 100755
--- a/bin/package-plugin.sh
+++ b/bin/package-plugin.sh
@@ -35,6 +35,15 @@ if [ ! -d "$SOURCE" ]; then
exit 1
fi
+# The WordPress and PHP requirements in the plugin header belong to the
+# template, which follows the framework; the development copy lags behind.
+# Read them before the sync and put them back after it.
+TEMPLATE_MAIN="$TARGET_DIR/%plugin_name%.php"
+REQUIREMENTS=""
+if [ -f "$TEMPLATE_MAIN" ]; then
+ REQUIREMENTS=$(grep -E '^ \* (Requires at least|Tested up to|Requires PHP):' "$TEMPLATE_MAIN" || true)
+fi
+
# Sync files (exclude node_modules, locks, build artifacts, .git)
echo "Syncing files..."
rsync -av --delete \
@@ -43,13 +52,39 @@ rsync -av --delete \
--exclude='yarn.lock' \
--exclude='.git' \
--exclude='bin/' \
+ --exclude='/README.md' \
+ --exclude='/.github/' \
+ --exclude='/LICENSE' \
+ --exclude='/license.txt' \
"$SOURCE/" "$TARGET_DIR/" \
--quiet
+# package.json comes from the development copy, which declares no license (or
+# another one): the template's is MIT, the same as LICENSE.
+echo "Setting the package.json license to MIT..."
+node -e '
+const fs = require("fs");
+const [file, license] = process.argv.slice(1);
+const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
+let out = pkg;
+if ("license" in pkg) {
+ pkg.license = license;
+} else {
+ out = {};
+ for (const [key, value] of Object.entries(pkg)) {
+ out[key] = value;
+ if (key === "private") out.license = license;
+ }
+ if (!("license" in out)) out.license = license;
+}
+fs.writeFileSync(file, JSON.stringify(out, null, 4) + "\n");
+' "$TARGET_DIR/package.json" "MIT"
+
echo "Replacing code name with placeholders..."
find "$TARGET_DIR" -type f \
-not -path "*/.git/*" \
+ -not -path "*/.github/*" \
-not -path "*/node_modules/*" \
-not -path "*/bin/*" \
-not -name "package-plugin.sh" \
@@ -105,6 +140,14 @@ elif [ -f "$TARGET_DIR/%plugin_name%.php" ]; then
true
fi
+if [ -n "$REQUIREMENTS" ] && [ -f "$TEMPLATE_MAIN" ]; then
+ echo "Restoring the template's requirements in the plugin header..."
+ while IFS= read -r line; do
+ key="${line%%:*}"
+ sed -i "s|^${key//\*/\\*}:.*|${line}|" "$TEMPLATE_MAIN"
+ done <<< "$REQUIREMENTS"
+fi
+
echo "Checking nothing kept the code name..."
# The replacement rules above are a hand-maintained list, and theme-default
@@ -112,7 +155,7 @@ echo "Checking nothing kept the code name..."
# blocks added under resources/views went out naming the development theme.
# Nothing there noticed, because nothing looked afterwards. This looks.
if leaked=$(grep -rn "${CODE_NAME}\|${CODE_STUDLY}\|${CODE_FUNCTION}\|${CODE_UPPER}" "$TARGET_DIR" \
- --exclude-dir=.git --exclude-dir=node_modules --exclude=package-plugin.sh); then
+ --exclude-dir=.git --exclude-dir=.github --exclude-dir=bin --exclude-dir=node_modules --exclude=package-plugin.sh); then
echo ""
echo "Error: the code name survived packaging:"
echo "$leaked"