emran-alhaddad / statamic-content-sync
Export/import Statamic Entries, Navigation, Taxonomies, Assets, Globals with a CP UI and diff preview.
Installs: 9
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:statamic-addon
Requires
- php: ^8.1
- laravel/framework: ^10.0|^11.0
- statamic/cms: ^5.0
Requires (Dev)
- laravel/pint: ^1.13
README
Export/import Collections, Navigation, Taxonomies, Assets, Globals with a Statamic Control Panel UI. See diffs like Git, choose Accept incoming or Keep current per item, then commit the import safely.
✨ Features
- One UI for everything: Collections, Taxonomies, Navigation trees, Globals, Asset meta.
- Smart pickers: Select the type; then pick specific handles (multi-select).
- Delta-friendly: Filter by sites and optional
since
(ISO8601) for narrow exports. - Git-style diff: Side-by-side preview of current vs incoming.
- Granular decisions: Choose per item to keep current or accept incoming.
- CLI included: Mirror UI flows via Artisan commands.
- Statamic v5 / Laravel 10–11 / PHP ≥ 8.1.
Roadmap: field-level merge decisions, queueable commits for large imports, binary asset copy helpers, rollback snapshots.
📦 Install
composer require "emran-alhaddad/statamic-content-sync:^0.1" php artisan vendor:publish --tag=content-sync-config php artisan statamic:stache:refresh && php artisan cache:clear
No frontend build required – compiled CP assets are included.
(If you’re developing the addon locally, run npm i && npm run build
.)
zsh tip: when installing dev branches, quote constraints (to avoid globbing):
composer require "emran-alhaddad/statamic-content-sync:dev-main"
⚙️ Configuration
Publish config → config/content-sync.php
:
return [ 'disk' => env('CONTENT_SYNC_DISK', 'local'), 'folder' => env('CONTENT_SYNC_FOLDER', 'sync'), 'chunk' => env('CONTENT_SYNC_CHUNK', 500), ];
Optional .env
:
CONTENT_SYNC_DISK=local
CONTENT_SYNC_FOLDER=sync
CONTENT_SYNC_CHUNK=500
🖥️ Control Panel Usage
Open Utilities → Content Sync.
Export
- Choose Type: Collections / Taxonomies / Navigation / Globals / Assets.
- Pick one or more handles from the list (multi-select).
- (Optional) Set Sites (comma-separated) and/or Since (ISO8601).
- Set an output filename (e.g.
my-export.json
) and click Export. - The JSON is written to
<disk>/<folder>/...
(e.g.storage/app/sync
).
Import
- Click Import tab and upload a previously exported JSON.
- Review the diff for each item (Current vs Incoming).
- For each item, choose Accept incoming or Keep current.
- Click Complete Import to apply decisions.
🧰 CLI (Optional)
Export:
php artisan content-sync:export \
--type=collections \
--handles=pages,news \
--sites=english,arabic \
--since="2025-01-01T00:00:00+03:00" \
--out=staging-delta.json
Import (preview only):
php artisan content-sync:import storage/app/sync/staging-delta.json
Import (apply all as “incoming”):
php artisan content-sync:import storage/app/sync/staging-delta.json --apply
📤 JSON Format (Export)
{ "exported_at": "2025-08-25T10:12:34+03:00", "type": "collections", "handles": ["pages", "news"], "sites": ["english"], "since": "2025-01-01T00:00:00+03:00", "items": [ { "uuid": "a0e42072-fddc-476e-8a92-ae2e2be4b902", "collection": "pages", "site": "english", "slug": "partnerships", "published": true, "updated_at": "2025-05-04T10:33:53+03:00", "data": { "...": "..." } } ] }
Other types (taxonomies
, navigation
, globals
, assets
) export their relevant fields (e.g., taxonomy terms, nav trees, global localizations, asset meta).
🔐 Permissions & Security
- All routes are under
web
withstatamic.cp.authenticated
. - If you need to restrict to super users or a specific role/permission, wrap the routes with your preferred middleware (or add a Gate).
🧪 Local Development
git clone git@github.com:emran-alhaddad/statamic-content-sync.git cd statamic-content-sync composer install npm i && npm run build vendor/bin/pint
Optionally, link into a Statamic app with a path repository for rapid iteration.
🐞 Troubleshooting
-
“Package not found”: Ensure the repo is on Packagist and a tag exists (e.g.
v0.1.0
). -
CP JS not loading: Confirm
resources/dist/js/content-sync.js
is committed and provider registers:Statamic::script('content-sync', __DIR__.'/../resources/dist/js/content-sync.js');
-
zsh eats
*
: Quote your Composer constraint ("vendor/pkg:*@dev"
) or usenoglob
.
🗺️ Roadmap
- Per-field merge decisions in the diff UI
- Queueable import & progress
- Binary asset copy helpers (between disks)
- Rollback & audit logs
- Tests + fixtures (Pest)
🤝 Contributing
PRs welcome! Please:
- Run
vendor/bin/pint --test
- Build assets via
npm run build
- Keep commits scoped & conventional (e.g.,
feat:
,fix:
,chore:
)
📜 License
MIT © Emran Alhaddad