spora-ai/installer

Routes `spora-plugin` packages to `plugins/{$name}/`, `spora-frontend` packages to `public/spora/`, and `spora-plugin-frontend` packages to `public/plugins/{$slug}/` when installed via Composer. Companion to spora-ai/spora-core.

Maintainers

Package info

github.com/spora-ai/spora-installer

Type:composer-plugin

pkg:composer/spora-ai/installer

Transparency log

Statistics

Installs: 3 441

Dependents: 2

Suggesters: 0

Stars: 0

Open Issues: 0

v1.5.0 2026-07-15 10:06 UTC

This package is auto-updated.

Last update: 2026-07-15 12:02:10 UTC


README

Composer plugin for Spora. Routes three Composer package types:

  • spora-pluginplugins/{$name}/
  • spora-frontendpublic/spora/
  • spora-plugin-frontendpublic/plugins/{$slug}/

…instead of Composer's default vendor/ install location.

You don't install this directly — it ships as a transitive dependency of spora-ai/spora-core. The Spora host application activates it automatically the first time Composer runs in a project that depends on spora-ai/spora-core.

Usage

composer require spora-ai/spora-core
# Any package with type "spora-plugin" now installs to plugins/<name>/
# instead of vendor/<vendor>/<name>/.

This is the package-type router that powers Spora's plugin system.

Frontend bundles (spora-plugin-frontend)

A second installer routes spora-plugin-frontend packages into public/plugins/<slug>/ (the directory the host SPA lazy-loads /plugins/<slug>/main.js from at runtime). The destination <slug> is not derived from the package short name — that previously produced a runtime 404 when the parent PHP plugin's plugin.json#slug (e.g. foo) differed from the frontend package's short name (e.g. spora-plugin-foo-frontend).

The frontend package declares the slug explicitly in composer.json:

{
  "name": "spora-ai/spora-plugin-foo-frontend",
  "type": "spora-plugin-frontend",
  "extra": {
    "spora-plugin-slug": "foo"
  }
}

Rules:

  • extra.spora-plugin-slug MUST equal the parent PHP plugin's plugin.json#slug.
  • The installer fails loud (InvalidArgumentException) when the field is missing, empty, or not a string. There is no fallback to the package short name.
  • Slugs must match ^[a-z0-9]+(?:-[a-z0-9]+)*$ after trimming — /, \, .., whitespace, uppercase, and underscores are rejected as path-traversal protection under the public web root.

See docs/spora-plugin-frontend.md for the full contract, error messages, and the Spora docs → Declaring the install destination slug for the operator-facing guide.

License

MIT.