Creating a Plugin
Generate the plugin structure
Use the plugin creation command:Or provide the name directly:This creates:
- Complete plugin directory structure
- PHP service provider and facade
- Android Kotlin and iOS Swift boilerplate
- JavaScript module
- Plugin manifest (
nativephp.json) - Tests and documentation
Configure the manifest
Edit
nativephp.json to define bridge functions, permissions, and dependencies.See Manifest Format below for details.Implement native code
Add your native functionality in:
resources/android/YourPluginFunctions.kt(Android)resources/ios/YourPluginFunctions.swift(iOS)
Add PHP implementation
Implement the PHP facade methods in
src/YourPlugin.php to call native code via nativephp_call().Manifest Format
Thenativephp.json manifest defines your plugin’s structure and requirements.
Basic Structure
Bridge Functions
Define native functions callable from PHP:Platform-Specific Configuration
Android
iOS
Assets
Declare static assets to copy during build:Events
List Laravel events your plugin dispatches:Hooks
Register commands that run during build phases:pre_compile- Before native code compilationpost_compile- After native code compilationcopy_assets- Copy ML models, binaries, etc.post_build- After native build completes
Secrets
Declare required environment variables:Native Implementation
Android (Kotlin)
Implement bridge functions inresources/android/YourPluginFunctions.kt:
iOS (Swift)
Implement bridge functions inresources/ios/YourPluginFunctions.swift:
PHP Implementation
Call native code from PHP insrc/Example.php:
Lifecycle Hooks
Create hook commands that extendNativePluginHookCommand:
$this->isAndroid()- Check if building for Android$this->isIos()- Check if building for iOS$this->pluginPath()- Get plugin directory path$this->buildPath()- Get native build directory path$this->copyToAndroidAssets($source, $dest)- Copy to Android assets$this->copyToIosBundle($source, $dest)- Copy to iOS bundle$this->downloadIfMissing($url, $path)- Download file if missing
Compiling Native Code
Android Compilation
Kotlin files inresources/android/ are automatically compiled during the build process:
- Files are copied to the Android project’s
app/src/main/java/directory - Gradle compiles them alongside the main app code
- Bridge functions are registered automatically
iOS Compilation
Swift files inresources/ios/ are automatically compiled:
- Files are added to the Xcode project
- Swift compiler builds them with the main app
- Bridge functions are registered automatically
Testing Your Plugin
The plugin generator creates a test suite intests/PluginTest.php:
- Manifest structure and required fields
- Bridge function definitions
- Native code files exist and contain expected classes
- PHP class structure
- Lifecycle hook configuration
Publishing Your Plugin
Prepare for release
- Update
README.mdwith usage instructions - Add examples and documentation
- Run tests:
./vendor/bin/pest - Validate manifest:
php artisan native:plugin:validate .
Publish to Packagist
Submit your repository to Packagist.org
Share with the community
Share your plugin in the NativePHP Discord
Best Practices
Use semantic versioning
Use semantic versioning
Follow SemVer for version numbers:
- Major version for breaking changes
- Minor version for new features
- Patch version for bug fixes
Document permissions clearly
Document permissions clearly
Explain why each permission is needed in your README so users understand what they’re granting.
Provide fallback behavior
Provide fallback behavior
Handle cases where native functionality isn’t available or fails gracefully.
Test on both platforms
Test on both platforms
Ensure your plugin works correctly on both iOS and Android before releasing.
Keep dependencies minimal
Keep dependencies minimal
Only include necessary native dependencies to avoid bloating the app size.
Use events for async operations
Use events for async operations
Dispatch Laravel events from native code for long-running operations.
Next Steps
Plugin System Overview
Learn how the plugin system works
Permissions
Configure native permissions for your plugin