Studio | ravencraft.dk

📘 Studio Brandbook & Arkitekturmanual v3.2 Spec Living Styleguide
📦 Modulguide 🎨 UI Kontroller ← Studio Forside

Studio Brandbook & Udviklerguide

Single Source of Truth for arkitektur, moduler og UI-komponenter i Ravencraft Studio

Formålet med dette Brandbook er at sikre en ensartet, robust og skalerbar platform. Før vi genopfinder hjul eller bygger moduler fra bunden, skal arkitekturen, komponenterne og bibliotekerne herunder følges. Alle kontroller er direkte forankret i assets/css/studio_ui.css og drives af dynamiske CSS Custom Properties.

🌈 Live Tema-simulator

Studio understøtter 14 centrale farvetemaer samt dynamiske organisationstemaer. Klik på et tema nedenfor for at se hvordan alle kontroller på hele siden tilpasser sig i realtid uden hardcodede styles.

Afprøv tema:

🎯 3-Tier Farvetema-hierarki & Organisationsbranding

Studio anvender en standardiseret 3-trins prioritering for udvælgelse af tema og farvepalet, som sikrer både individuel valgfrihed, konsistent organisationsbranding og globale standarder:

1 Prioritet 1: Brugerens eget valg af tema

Hvis en bruger aktivt har valgt et personligt tema i sine profilindstillinger ($_SESSION['user_theme'] !== 'system'), har dette absolut førsteprioritet og overstyrer både organisationens tema og globale systemindstillinger.

2 Prioritet 2: Organisationens valg af tema (eller special-defineret organisationstema)

Hvis brugerens eget tema er sat til system (eller intet er valgt), og brugeren er tilknyttet en organisation i qr_org.db, nedarver brugeren automatisk organisationens tema ($_SESSION['user_org']). Organisationer kan enten vælge et af Studios 14 standardtemaer som udgangspunkt eller skræddersy alle 6 nøglefarver (primær, accent, mørk, baggrund, kant og kort) samt fulde CSS-baggrundsgradienter for 100% white-labeling.

3 Prioritet 3: Det globale tema i Studio

Hvis hverken brugeren eller brugerens organisation har specificeret et tema, anvendes det globale standardtema konfigureret i systemindstillingerne ($sys_settings['theme_mode'] ?? 'light').

ℹ️ Lokale modul-overstyringer: Specifikke moduler eller præsentationssider (f.eks. en fuldskærms-lobby eller et quiz-view) kan definere $page_theme_mode = '...' før inkludering af head.php. Dette overstyrer temaet lokalt og isoleret for netop det specifikke view uden at ændre brugerens eller organisationens faste præferencer.

🏛️ Studio Arkitektur-mandat

De ufravigelige principper for al udvikling i Ravencraft Studio:

1 Nul hardcodet styling (Zero Hardcoded CSS)

Ingen knapper, kort, headers eller tekst må anvende faste hex-farver som #0070f3 eller #1e293b i CSS eller inline-styles. Benyt altid CSS variabler (fx var(--primary), var(--card-bg), var(--dark), var(--border), var(--bg)). Dette muliggør problemfri temaskift og automatisk organisations-white-labeling.

2 Modulær isolation (No Cross-Module Dependency)

Krydsafhængighed mellem moduler er strengt forbudt (f.eks. må modules/poll aldrig inkludere filer fra modules/qr). Al fælles forretningslogik, sessionshåndtering, adgangskontrol, billedbehandling og globale hjælpefunktioner skal placeres i studio_ravencraft_dk_private/includes/.

3 Selvhelende databaser (Self-Healing SQLite)

Hvert modul har sin egen isolerede SQLite-database i studio_ravencraft_dk_private/databases/ via hjælpefunktionen get_db_path('modulnavn.db'). Databasen skal oprette sine egne tabeller via CREATE TABLE IF NOT EXISTS ved første kørsel og udføre automatiske schema-migrationer, hvis en kolonne mangler.

4 Central Identitet & Tilladelser

Alle moduler skal verificere brugerens tilladelse ved start via require_module_access('modul_noegle'). Dette sikrer automatisk håndtering af 14-dages tidsbegrænsede demo-adgange og permanent adgangskontrol.

5 Dynamisk Miljø & .htaccess Backend-switching

Undgå at hardcode relative stier som ../../studio_ravencraft_dk_private/ i koden. Studio definerer i stedet den private backend-mappe som en miljøvariabel i .htaccess:

Apache .htaccess
SetEnv STUDIO_PRIVATE_DIR "studio_ravencraft_dk_private"

I roden af Studio findes bootstrap.php, som automatisk udlæser denne variabel og definerer STUDIO_PRIVATE_PATH samt hjælpefunktionen studio_private_path($subpath).

Hurtig staging/produktions-flytning: Når en ny udgave af Studio (fx studiov3) skal idriftsættes, kan den udrulles direkte til produktion blot ved at skifte værdien i .htaccess til den nye mappe (eller omvendt), uden at en eneste PHP-fil i systemet behøver ændres!

🚀 Studio v3: Subdomæne- & Kerne-Arkitektur

Studio v3 markerer overgangen til en fuldt distribueret subdomæne-arkitektur med isolerede moduldatabaser, delt privat kerne (Løsning A), central identitetsstyring og streng overholdelse af Brandbooket.

1 Subdomæner & Modul-isolation

I Studio v3 bor alle moduler på deres egne selvstændige subdomæner til ravencraft.dk:

  • Hovedportal & Identity Provider: studio.ravencraft.dk (udvikles i studiov3.ravencraft.dk).
  • Modul Web-roots: F.eks. flow.ravencraft.dk, buzz.ravencraft.dk, poll.ravencraft.dk.
  • Private Modul-mapper: Hvert modul har sin egen isolerede private mappe (fx flow_ravencraft_dk_private/) til sine egne SQLite-databaser og modullogik.
2 Løsning A: Delt privat kerne (Server-side HTML)

