Files
lucent-laravel/docs/Website Setup.md
2026-05-06 23:42:32 +03:00

6.8 KiB
Raw Permalink Blame History

Website Setup

This is an opinionated website setup. It's irrelevant to both Lucent and Laravel. It is just the way I like to organize everything.

Summary

  • Create a Lucent folder with Schemas, Image Filters and Pages
  • Pages are similar to controllers, but will also get used to statically generate the website
  • A Context singleton class that acts as a container for global state
  • A middleware to initiate the Context class and set the application state for the request
  • Some helper functions to make our life easier

Context Class

<?php namespace App\Lucent;

class Context
{
    public string $website = "";
    public string $title;
    public string $description = "";
    public string $url = "";
    public string $mode = "static";
    public string $locale = "el";
    public array $data = [];
    public array $locales = ["el","en"];

    protected array $pages = [
        "homepage" => Homepage::class,
    ];
    
    public function __construct(
        public Application $app,
        public Query $query
        ){}

    public function render(string $pageName, ...$args): string
    {
        $page = $this->app->make($this->pages[$pageName]);
        return $page->render(...$args);
    }

    public function getTitle()
    {
    return empty($this->title) ?  $this->website : $this->title . " | " . $this->website;
    }

    public function getFullUrl(string $path = "")
    {
        return config("app.url") . $this->generateLocaleUrl($path, $this->locale);
    }

    public function localeUrl(string $path = ""): string
    {
        return $this->generateLocaleUrl($path, $this->locale);
    }

    public function switchLocale(string $locale, $path = ""): string
    {
        return $this->generateLocaleUrl($path, $locale);
    }

    private function generateLocaleUrl(string $path, string $locale): string
    {
        if ($this->mode ==  "preview") {
            return config("app.url") . "/preview/" . $locale . "/" . trim($path, "/");
        }
        return config("app.url") . "/" . $locale . "/" . trim($path, "/");
    }
}

Add this class to AppServiceProvider as a singleton

 $this->app->singleton(Context::class);

Context Middleware

<?php namespace App\Http\Middleware;

class Context
{
    public function __construct(public Context $context){}

    public function handle(Request $request, Closure $next, string $mode = "static"): Response
    {
        $this->context->locale = $request->route("locale");
        App::setLocale($this->meta->locale);
        $this->context->mode = $mode;
        $this->context->loadData();
        return $next($request);
    }
}

Add the middleware inside the HTTP Kernel file.

Configuration

After publishing the config (php artisan vendor:publish --tag=lucent-config), configure config/lucent.php via .env:

Key Env var Default Description
env LUCENT_ENV production production or development
auth LUCENT_AUTH lucent Auth driver: lucent or lunar
disk LUCENT_DISK public Laravel filesystem disk for uploads
schemas_path LUCENT_SCHEMAS_PATH resources/lucent/schemas Where schema JSON files live
database LUCENT_DB_CONNECTION DB_CONNECTION Database connection name
name LUCENT_NAME Lucent CMS display name
url LUCENT_URL APP_URL Base URL of the CMS
previewTarget LUCENT_PREVIEW_TARGET previewTarget Preview route parameter
commands [] Artisan commands exposed to admin users (see Static Generator)
imageFilters [] Image filter presets applied to uploads (see below)
canInvite ["admin"] Roles that can invite new users
canBuild ["admin"] Roles that can trigger static builds
systemUserId "" User ID used for console-initiated record writes

Image Filters

Image filters are Intervention Image filter classes applied to every uploaded image, producing additional versions (e.g. a cropped or watermarked variant). Each preset is stored at templates/{name}/{original-path} on the configured disk.

Define filters in config/lucent.php:

"imageFilters" => [
    "hero" => \App\ImageFilters\HeroFilter::class,
    "thumb" => \App\ImageFilters\ThumbFilter::class,
],

A filter class must implement Intervention\Image\Filters\FilterInterface:

namespace App\ImageFilters;

use Intervention\Image\Filters\FilterInterface;
use Intervention\Image\Image;

class HeroFilter implements FilterInterface
{
    public function applyFilter(Image $image): Image
    {
        return $image->fit(1200, 600)->encode('webp', 80);
    }
}

Every uploaded image automatically gets a 300×300 WebP thumbnail at thumbs/{path} in addition to any configured presets.

Authentication

Lucent uses email-link (magic link) login — no passwords. Users receive a time-limited link by email.

Auth modes

Set LUCENT_AUTH to choose how users are stored:

Value Description
lucent Users stored in the lucent_users table. Supports roles.
lunar Delegates to Lunar's lunar_staff table. Roles not supported.

Login flow

  1. User submits their email at /lucent/login
  2. A 32-character token is stored against the user with a timestamp
  3. Lucent emails a login link containing the token
  4. User clicks the link → token is validated (must be used within 1 hour)
  5. Session is established; token is cleared

First-time setup

The /lucent/register route is only available when no users exist in the system. Once the first admin registers, the route returns a redirect to /lucent/login. Registration automatically assigns the admin role and sends a login link.

Middleware

Two middleware aliases are available for your routes:

Alias Description
lucent.auth Requires an active Lucent session
lucent.guest Redirects authenticated users away

Roles

Roles are defined in your channel config. Only roles listed there are valid — anything else is silently stripped on assignment. The canInvite and canBuild config keys control which roles can invite users and trigger builds respectively.

On console commands and non-/lucent routes, currentUserId() returns config("lucent.systemUserId") instead of the session user.

Database Tables

All Lucent-managed tables use the lucent_ prefix:

Table Description
lucent_records All collection and file schema records
lucent_files Uploaded file metadata
lucent_edges Relationships between records
lucent_revisions Record revision history
lucent_users Users (when using lucent auth mode)
lucent_command_logs Background command execution logs

These are created automatically by running php artisan lucent:setup.