# Static Generator To generate the static content of the website, lucent provides a helper class. ## Laravel Command Create an Artisan command and inject `StaticGenerator`: ```php class GenerateStatic extends Command { protected $signature = 'generate:static'; public function __construct( public StaticGenerator $staticGenerator, public Context $ctx, ) { parent::__construct(); } public function handle(): void { $this->staticGenerator->run('generate:static', function ($writer) { $writer->save("/", $this->ctx->render("homepage")); $writer->save("/about", $this->ctx->render("about")); }); } } ``` `run(string $signature, callable $callback)` — the first argument must match the command's artisan signature. This is used to stream live build logs in the Lucent UI. The callback receives a `Writer` instance. ## Writer: save Writes an HTML file at the given path: ```php $writer->save("/blog/my-post", $html); // writes to: storage/lucent/build/blog/my-post/index.html ``` An optional third argument changes the file extension (default `"html"`). ## Writer: createRedirect Generates an HTML meta-refresh redirect. Useful for root-level locale redirects: ```php $writer->createRedirect("/", "/el"); $writer->createRedirect("/", "/el", "Redirecting", "Please wait..."); ``` Arguments: `from`, `to`, `title` (default `"Redirecting"`), `message` (default `"Redirecting Soon..."`). ## Writer: recordIterator Iterates over all records in paginated batches — useful when there are too many records to load at once: ```php $writer->recordIterator( query: fn(int $limit, int $skip) => $query ->filter(["schema" => "blogPosts"]) ->onlyPublished() ->limit($limit) ->skip($skip) ->tree(), parser: function ($records) use ($writer) { foreach ($records as $record) { $writer->save( "/blog/" . $record->data->slug, $this->ctx->render("blogPost", $record), ); } }, ); ``` Signature: `recordIterator(callable $query, callable $parser, int $skip = 0, int $limit = 100): int` The `$query` callable receives `($limit, $skip)` and must return a collection. Iteration stops automatically when a batch returns zero records. ## Storage and Permissions All generated HTML is written to `storage/lucent/build` during the run, then atomically swapped to `storage/lucent/live` on completion. Create the public symlink with: ```bash php artisan lucent:livelink ``` The static site is then accessible at `http://localhost:8000/live`. To serve it without the `/live` prefix, add this to your nginx vhost: ```nginxconf location / { try_files /live$uri/index.html /live$uri $uri $uri/ /index.php?$query_string; } ``` ## Artisan Commands | Command | Description | |---|---| | `lucent:setup-db` | Create all Lucent database tables | | `lucent:schemas` | Compile schema JSON files | | `lucent:livelink` | Create the `public/live` symlink | | `lucent:rebuild:thumbnails` | Regenerate thumbnails for all uploaded images | | `lucent:removeOrphanEdges` | Remove edges pointing to deleted records | | `lucent:generate:collection {name}` | Scaffold a new collection schema JSON file | ## Build from the Lucent UI Register your generate command in `config/lucent.php` so admin users can trigger it from the UI: ```php "commands" => [ "generate:static" => "Generate Static Site", ], ``` Only roles listed in `canBuild` can trigger commands from the UI.