Best Practices
On this page
#Overview
Building a plugin that works is only the first step. Building one that's easy to install, well-documented, and tested across platforms and frontend stacks is what makes a plugin worth publishing.
This page covers the standards we expect from plugins listed on the NativePHP Plugin Marketplace and what makes the difference between a plugin developers trust and one they abandon after 10 minutes.
#Documentation
Every plugin must ship with a comprehensive README. This is the first thing developers see and it determines whether they'll bother installing your plugin at all.
#Required README Sections
Your README should include all of the following:
Installation:
## Installation composer require vendor/my-plugin php artisan native:plugin:register vendor/my-plugin
PHP usage with complete examples:
## Usage (PHP) use Vendor\MyPlugin\Facades\MyPlugin; // Basic usage$result = MyPlugin::doSomething(['option' => 'value']); // Listening for events in Livewire#[OnNative(SomethingCompleted::class)]public function handleResult($data){ $this->result = $data['result'];}
JavaScript usage for SPA frameworks:
## Usage (JavaScript) import { DoSomething } from 'vendor-my-plugin'; // In Vue/React componentsconst result = await DoSomething({ option: 'value' });
Available methods, events, and required permissions — document every public method your facade exposes, every event your plugin dispatches, and every permission it requires. Don't make developers read your source code to figure out what your plugin does.
Environment variables and secrets — if your plugin requires API keys or tokens, document exactly where to get them and how to configure them.
#Keep Documentation Current
Update your README whenever you change your plugin's API. Outdated documentation is worse than no documentation — it actively misleads developers and wastes their time. If a method signature changes, update the README in the same commit.
#JavaScript Implementations
Every plugin must provide a JavaScript library alongside the PHP facade. Many NativePHP apps use Inertia with Vue or React, and those developers need to call your native functions directly from their components without going through Livewire.
Your resources/js/ directory should export clean, documented functions:
// resources/js/index.jsconst baseUrl = '/_native/api/call'; async function bridgeCall(method, params = {}) { const response = await fetch(baseUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ method, params }) }); return response.json();} export async function DoSomething(options = {}) { return bridgeCall('MyPlugin.DoSomething', options);} export async function DoSomethingElse(id, options = {}) { return bridgeCall('MyPlugin.DoSomethingElse', { id, ...options });}
Provide a named export for every bridge function your plugin exposes. If your plugin dispatches events, document how to listen for them in both Livewire and SPA contexts.
#npm Package
Consider publishing your JavaScript library as an npm package so developers can npm install it and get proper
TypeScript definitions, autocompletion, and tree-shaking.
#Testing on Real Devices
Simulators and emulators are useful for development, but they don't catch everything. Many native APIs behave differently — or don't work at all — on real hardware. Camera, biometrics, Bluetooth, NFC, GPS, and sensors all require real device testing.
#Requirements
- Android — test on a physical Android device. Don't rely solely on the Android emulator.
- iOS — test on a physical iPhone or iPad. The iOS simulator doesn't support camera, biometrics, or many hardware features.
- Test on devices running both current and previous major OS versions when possible.
#Provide a Test App
Ideally, provide a link to a test build so that the NativePHP team and other developers can verify your plugin works without having to set up the full build chain:
- iOS — distribute via TestFlight
- Android — distribute via a Google Play testing track (internal, closed, or open testing)
Include the test app link in your README and your plugin marketplace submission. This significantly speeds up the review process and builds trust with users.
#Frontend Stack Compatibility
NativePHP apps use different frontend stacks. Your plugin must work with all of them.
#Test With
- Livewire v3 — the most common stack for NativePHP apps. Test that
#[OnNative]event listeners work, that facade calls from Livewire actions return correct data, and that loading states behave properly. - Livewire v4 — test forward compatibility.
- Inertia + Vue — test your JavaScript library imports and bridge calls from Vue components. Verify events are received correctly.
- Inertia + React — same as Vue. Test imports, bridge calls, and event handling from React components.
If your plugin only supports a subset of these stacks, document this clearly in your README. But aim for full compatibility — it's the difference between a plugin that works for everyone and one that fragments the ecosystem.
#Example: Livewire Component
use Livewire\Component;use Native\Mobile\Attributes\OnNative;use Vendor\MyPlugin\Facades\MyPlugin;use Vendor\MyPlugin\Events\ScanComplete; class Scanner extends Component{ public ?string $result = null; public function scan(): void { MyPlugin::startScan(); } #[OnNative(ScanComplete::class)] public function handleScan($data): void { $this->result = $data['value']; } public function render() { return view('livewire.scanner'); }}
#Example: Vue Component (Inertia)
<script setup>import { ref } from 'vue';import { StartScan, OnScanComplete } from 'vendor-my-plugin'; const result = ref(null); OnScanComplete((data) => { result.value = data.value;}); async function scan() { await StartScan();}</script> <template> <button @click="scan">Scan</button> <p v-if="result">{{ result }}</p></template>
#Boost Guidelines
If your users use Laravel Boost, providing Boost guidelines makes your plugin dramatically easier to work with. When developers ask their assistant to use your plugin, it will know exactly how — which methods to call, what events to listen for, and how to handle responses.
Generate guidelines with:
php artisan native:plugin:boost
This creates resources/boost/guidelines/core.blade.php in your plugin. Edit it to include:
- All available facade methods with descriptions and parameter types
- All events your plugin dispatches with their payload shapes
- JavaScript usage examples
- Common patterns and gotchas
- Required permissions and configuration
When users install your plugin and run php artisan boost:install, these guidelines are automatically loaded.
#Validation
Run the validation command before every release:
php artisan native:plugin:validate
This catches:
- Manifest syntax errors and missing required fields
- Bridge function declarations that don't match native code
- Hook commands that aren't registered
- Missing declared assets
Your plugin should pass validation with zero errors. If you're using the
Plugin Dev Kit, use the /validate-nativephp-plugin command which runs additional
checks beyond the Artisan command.
Fix every warning too — they often indicate issues that will cause confusing failures for your users at build time or runtime.
#Checklist
Before submitting your plugin to the NativePHP Plugin Marketplace, verify:
- README documents installation, PHP usage, and JS usage with complete examples
- README documents all public methods, events, and required permissions
- JavaScript library exports a function for every bridge function
-
php artisan native:plugin:validatepasses with zero errors - Tested on a physical Android device
- Tested on a physical iOS device (if iOS is supported)
- Tested with Livewire v3 and v4
- Tested with Inertia + Vue
- Tested with Inertia + React
- Boost guidelines are included (
php artisan native:plugin:boost) - TestFlight and/or Google Play testing track link provided
- All secrets and environment variables are documented
- Changelog is maintained for version history
#Official Plugins & Dev Kit
The official NativePHP plugins follow all of these best practices and serve as reference implementations. Browse them on the Plugin Marketplace for examples of well-structured, well-documented plugins.
Need help building your plugin to these standards? The Plugin Dev Kit generates production-ready plugins with proper structure, documentation, and Boost guidelines built in.