-
Notifications
You must be signed in to change notification settings - Fork 0
Standalone Mode
Razy's Standalone Mode is the simplest way to build an application — a single-module, zero-config setup that requires no package manager, no distributor configuration, and no domain restrictions.
-
Default mode: Standalone activates automatically when a
standalone/folder exists and multisite is not enabled -
Ultra-flat structure: No
module.php, nopackage.php, no version directories — just controllers and views - Full framework access: DI container, template engine, routing, and all Razy utilities are available
- Any domain: No domain restrictions — any incoming connection loads the standalone module
php Razy.phar standaloneThis creates:
standalone/
controller/
app.php # Main controller (route registration)
app.index.php # Index route handler (/)
view/
index.tpl # Index page template
Create the standalone/ directory at your project root with at minimum:
standalone/
controller/
app.php # Main controller
my-project/
index.php # Entry point (or router.php)
config.inc.php # Framework config (timezone, debug, phar_location)
Razy.phar # Framework archive
standalone/ # Your application lives here
controller/
app.php # Main controller class
app.index.php # Handler for '/' route
app.about.php # Handler for 'about' route
app.api.php # Handler for 'api' route
view/
index.tpl # Templates
about.tpl
library/ # Optional: custom classes (autoloaded)
In main.php, before the normal multisite host-matching flow:
- Check if
standalone/directory exists atSYSTEM_ROOT - Check if
config.inc.phpdoes NOT have'multiple_site' => true - Check if
RAZY_MULTIPLE_SITEenvironment variable is NOT'true' - If all conditions are met → standalone mode activates
STANDALONE_MODE = is_dir('standalone/') && !$razyConfig['multiple_site'] && getenv('RAZY_MULTIPLE_SITE') !== 'true'
index.php → Razy.phar → main.php → bootstrap.inc.php
↓
Standalone detection (standalone/ exists, multisite not enabled)
↓
Application::standalone($standalonePath)
→ Creates Standalone instance (no dist.php, no Domain)
→ DI Container injected from Application
↓
Application::queryStandalone(URL_QUERY)
→ Standalone::initialize() creates one Module directly
→ Module loads controller/app.php
→ Standalone::matchRoute() dispatches to matched handler
| Normal Mode | Standalone Mode |
|---|---|
sites.inc.php required |
Not needed (but can coexist) |
Domain matching (host()) |
Skipped — any domain works |
dist.php in sites/
|
Not needed |
module.php per module |
Not needed — synthesized internally |
package.php per version |
Not needed |
vendor/package/ nesting |
Flat — standalone/controller/app.php
|
Version directories (default/) |
None — code lives at standalone/ root |
The main controller at standalone/controller/app.php is identical to any Razy controller:
<?php
use Razy\Agent;
use Razy\Controller;
return new class extends Controller {
public function __onInit(Agent $agent): bool
{
$agent->addLazyRoute([
'/' => 'index',
'about' => 'about',
'api/users' => 'api/users',
]);
return true;
}
};Route handlers follow the standard naming convention: app.{route}.php
<?php
// standalone/controller/app.index.php
use Razy\Controller;
return function (): void {
/** @var Controller $this */
header('Content-Type: text/html; charset=UTF-8');
$template = $this->loadTemplate('index');
echo $template->output();
};Templates in standalone/view/ use the standard Razy template engine:
{# standalone/view/index.tpl #}
<!DOCTYPE html>
<html>
<head><title>{$title}</title></head>
<body>
<h1>{$heading}</h1>
<!-- BEGIN: content -->
<p>{$text}</p>
<!-- END: content -->
</body>
</html>The standalone module has access to the Application-level DI container. Inject services in your controller:
return new class extends Controller {
public function __onInit(Agent $agent): bool
{
// Access the DI container
$container = $this->module->getContainer();
// Resolve services
$pluginManager = $container->make(\Razy\PluginManager::class);
$agent->addLazyRoute(['/' => 'index']);
return true;
}
};To convert a standalone app to multisite:
- Set
'multiple_site' => trueinconfig.inc.php - Create
sites.inc.phpat the project root (usephp Razy.phar set) - Move your standalone code into a proper module under
sites/<dist>/ - Standalone mode deactivates because multisite is enabled
Both can coexist during development — toggle between modes by changing the multiple_site config value.
# Scaffold a new standalone app
php Razy.phar standalone
# Scaffold with force-overwrite
php Razy.phar standalone --force
# Scaffold into a specific directory
php Razy.phar standalone -f /var/www/myapp- Single module only: Standalone mode loads exactly one module
-
No inter-module API: No
$this->api()calls (only one module exists) -
No package prerequisites: No
composeor dependency resolution -
No shared modules: Global modules from
shared/module/are not scanned - No data mapping: Cross-site data mapping is not available
For multi-module applications or cross-module communication, use the standard multisite mode with sites.inc.php.