Projects
About 373 wordsAbout 1 min
A Spora project is a single Spora deployment customised with project-local code. The skeleton already gives you a working install; spora-maker is the scaffolder for adding the project-local pieces — a new Tool, a new HTTP controller, or a regenerated app/App.php entry class.
spora-maker is installed in the skeleton as a require-dev Composer dependency. It exposes a small set of make:* commands on the existing bin/spora console — no separate binary to learn, no new install step.
spora/
├── app/
│ ├── App.php ← regenerated by `make:app`
│ ├── Tools/ ← populated by `make:tool`
│ │ └── WebSearchTool.php
│ └── Http/
│ └── Controllers/ ← populated by `make:controller`
│ └── MyApiController.php
└── vendor/spora-ai/spora-maker/ ← the scaffolder (require-dev)Scaffolding commands
All three scaffolder commands share the same bin/spora binary you already use. They take a positional class name, refuse to overwrite existing files, and print next-step hints on success.
- Scaffolding → make:tool, make:controller, make:app — the full command reference with examples and the generated-code templates
When to use a project vs a plugin
| Need | Use |
|---|---|
| One tool, this project only | app/Tools/Foo.php (scaffolded with make:tool) |
| Multiple project-local contributions + routes + DI | app/App.php (scaffolded with make:app) + several make:tool / make:controller |
| Distribute to other Spora installs | A plugin(Open in new window), not a project — promote app/ into a Composer package, rename App.php → Plugin.php, add plugin.json |
The promotion path is mechanical, not a rewrite — see the Customization guide for the full flow.
Project-local vs Core concepts
The project-local flow is documented here. The deeper architecture (the hook surface, lifecycle ordering, AppLoader) lives in:
- Concepts → App extensions — the full
SporaExtensionInterfacehook surface,AbstractExtensionbase class, and howapp/App.phpis discovered and wired - Concepts → Tool system — the
#[Tool],#[ToolOperation],#[ToolParameter],#[ToolSetting]attribute surface thatmake:toolscaffolds against - Concepts → PHP interfaces — the contracts each generated class implements
The scaffolder emits code that is trivially correct but incomplete — it leaves // TODO: implement. placeholders everywhere the developer needs to fill in real logic. The intent is to remove the boilerplate (namespace, use statements, class declaration, base class extension) and let the developer focus on the tool’s behaviour.