For at undgå klodset, skrøbelig JavaScript-genereret HTML til topbaren og head-injektion, anvender Studio v3 Løsning A: En delt privat kerne i studiov3_ravencraft_dk_private/ (eller studio_ravencraft_dk_private/ i produktion).

Alle subdomæner inkluderer head.php, header.php og header-user.php direkte herfra. Dette sikrer lynhurtig server-side rendering, ensartet design på tværs af platformen og fuld SEO/performance uden DOM-flicker.

3 Single Active Session (Concurrent Session Control)

En bruger må kun have 1 aktiv session ad gangen. Ved login genereres et unikt current_session_token, som gemmes i databasen og i brugerens session.

Princippet "Ny session vinder": Hvis brugeren logger ind fra en ny enhed eller browser, overskrives tokenet i databasen. Næste gang den ældre session laver en forespørgsel, termineres den automatisk (session_destroy()), og brugeren omdirigeres til login. Samme terminering sker øjeblikkeligt ved ændring af adgangskode.

4 Identity Claims i Session (0 API-kald)

For at undgå 3-4 API-kald eller databaseopslag pr. sidevisning på subdomænerne, caches alle profil- og organisationsdata direkte i $_SESSION ved login på Studio:

  • $_SESSION['user_name'] & $_SESSION['user_avatar'] (fuld CDN URL: https://lib.ravencraft.dk/uploads/avatars/...)
  • $_SESSION['user_org'] (indeholder org_name, logo_url som https://lib.ravencraft.dk/uploads/orgs/... samt brandfarver)
  • $_SESSION['allowed_features'] (aktive moduler og tilladelser)

Fordi sessionen deles via cookie-domænet .ravencraft.dk, har flow.ravencraft.dk, buzz.ravencraft.dk m.fl. øjeblikkelig adgang til alle claims uden et eneste eksternt kald. Ved profilopdatering overskrives claims i sessionen i realtid.

5 Centralt CDN & CORS-konfiguration (lib.ravencraft.dk)

Subdomæner og moduler henter delte stylesheets (studio_ui.css), webfonts, JavaScript-værktøjer samt brand- og uploadede aktiver (logoer, avatarer) direkte fra det centrale CDN https://lib.ravencraft.dk. Dette styres via miljøvariablen STUDIO_CDN_URL i subdomænets .htaccess:

Apache .htaccess på subdomænet
SetEnv STUDIO_CDN_URL "https://lib.ravencraft.dk"

lib_ravencraft_dk udsender Access-Control-Allow-Origin: * og 1-års browser-caching på alle statiske aktiver, så moduler deler cachen og aldrig oplever cross-origin eller 404-fejl.

⚠️ Brandbook Forhåndsgodkendelse (Ufravigeligt Mandat)

Under al udvikling af Studio v3 skal Brandbooket løbende kontrolleres og bekræftes. Der må under ingen omstændigheder indføres nye kontroller, knaptyper, kort-varianter eller formularelementer i Studio v3 uden forudgående godkendelse.

Nye elementer skal altid først godkendes, dokumenteres i Brandbooket og tilføjes til studio_ui.css, før de tages i anvendelse i noget modul.

7 Studio Landingsside: 4-Kolonne Modul-grid (Kun Landingsside)

For at fastholde det overskuelige moduloverblik fra Studio v1 og v2, benytter Studio v3's centrale forside (index.php) et fast 4-kolonne responsivt gitter (.studio-module-grid) til visning af installerede moduler.

⚠️ Ufravigelig Arkitektur-regel:

Klassen .studio-module-grid og dens 4-kolonne layout er udelukkende gældende for Studio portalens landingsside. Den må ikke anvendes som generelt layout inde i de enkelte moduler, dashboards eller undersider. Interne sider og moduler skal altid anvende det fleksible standard-kortgitter .studio-card-grid (som automatisk flyder ud med repeat(auto-fill, minmax(280px, 1fr))).

  • Kun subdomæner: Landingssidens grid viser udelukkende moduler med gyldige subdomæne-adresser (f.eks. https://flow.ravencraft.dk).
  • Ingen overflødige badges: Modulkortene må ikke vise tags som "Kerne" eller "Subdomæne", da samtlige moduler i Studio v3 følger subdomæne-arkitekturen.

📦 Guide: Sådan implementeres et modul i Studio

Trin-for-trin opskrift til at oprette og fuldt integrere et nyt modul.

1 Mappestruktur for modulet

Opret en dedikeret undermappe i modules/ navngivet med små bogstaver og bindestreger/underscores:

modules/mitmodul/ ├── module.json # Påkrævet: Modul-metadata, status og tilladelsesnoder ├── index.php # Påkrævet: Hovedindgang (katalog / brugerflade) ├── mitmodul.css # Valgfrit: Modulspecifikke styles (skal respektere CSS-variabler) ├── db.php # Valgfrit: Database-initialisering og hjælpefunktioner ├── api.php # Valgfrit: JSON API endpoints for AJAX / realtime └── subpages/ # Valgfrit: Eventuelle underordnede visninger
2 Modulspecifikation (module.json)

Hvert modul skal indeholde en gyldig module.json fil:

JSON - modules/mitmodul/module.json
{
    "name": "Studio MitModul",
    "purpose": "Klar og præcis beskrivelse af modulets didaktiske formål på dansk.",
    "status": "development",
    "permission_nodes": [
        "mitmodul"
    ],
    "settings_file": "mitmodul_settings_schema.json",
    "last_change": "2026-10-16 11:19:54",
    "changed_by": "Udvikler Navn"
}
Status-værdier: development (under udvikling), active (fuldt tilgængelig), production (stabil produktion), maintenance (lukket pga. vedligeholdelse).
3 Registrering i features.json

Tilføj tilladelsesnoden og modulets landing-card i studio_ravencraft_dk_private/includes/features.json:

JSON Snippet til features.json
// 1. Under "permissions":
{
    "key": "mitmodul",
    "label": "🚀 Studio MitModul",
    "default_checked": true
}

// 2. Under "landing_cards" (Alle moduler i Studio v3 er subdomæner):
{
    "id": "mitmodul",
    "title": "Studio MitModul",
    "description": "Beskrivelse vist på forsiden i 4-kolonne modul-oversigten.",
    "url": "https://mitmodul.ravencraft.dk",
    "required_features": ["mitmodul"],
    "check_operator": "AND",
    "show_to_guests": true,
    "admin_only": false,
    "style": "",
    "class": "",
    "enabled": true,
    "maintenance": false
}
4 Pæne URL-adresser via .htaccess

Tilføj rewrite-regler i rodens .htaccess, så brugerne kan tilgå studio.ravencraft.dk/mitmodul direkte:

Apache .htaccess snippet
# Rewrite /mitmodul to modules/mitmodul/index.php
RewriteRule ^mitmodul/mitmodul\.css$ modules/mitmodul/mitmodul.css [L]
RewriteRule ^mitmodul/?$ modules/mitmodul/index.php [L,QSA]
RewriteRule ^mitmodul/([a-zA-Z0-9_-]+\.php)$ modules/mitmodul/$1 [L,QSA]
RewriteRule ^mitmodul/([a-zA-Z0-9_-]+)$ modules/mitmodul/$1.php [L,QSA]
5 Adgangskontrol & 14-Dages Demo (require_module_access)

I toppen af modulets index.php og alle handlinger kaldes require_module_access('modul_noegle'). Dette sikrer:

  • Uloggede brugere omdirigeres automatisk til /login.php?redirect=....
  • Administratorer godkendes automatisk.
  • Brugere med aktiv tilladelse eller en aktiv 14-dages prøveperiode i studio_access.db godkendes automatisk.
  • Brugere uden adgang eller med udløbet prøveperiode omdirigeres venligt tilbage til forsiden med en advarselsbesked.
PHP Adgangs-sikring
// Inkluder central bootstrap (indlæser .htaccess miljøvariabel, microservices og session)
require_once __DIR__ . '/../../bootstrap.php';

// Beskyt modulet:
require_module_access('mitmodul');
6 SQLite Databaser (Self-healing & Isoleret)

Brug altid get_db_path('mitmodul.db') til at hente stien til databasen. Eksempel på en robust initialiseringsfunktion:

PHP - Selvhæftende Database Initialisering
function getMitModulDB(): PDO {
    static $db = null;
    if ($db === null) {
        $dbPath = get_db_path('studio_mitmodul.db');
        $db = new PDO("sqlite:" . $dbPath);
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $db->exec("PRAGMA busy_timeout = 5000;");

        // Selvhæftende tabeller:
        $db->exec("CREATE TABLE IF NOT EXISTS mitmodul_items (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER NOT NULL,
            title TEXT NOT NULL,
            description TEXT,
            status TEXT DEFAULT 'active',
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )");
        $db->exec("CREATE INDEX IF NOT EXISTS idx_mitmodul_user ON mitmodul_items(user_id);");
    }
    return $db;
}
7 Komplet Modul Boilerplate (index.php)

Kopiér denne skabelon direkte ind som modules/mitmodul/index.php for at komme i gang på 30 sekunder:

PHP / HTML5 Boilerplate - modules/mitmodul/index.php
<?php
// modules/mitmodul/index.php
session_start();

// 1. Central bootstrap (indlæser automatisk micro-services og php-user-session via .htaccess)
require_once __DIR__ . '/../../bootstrap.php';

// 2. Håndhæv moduladgang
require_module_access('mitmodul');

$user_id = $_SESSION['user_id'] ?? 0;
?>
<!DOCTYPE html>
<html lang="da">
<head>
    <?php require_once studio_private_path('includes/head.php'); ?>
    <link rel="stylesheet" href="/mitmodul/mitmodul.css?v=1.0">
    <title>Studio MitModul - Didaktisk Værktøj</title>
</head>
<body>

    <header>
        <?php require_once studio_private_path('includes/header.php'); ?>
    </header>

    <!-- Modul Sub-Header -->
    <div class="studio-sub-header">
        <div class="studio-sub-header-nav">
            <span style="font-weight: 700; color: var(--studio-dark);">🚀 Studio MitModul</span>
            <div class="studio-tabs">
                <a href="index.php" class="studio-tab active">Oversigt</a>
                <a href="create.php" class="studio-tab">Opret Ny</a>
            </div>
        </div>
        <div class="studio-sub-header-actions">
            <a href="/" class="studio-btn studio-btn-sm studio-btn-secondary">← Tilbage til Studio</a>
        </div>
    </div>

    <!-- Hovedindhold -->
    <div class="container" style="max-width: 1200px; margin: 30px auto; padding: 0 20px;">
        <div class="studio-card">
            <div class="studio-card-header">
                <h3 class="studio-card-title">Velkommen til MitModul</h3>
                <span class="studio-badge studio-badge-primary">Aktiv</span>
            </div>
            <div class="studio-card-body">
                <p>Dit modul er fuldt integreret med Studio identitet, temaer og adgangskontrol.</p>
            </div>
            <div class="studio-card-footer">
                <button type="button" class="studio-btn studio-btn-secondary">Sekundær Handling</button>
                <button type="button" class="studio-btn studio-btn-primary">Gem & Fortsæt ➜</button>
            </div>
        </div>
    </div>

</body>
</html>

🔗 Distributions-infrastruktur: rci.dk Korte URLs & Gateway

rci.dk (Ravencraft Ingenuity) fungerer som platformens ultra-korte edge-router, scannings-gateway og omdirigeringstjeneste. Den er uundværlig for al mobil interaktion, QR-koder og storskærms-deltagelse.

★ Hvorfor rci.dk er uundværlig for Studio

1. Ultra-lav QR-densitet

Jo kortere URL en QR-kode indeholder (fx rci.dk/p/1234 frem for lange deep-links), desto færre prikker/moduler skal koden have. Dette gør koden ekstremt robust og lynhurtig at scanne fra lang afstand på storskærme, på messestande og på trykte materialer.

2. Hurtig manuel indtastning

Hvis en deltagers mobilkamera har problemer, eller hvis deltageren sidder for langt væk fra storskærmen, kan kortere links som rci.dk/buzz/4812 eller rci.dk/s/15 tastes manuelt i browseren på under 5 sekunder.

3. Lynhurtig Edge-Performance

rci.dk er bygget som en ultra-letvægts router. Den indlæser ikke hele Studio-portalen, men logger scanningen direkte i SQLite med GDPR-anonymiseret IP og viderestiller brugeren (301/302) på under 10 millisekunder.

📋 Nuværende Ruter & Præfiks-katalog i rci.dk

rci.dk/index.php
URL-mønster Tilhørende Modul Handling & Omdirigering
rci.dk/buzz/{kode} Studio Buzz Sender direkte til mobilspiller-klienten: studio.ravencraft.dk/buzz/buzz-client?gameid={kode}
rci.dk/p/{kode} el. rci.dk/{kode} Studio Poll Registrerer stemmen i studio_poll.db, logger scanningen og viser letvægts "Tak for din stemme"-kort med kommentarformular.
rci.dk/d/{kode} el. rci.dk/r/{kode} Studio QR Dynamisk QR: Logger scanningsmetrik (GDPR-anonymiseret IP), håndterer vCard-download eller viderestiller til destinationen.
rci.dk/t/{id} Studio Tags Sender direkte til mobil live-ordsky input: studio.ravencraft.dk/t.php?id={id}
rci.dk/s/{id} Studio Survey Afvikler mobil-respondenten direkte på rci.dk/s/{id} (historiske studio.ravencraft.dk/s.php?id={id} laver 301-redirect hertil).
rci.dk/f/{uuid} el. rci.dk/flow/{uuid} Studio Flow Sender til mobilafvikling af proces- og beslutningstræet: flow.ravencraft.dk/run?uuid={uuid}
rci.dk/ (tom sti) Studio Hovedportal Omdirigerer direkte til https://studio.ravencraft.dk
🚀 Fremtidssikret Gateway & Udvidelsesmuligheder

rci.dk er ikke blot begrænset til omdirigeringer. Domænet og dets arkitektur er designet som en udvidelsesparat gateway, der kan rumme en bred vifte af fremtidige funktioner:

  • Generisk URL-forkorter & Kampagne-tracking: Tabellen short_urls er allerede forberedt i studio_dynamic_qr.db, så vilkårlige marketing-links, kampagner og vanity-koder kan administreres centralt.
  • Mobile Letvægts Mini-Apps: Ligesom afstemnings-kommentarer kører direkte i rci.dk/index.php uden at trække hele Studio-skallen med, kan nye hurtige mikro-interfaces (fx lottotrækninger, hurtig feedback, ja/nej-knapper eller touch-kiosker) afvikles direkte på rci.dk for maksimal fart.
  • Hurtig Event- & Stand-Check-in: Scanning af deltager-QR-koder eller adgangskort ved arrangementer og messer uden logintung backend.
  • IoT, NFC & Webhook endpoints: Modtagelse af data eller triggere fra fysiske NFC-tags eller hardware-scannere.

Sådan tilføjes et nyt modul eller ny rute til rci.dk:

I rci.dk/index.php tilføjes en ny præfiks-blok. Koden undersøger $prefix og håndterer enten omdirigering eller direkte visning:

PHP - Tilføjelse af ny rute i rci.dk/index.php
// Eksempel: Nyt modul 'mitmodul' kobles på rci.dk (fx rci.dk/m/123 eller rci.dk/mitmodul/123)
if ($prefix === 'mitmodul' || $prefix === 'm') {
    $item_id = $code;
    if (!empty($item_id)) {
        // Valgfrit: Log scanning eller udfør hurtig validering her...
        
        // Viderestil deltageren til modulets mobilvisning:
        header("Location: https://studio.ravencraft.dk/mitmodul/view.php?id=" . urlencode($item_id));
        exit;
    }
}

📦 Central Biblioteks-arkitektur (lib.ravencraft.dk & lib_private)

For at undgå duplikering af kode og sikre 100% GDPR-compliance samt uafhængighed af eksterne CDN'er, adskiller Studio platformen skarpt mellem offentlige frontend-aktiver og private backend-biblioteker.

1 lib_ravencraft_dk (Offentligt Frontend CDN & Asset Hub)

Det offentlige subdomæne https://lib.ravencraft.dk (mappe: lib_ravencraft_dk/) fungerer som platformens centrale distributionshub for stylesheets, skrifttyper, JavaScript-biblioteker, statiske brand-assets og dynamiske uploads. Det betjener Studio, samtlige subdomæner samt eksterne webapps som infokort.dk:

  • CORS & Caching: .htaccess udsender Access-Control-Allow-Origin: * og 1-års browser-cache, så webfonts, scripts og billeder kan hentes på tværs af alle subdomæner uden sikkerhedsfejl eller unødige genhentninger.
  • Statiske Brand Assets (assets/img/): Huser globale brandelementer (favicon.ico, favicon.png, default_avatar.webp, header_logo.png).
  • Dynamiske Uploads (uploads/): Centraliseret lager for brugeravatarer (uploads/avatars/) og organisationslogoer (uploads/orgs/). Sikrer at underdomæner som flow.ravencraft.dk og buzz.ravencraft.dk aldrig leder lokalt efter uploads med 404-fejl til følge.
  • GDPR & Stabilitet: Ingen afhængighed af eksterne CDN'er (som cdnjs eller jsdelivr). Ingen bruger-IP'er lækkes til tredjepartsudbydere.
lib_ravencraft_dk/ # Web-root for https://lib.ravencraft.dk ├── .htaccess # CORS headers (*) og 1-års browser-caching ├── assets/img/ # Brand assets (favicon, default avatar, logoer) ├── uploads/ # Brugeravatarer og organisationslogoer │ ├── avatars/ │ └── orgs/ ├── css/ │ ├── studio_ui.css # Officielt Brandbook stylesheet │ └── easymde.min.css # EasyMDE editor styling ├── js/ │ ├── heic2any/heic2any.min.js # iPhone HEIC foto konvertering │ ├── easymde/easymde.min.js # Markdown editor │ └── marked/marked.min.js # Markdown parser └── fonts/ # Lokale webfonts (Inter, Roboto osv.)
2 lib_ravencraft_dk_private (Delt Privat Backend Kerne)

Server-side PHP biblioteker (som PHPMailer og Composer-pakker) må aldrig placeres i en offentlig web-root. De bor i stedet i lib_ravencraft_dk_private/, placeret uden for webserverens offentlige mappe:

  • Delt mellem flere webapps: Både Ravencraft Studio/moduler og eksterne webapps på serveren (f.eks. infokort.dk) inkluderer herfra – kun én central installation at opdatere og vedligeholde.
  • Lynhurtig kørsel: Læses direkte fra lokal disk med 0 ms netværks-overhead og fuld PHP OPcache-understøttelse.
  • Central Autoloader: Enhver applikation skal blot kalde require_once lib_private_path('autoload.php'); for at aktivere de delte pakker.
  • PHPMailer (v7.1.1): Ligger i lib_ravencraft_dk_private/vendor/PHPMailer/ og konfigureres til at sende via Simply.coms officielle mailserver websmtp.simply.com:587 med STARTTLS og SMTP-autentificering for ubegrænset scriptafsendelse.

🚀 Stand-alone Modul Skalering (12-Factor App)

Alle moduler i Ravencraft platformen skal udvikles, så de kan skaleres ud på deres egen dedikerede server blot ved at ændre miljøvariabler, uden at en eneste linje PHP-kode skal omskrives.

⚙️ Konfigurationsfil & Eksterne Ressource-referencer

Hvert modul indeholder i sin private mappe (f.eks. flow_ravencraft_dk_private/config.php) et centralt konfigurationsobjekt. Ingen eksterne URLs må hardcodes direkte i PHP-kildeteksten. Benyt altid de definerede miljø- og konfigurationsværdier:

PHP - Standard Modul Konfiguration (modul_private/config.php)
<?php
/**
 * Eksempel på stand-alone forberedt modulkonfiguration
 * Værdierne overskrives nemt via Apache SetEnv i .htaccess eller .env filer
 */
return [
    'app_name'    => 'Studio Flow',
    'environment' => getenv('APP_ENV') ?: 'production', // 'development' | 'production' | 'standalone'

    // 🌐 Eksterne URLs (Frontend, Identitet & Gateway)
    'urls' => [
        'cdn'      => getenv('STUDIO_CDN_URL')      ?: 'https://lib.ravencraft.dk',
        'portal'   => getenv('STUDIO_PORTAL_URL')   ?: 'https://studio.ravencraft.dk',
        'rci'      => getenv('RCI_SHORT_URL')       ?: 'https://rci.dk',
        'services' => getenv('STUDIO_SERVICES_URL')  ?: 'https://services.ravencraft.dk',
    ],

    // ⚙️ Backend Integrationer
    'backend' => [
        // 'shared_server' når moduler bor sammen, 'standalone' hvis flyttet til egen server
        'driver'           => getenv('STUDIO_BACKEND_MODE') ?: 'shared_server',
        'lib_private_path' => getenv('LIB_PRIVATE_DIR')     ?: __DIR__ . '/../../lib_ravencraft_dk_private',
        'studio_core_path' => getenv('STUDIO_PRIVATE_DIR')  ?: __DIR__ . '/../../studio_ravencraft_dk_private',
    ]
];

De to driftstilstande:

1. Samme Server (I dag)

Moduler trækker direkte på lib_ravencraft_dk_private og studio_private via lokale diskstier. Sessioner og claims deles lynhurtigt over .ravencraft.dk cookies med 0 ms netværkskald.

2. Egen Server (Stand-alone)

Modulets webroot og private mappe flyttes til en ny server. Databasen følger med. I .htaccess peges STUDIO_CDN_URL på https://lib.ravencraft.dk og STUDIO_PORTAL_URL på https://studio.ravencraft.dk – og modulet kører videre fejlfrit!

🗺️ Hvor findes biblioteker, styles og scripts?

Komplet fil- og funktionskort over alle delte aktiver i platformen. Genbrug altid eksisterende biblioteker i stedet for at tilføje duplikater.

🎨 Central Stylesheets (CSS)

/assets/css/ & /assets/styles/
Sti Formål Inkluderes via
/assets/css/studio_ui.css Det centrale UI designsystem (knapper, kort, modaler, formularer, badges, alerts, tabs, heroes). Automatisk via head.php
/assets/styles/style.css Global master stylesheet med base typography, reset, grid tables og system header. Automatisk via head.php
/assets/styles/style-poll-presentation.css Storskærms- og kioskpræsentation for afstemninger og live grafer. Valgfrit i præsentationsvisninger
/assets/styles/style-buzz-presentation.css Realtids gamification og quiz-podie layout for Studio Buzz. Valgfrit i spilvisninger
/assets/styles/style-tag-cloud.css Visualisering og animationslayout for live ordskyer. Valgfrit i ordsky-visninger

⚡ JavaScript Værktøjer & Realtime

/assets/js/
Script / Sti Funktion Brugs-eksempel
/assets/js/studio-drag-drop.js Standard HTML5 træk-og-slip bibliotek til Kanban-boards, genorganisering af trin og lister. <script src="/assets/js/studio-drag-drop.js"></script>
/assets/js/studio-webrtc.js P2P WebRTC data-kanaler til lynhurtig realtids multiplayer uden server-load. const rtc = new StudioWebRTC(sessionId);
/assets/js/buzz-network.js WebSocket & netværkslag for live spilsynkronisering og buzzere. <script src="/assets/js/buzz-network.js"></script>
https://lib.ravencraft.dk/js/altcha/altcha.min.js ALTCHA Proof-of-Work web component (lokalt hostet jf. Brandbook, UMD bundle). <script async defer src="https://lib.ravencraft.dk/js/altcha/altcha.min.js"></script>
https://studio.ravencraft.dk/altcha-challenge.php Letvægts proof-of-work spam-beskyttelse uden cookietracking eller eksterne Google-kald (CORS aktiveret). <altcha-widget challengeurl="https://studio.ravencraft.dk/altcha-challenge.php"></altcha-widget>

⚙️ Private Micro-services & Inkluderede Komponenter

studio_ravencraft_dk_private/includes/
Filnavn Hovedfunktioner Brug / Formål
head.php Injektion af meta-tags, viewport, CSS, tema-variabler, favicon og organisationens farver. Skal altid inkluderes i <head>
header.php & header-user.php Fælles systembar med logo, titel, organisation og bruger-avatar dropdown menu. Skal altid inkluderes i <header>
micro-services.php formatToLocalTime($utc), getClientIP(), anonymizeIP($ip), get_db_path($name), get_system_settings(), lib_public_path(), lib_private_path(), lib_asset_url(), refresh_user_session_claims(). Inkluderer automatisk mail-service.php. Generelle globale platformtjenester og stistyring
access-service.php grant_user_module_access($uid, $mod, $type, $exp), check_user_module_access_db($uid, $mod). Håndtering af 14-dages demoer og rettighedsmoduler i studio_access.db
image-service.php studio_save_uploaded_image_as_webp($file, $targetDir, $prefix, $quality). Konverterer til WebP, genererer absolutte CDN URLs til lib_ravencraft_dk og spejler automatisk avatarer og org-logoer. Central billedkonvertering, WebP-optimering og CDN-spejling
org-service.php get_user_organization($uid), organisationstilknytning og custom farveprofiler. Normaliserer automatisk logo-stier til CDN. Multi-tenant organisationsstyring
mail-service.php send_system_email($to, $subject, $body, $fromName, $replyTo) og send_email() via PHPMailer (v7.1.1 fra lib_ravencraft_dk_private) over websmtp.simply.com:587 med STARTTLS. Transaktionelle e-mails, OTP logins, invitationer og bekræftelser
components/comments-component.php Komplet plug-and-play kommentartråd-widget med avatars, svar og sletning. Inkluder i værktøjer for brugerfeedback
global-smileys.php Standardiserede smiley- og feedbackskalaer (1-5) med ensartede ikoner. Hurtig brugerevaluering på touchskærme

⚡ Central Services Hub (services.ravencraft.dk)

REST APIs & Microservices

https://services.ravencraft.dk fungerer som platformens fælles backend API- og mikrotjeneste-hub. Tjenesterne udstiller standardiserede endpoints til billedkonvertering, placeholders, logingestion, mailforsendelse og universel QR-kodegenerering.

📱 QR Router & Generator Service (/qr-gen)

Aktiv v1.0.0

Officielt QR Endpoint: https://services.ravencraft.dk/qr-gen
Samler al QR-kodegenerering for hele Ravencraft (Studio Survey, Studio Poll, Studio QR, eksterne sites). Udstyret med disk-caching, så gentagne scanninger og visninger afvikles på < 5 ms med HTTP 304 / ETag uden at belaste eksterne netværk eller risikere adblocker-blokeringer.

Parameter: data (Påkrævet)
URL el. tekst der kodes
Parameter: size (px)
50 - 1200 (standard 300)
Parameter: color & bgcolor
Hex-farver uden #
Parameter: qzone & ecc
Margen (0-20) & L/M/Q/H
Parameter: download=1
Tvinger fil-download
Parameter: transparent=1
100% gennemsigtig baggrund

📋 Samtlige registrerede mikrotjenester i services.ravencraft.dk:

Mikrotjeneste Endpoint Formål & Funktion
QR-Gen /qr-gen Universel QR-kode generator og router med disk-caching, custom farver og download-stream.
Placeholder /placeholder Dynamisk placeholder-billedgenerator (PNG/SVG) med brugerdefineret tekst, dimensioner og farver.
Any2WebP /any2webp Universel on-the-fly billedkonvertering til optimeret WebP format (PNG, JPG, GIF, BMP).
PNG2WebP /png2webp High-speed cached PNG til WebP konvertering.
HD-Scaling /hd-scaling Proportional 16:9 canvas-indstøbning af vilkårlige formater til HD, 2K og 4K præsentationer.
Log Ingest /log/ingest.php Centraliseret asynkron event-, revisions- og fejllogning til SQLite.
Mail /mail Transaktionel e-mail API over PHPMailer og Simply.com SMTP.

🎨 UI Kontrol-katalog (Live Showcase)

Nedenfor ses samtlige kontroller og klasser defineret i studio_ui.css. Hvert element gengives levende under det aktive tema, ledsaget af færdige kodeeksempler med 1-klik kopiering.

🔘 Knapper (Buttons & Action Variants)

.studio-btn, .btn, .studio-btn-*

Tag Knap (.tag-btn)
HTML Kode - Knapper
<!-- Standard Varianter -->
<button type="button" class="studio-btn studio-btn-primary">Primary Knap</button>
<button type="button" class="studio-btn studio-btn-secondary">Secondary Knap</button>
<button type="button" class="studio-btn studio-btn-outline">Outline Knap</button>
<button type="button" class="studio-btn studio-btn-success">Success Knap</button>
<button type="button" class="studio-btn studio-btn-danger">Danger Knap</button>
<button type="button" class="studio-btn studio-btn-link">Link Knap</button>

<!-- Knap-størrelser -->
<button type="button" class="studio-btn studio-btn-sm studio-btn-primary">Lille knap</button>
<button type="button" class="studio-btn studio-btn-lg studio-btn-primary">Stor knap</button>

<!-- Knapgruppe -->
<div class="studio-btn-group">
    <button type="button" class="studio-btn studio-btn-secondary">Annuller</button>
    <button type="submit" class="studio-btn studio-btn-primary">Gem ændringer</button>
</div>

🎯 Interaktive Valgknapper (Choice Buttons)

.studio-choice-btn, .btn-choice
HTML Kode - Valgknapper
<button type="button" class="studio-choice-btn">
    <span>🚀 Hurtig automatisk opsætning</span>
    <span>➔</span>
</button>

🃏 Kort, Containere & Layout (Cards & Grid)

.studio-card, .channel-group-card, .studio-card-grid

Standard Studio Kort

Kort

Dette er standard-kortet i Studio med bløde hjørner, subtil skygge og temastyret baggrund.

Kort med Farveaccent

Highlight

Anvender .channel-group-card for en fremhævet venstrebord i temaets primære farve.

HTML Kode - Kort
<div class="studio-card">
    <div class="studio-card-header">
        <h4 class="studio-card-title">Titel på Kort</h4>
        <span class="studio-badge studio-badge-primary">Status</span>
    </div>
    <div class="studio-card-body">
        <p>Indhold og forklaring herinde...</p>
    </div>
    <div class="studio-card-footer">
        <button type="button" class="studio-btn studio-btn-secondary">Luk</button>
        <button type="button" class="studio-btn studio-btn-primary">Gem</button>
    </div>
</div>

<!-- Responsivt kort-gitter -->
<div class="studio-card-grid">
    <!-- Kort indsættes her -->
</div>

🏛️ Studio Landingsside 4-Kolonne Grid (Kun Landingsside)

.studio-module-grid, .module-card
⚠️ Gælder KUN for Studio Landingssiden

Dette specifikke 4-kolonne grid (repeat(4, 1fr)) og tilhørende .module-card er udelukkende tilladt på Studio portalens landingsside (forsiden) for at levere det velkendte, kompakte katalog-overblik fra Studio v1 og v2.

Forbud mod brug i moduler: Dashboards, arbejdsskærme og interne undersider i modulerne må IKKE benytte .studio-module-grid, men skal altid anvende det generelle, fleksible .studio-card-grid.

Studio Flow

Visuel processtyring, interaktive didaktiske læringsforløb og trin-for-trin flow.

Studio Network 🛠️ Test-adgang

Didaktisk netværk, faglige statusopdateringer og intern videndeling.

Studio Buzz

Lynhurtig interaktiv buzzer og live-spørgsmål til auditoriet og klasserummet.

Studio Poll 🛠️ Vedligehold

Hurtige didaktiske afstemninger og meningsmålinger med øjeblikkelig resultatgraf.

HTML & CSS Kode - Landingsside 4-Kolonne Modul-grid
<!-- 4-Kolonne Modul-grid (BEMÆRK: Gælder KUN for Studio Landingssiden index.php) -->
<div class="studio-module-grid">
    <div class="module-card">
        <div class="module-card-header">
            <h4 class="module-card-title">
                <span>Studio Flow</span>
                <!-- Kun vedligeholdelses-badges tilladt (ingen Kerne/Subdomæne badges) -->
                <span class="studio-badge studio-badge-warning" style="font-size: 10px;">🛠️ Test-adgang</span>
            </h4>
            <p class="module-card-desc">Visuel processtyring og interaktive didaktiske læringsforløb.</p>
        </div>
        <div class="module-card-footer">
            <span style="font-size: 12px; color: var(--studio-success); font-weight: 600;">● Aktiv</span>
            <a href="https://flow.ravencraft.dk" class="studio-btn studio-btn-primary studio-btn-sm">Åbn Flow →</a>
        </div>
    </div>
</div>

<!-- CSS Regler i assets/css/studio_ui.css -->
.studio-module-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
    margin-bottom: 40px;
}
@media (max-width: 1100px) { .studio-module-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 800px)  { .studio-module-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px)  { .studio-module-grid { grid-template-columns: 1fr; } }

📝 Formular-kontroller & Input-felter

.studio-form-group, .studio-input, .studio-select
Dette er en hjælpetekst (.studio-input-hint)
HTML Kode - Formular
<div class="studio-form-group">
    <label class="studio-label" for="felt1">Navn på Værktøj</label>
    <input type="text" id="felt1" class="studio-input" placeholder="Indtast værdi...">
    <div class="studio-input-hint">Hjælpetekst til brugeren.</div>
</div>

<!-- Input-gruppe med integreret knap -->
<div class="studio-input-group">
    <input type="text" class="studio-input" placeholder="Søg...">
    <button type="button" class="studio-btn studio-btn-primary">Søg</button>
</div>

🪟 Modaler & Lightboxes (Interaktiv Demo)

.studio-modal-backdrop, .studio-modal-card

Studio modaler har indbygget backdrop-blur, blød åbningsanimation og kan lukkes via kryds, klik udenfor eller Escape-tasten.

HTML & JS Kode - Modal
<!-- Modal HTML Struktur -->
<div id="minModal" class="studio-modal-backdrop" onclick="closeModal('minModal')">
    <div class="studio-modal-card" onclick="event.stopPropagation()">
        <div class="studio-modal-header">
            <h3 class="studio-modal-title">Titel på Modal</h3>
            <button type="button" class="studio-modal-close" onclick="closeModal('minModal')">×</button>
        </div>
        <div class="studio-modal-body">
            <p>Indholdet af modalkortet placeres her...</p>
        </div>
        <div class="studio-modal-footer">
            <button type="button" class="studio-btn studio-btn-secondary" onclick="closeModal('minModal')">Luk</button>
            <button type="button" class="studio-btn studio-btn-primary">Bekræft</button>
        </div>
    </div>
</div>

<!-- JS Hjælpere (Åbn / Luk) -->
<script>
function openModal(id) {
    const el = document.getElementById(id);
    if (el) { el.classList.add('open'); document.body.style.overflow = 'hidden'; }
}
function closeModal(id) {
    const el = document.getElementById(id);
    if (el) { el.classList.remove('open'); document.body.style.overflow = ''; }
}
</script>

🏷️ Badges & Status-mærkater

.studio-badge, .studio-badge-*
Primary Tag ✔ Aktiv / Fuldført ⚡ Venter svar ✖ Fejlet / Udløbet 🔒 Låst Modul
HTML Kode - Badges
<span class="studio-badge studio-badge-primary">Primary</span>
<span class="studio-badge studio-badge-success">✔ Aktiv</span>
<span class="studio-badge studio-badge-warning">⚡ Advarsel</span>
<span class="studio-badge studio-badge-danger">✖ Fejl</span>
<span class="studio-badge-lock">🔒 Låst</span>

⚠️ Notifikationer & Alarmer (Alerts)

.studio-alert, .studio-alert-*
ℹ️ Info: Dette er en oplysende notifikation til brugeren om systemstatus.
✔ Succes: Dine ændringer er blevet gemt i databasen uden fejl!
⚡ Advarsel: Du har 2 dage tilbage af din gratis prøveperiode.
✖ Fejl: Handlingen kunne ikke gennemføres. Kontroller dine indtastninger.
HTML Kode - Alarmer
<div class="studio-alert studio-alert-info">
    ℹ️ <strong>Info:</strong> Systemet opdateres i nat.
</div>

<div class="studio-alert studio-alert-success">
    ✔ <strong>Succes:</strong> Elementet er oprettet!
</div>

<div class="studio-alert studio-alert-warning">
    ⚡ <strong>Advarsel:</strong> Husk at gemme dine data.
</div>

<div class="studio-alert studio-alert-danger">
    ✖ <strong>Fejl:</strong> Ugyldig e-mailadresse angivet.
</div>

🧭 Sub-Headers, Faner & Trin-indikatorer (Tabs & Wizard)

.studio-sub-header, .studio-tabs, .step-indicators
Studio Modul
1. Grundlæggende Data
2. Spørgsmål & Svar
3. Publicering & QR
HTML Kode - Navigation & Faner
<!-- Sub-header Værktøjslinje -->
<div class="studio-sub-header">
    <div class="studio-sub-header-nav">
        <span style="font-weight: 700;">Modultitel</span>
        <div class="studio-tabs">
            <a href="?tab=1" class="studio-tab active">Oversigt</a>
            <a href="?tab=2" class="studio-tab">Indstillinger</a>
        </div>
    </div>
    <div class="studio-sub-header-actions">
        <button class="studio-btn studio-btn-sm studio-btn-primary">Handling</button>
    </div>
</div>

<!-- Trin-indikator (Wizard) -->
<div class="step-indicators">
    <div class="step-dot active"><span>1.</span> Opsætning</div>
    <div class="step-dot"><span>2.</span> Konfiguration</div>
    <div class="step-dot"><span>3.</span> Fuldført</div>
</div>

📊 Data-Tabeller (.list-table & .grid-table)

table, .list-table, th, td
# Session / Navn Status Oprettet Handlinger
1 Workshop: Digital Didaktik 2026 Aktiv 09.09.2026 14:30
2 Live Poll: Fremtidens Værktøjer Venter 08.09.2026 09:15
HTML Kode - Data-tabel
<table class="list-table">
    <thead>
        <tr>
            <th>#</th>
            <th>Navn</th>
            <th>Status</th>
            <th style="text-align: right;">Aktion</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>Element titel</td>
            <td><span class="studio-badge studio-badge-success">Aktiv</span></td>
            <td style="text-align: right;">
                <button type="button" class="btn-action">Rediger</button>
            </td>
        </tr>
    </tbody>
</table>

🦸 Hero Banner (.studio-hero)

.studio-hero, .studio-hero-title, .studio-hero-desc

Kom hurtigt i gang med Modulet

Optimeret velkomstsektion til kataloger og modul-dashboards

Brug hero-sektionen til at byde brugeren velkommen og give klar instruks om modulets overordnede formål.

HTML Kode - Hero Banner
<section class="studio-hero">
    <h1 class="studio-hero-title">Modultitel</h1>
    <p class="studio-hero-subtitle">Kort undertitel eller tagline</p>
    <p class="studio-hero-desc">Uddybende introduktionstekst til sidens formål...</p>
</section>

🎨 CSS Custom Properties Reference

:root Design Tokens
Token / CSS Variabel Eksempel Værdi (Standard) Anvendelse
var(--studio-org-primary) / var(--primary) #0070f3 Primære knapper, aktive faner, links og brandfarver.
var(--card-bg) / var(--studio-card-bg) #ffffff Baggrund for kort, paneler, tabeller og modaler.
var(--dark) / var(--studio-dark) #0f172a Primær tekstfarve, overskrifter og ikoner.
var(--bg) / var(--studio-bg) #f8fafc Selve sidens baggrund og sekundære overflader.
var(--border) / var(--studio-border) #e2e8f0 Bordere på inputs, kort, tabeller og adskillere.
var(--studio-danger) #ef4444 Slet-knapper, fejlmeddelelser og kritiske advarsler.
var(--studio-success) #10b981 Succes-badges, gennemførte opgaver og gem-indikatorer.
var(--studio-warning) #f59e0b Advarsels-badges, tidsbegrænsninger og noter.

✨ Studio Live Modal Demo

Dette er en fuldt funktionsdygtig Studio Modal. Den understøtter automatisk tema-arv, baggrunds-blur, scroll-lås på siden og kan lukkes via Escape-tasten eller ved at klikke uden for kortet.

✔ Designsystem Verificeret: Alt layout tilpasses dynamisk til dine tema- og organisationsvalg!