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.
🎯 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:
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.
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.
Hvis hverken brugeren eller brugerens organisation har specificeret et tema, anvendes det globale standardtema konfigureret i systemindstillingerne ($sys_settings['theme_mode'] ?? 'light').
$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:
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.
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/.
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.
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.
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:
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.
I Studio v3 bor alle moduler på deres egne selvstændige subdomæner til ravencraft.dk:
- Hovedportal & Identity Provider:
studio.ravencraft.dk(udvikles istudiov3.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.
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.
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.
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'](indeholderorg_name,logo_urlsomhttps://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.
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:
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.
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.
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.
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.
Opret en dedikeret undermappe i modules/ navngivet med små bogstaver og bindestreger/underscores:
Hvert modul skal indeholde en gyldig module.json fil:
{
"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"
}
development (under udvikling), active (fuldt tilgængelig), production (stabil produktion), maintenance (lukket pga. vedligeholdelse).
Tilføj tilladelsesnoden og modulets landing-card i studio_ravencraft_dk_private/includes/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
}
Tilføj rewrite-regler i rodens .htaccess, så brugerne kan tilgå studio.ravencraft.dk/mitmodul direkte:
# 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]
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.dbgodkendes automatisk. - Brugere uden adgang eller med udløbet prøveperiode omdirigeres venligt tilbage til forsiden med en advarselsbesked.
// Inkluder central bootstrap (indlæser .htaccess miljøvariabel, microservices og session)
require_once __DIR__ . '/../../bootstrap.php';
// Beskyt modulet:
require_module_access('mitmodul');
Brug altid get_db_path('mitmodul.db') til at hente stien til databasen.
Eksempel på en robust initialiseringsfunktion:
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;
}
Kopiér denne skabelon direkte ind som modules/mitmodul/index.php for at komme i gang på 30 sekunder:
<?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.
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 |
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_urlser allerede forberedt istudio_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.phpuden 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.dkfor 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:
// 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.
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:
.htaccessudsenderAccess-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 somflow.ravencraft.dkogbuzz.ravencraft.dkaldrig 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.
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 mailserverwebsmtp.simply.com:587med 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.
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
/**
* 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:
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.
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> |
⚡ 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.
data (Påkrævet)URL el. tekst der kodes
size (px)50 - 1200 (standard 300)
color & bgcolorHex-farver uden #
qzone & eccMargen (0-20) & L/M/Q/H
download=1Tvinger fil-download
transparent=1100% 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 |
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-*<!-- 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<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-gridStandard Studio Kort
KortDette er standard-kortet i Studio med bløde hjørner, subtil skygge og temastyret baggrund.
Kort med Farveaccent
HighlightAnvender .channel-group-card for en fremhævet venstrebord i temaets primære farve.
<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
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.
<!-- 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<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.
<!-- 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-*<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-*<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>
📊 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 |
<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-descKom 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.
<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. |