Initial commit

This commit is contained in:
KirbyCMS Deploy
2026-04-15 11:50:31 +00:00
commit 0a8c107828
1114 changed files with 203788 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
preview: fields
wysiwyg: true
tabs:
content:
label: tab.content.label
fields:
advanced:
label: tab.advanced.label
fields:
blockId:
label: field.blockId.label
type: slug
before: "#"
icon: false

View File

@@ -0,0 +1,11 @@
extends: blocks/_base
title: example
icon: title
label: "{{ text }}"
tabs:
content:
fields:
text:
label: text
type: text

View File

@@ -0,0 +1,4 @@
label: field.blocks.label
type: blocks
fieldsets:
- example

View File

@@ -0,0 +1,2 @@
extends: fields/link
label: field.button.label

View File

@@ -0,0 +1,10 @@
label: field.image.label
type: files
uploads:
parent: site.find('page://images')
template: image
multiple: false
image:
cover: false
info: "{{ file.alt }}"
query: site.find('page://images').images.filterBy('template', 'image')

View File

@@ -0,0 +1,34 @@
label: field.link.label
type: object
empty: field.link.empty
columns:
label:
width: 1/2
link:
width: 1/2
fields:
label:
label: field.link.label.label
type: text
width: 1/3
link:
label: field.link.link.label
type: link
width: 2/3
options:
- url
- page
- file
- email
- tel
newTab:
label: field.link.newTab.label
type: toggle
width: 1/3
default: false
anchor:
label: field.link.anchor.label
type: slug
icon: false
width: 2/3
before: "#"

View File

@@ -0,0 +1,12 @@
extends: fields/writer
inline: false
nodes:
- paragraph
- heading
- bulletList
- orderedList
headings:
- 2
- 3
- 4
- 5

View File

@@ -0,0 +1,7 @@
label: field.text.label
type: writer
marks:
- bold
- link
- email
inline: true

View File

@@ -0,0 +1,4 @@
title: file.file.title
fields:
hidden: true

View File

@@ -0,0 +1,10 @@
title: file.image.title
accept:
extension: jpg, jpeg, png, svg
type: image
fields:
alt:
label: file.image.alt.label
type: text
help: file.image.alt.help

View File

@@ -0,0 +1,4 @@
extends: pages/home
title: page.error.title
image:
icon: cancel

View File

@@ -0,0 +1,16 @@
extends: pages/images
title: page.files.titles
image:
icon: file-word
sections:
files:
label: section.files.label
type: files
template: file
layout: table
limit: 60
uploads:
template: file
search: true
sortBy: filename desc

View File

@@ -0,0 +1,25 @@
extends: pages/layout
title: page.home.title
image:
icon: home
options:
# access
# changeSlug
# changeStatus
# changeTemplate
# changeTitle
# create
delete: false
duplicate: false
# list
move: false
# preview
# sort
# update
tabs:
content:
columns:
sidebar: false

View File

@@ -0,0 +1,40 @@
title: page.images.title
image:
icon: file-image
back: "transparent"
color: "var(--color-gray-600)"
query: false
options:
# access
changeSlug: false
changeStatus: false
# changeTemplate
changeTitle: false
# create
delete: false
duplicate: false
# list
move: false
preview: false
# sort
update: false
status:
draft: false
unlisted: true
listed: false
sections:
files:
label: section.images.label
type: files
layout: cardlets
template: image
uploads:
template: image
search: true
sortBy: filename desc
info: '{{ file.alt.isNotEmpty ? file.filename : "" }}'
text: "{{ file.alt.or(file.filename) }}"
limit: 100

View File

@@ -0,0 +1,39 @@
title: page.layout.title
image:
icon: grid
back: "var(--theme-accent)"
color: "var(--theme-primary)"
options:
# access
# changeSlug
# changeStatus
# changeTemplate
# changeTitle
# create
# delete
# duplicate
# list
# move
# preview
# sort
# update
tabs:
content:
label: tab.content.label
icon: text
columns:
main:
width: 3/4
type: fields
fields:
blocks: fields/blocks
sidebar:
width: 1/4
sections:
children:
label: section.children.label
type: pages
template: layout
seo: seo/page

View File

@@ -0,0 +1,22 @@
title: site.title
tabs:
pages:
label: tab.pages.label
icon: page
columns:
- width: 2/3
sections:
pages:
label: field.pages.label
type: pages
info: "/{{ page.slug }}"
create:
- layout
templates:
- home
- error
- layout
image: icon
navigation: tabs/navigation
seo: seo/site

View File

@@ -0,0 +1,26 @@
icon: bars
label: tab.navigation.label
columns:
- width: 1/4
fields:
_navigation:
label: field.navigation.label
type: headline
- width: 3/4
sections:
placeholder: &placeholder
headline: Placeholder
type: info
text: " "
- width: 1
fields:
_line1: &line
type: line
- width: 1/4
fields:
_footer:
label: field.footer.label
type: headline
- width: 3/4
sections:
placeholder: *placeholder

View File

@@ -0,0 +1,7 @@
title: user.admin.title
description: user.admin.description
fields:
favorites:
label: user.favorites.label
type: pages

View File

@@ -0,0 +1,10 @@
extends: users/admin
title: user.editor.title
description: user.editor.description
permissions:
access:
system: false
languages: false
backups: false
users: false

View File

@@ -0,0 +1,80 @@
<?php
use Kirby\Cms\Pages;
use Kirby\Http\Url;
use tobimori\Spielzeug\Menu;
require_once dirname(__DIR__) . '/plugins/kirby3-dotenv/global.php';
loadenv([
'dir' => realpath(dirname(__DIR__, 2)),
'file' => '.env',
]);
return [
'debug' => json_decode(env('KIRBY_DEBUG')),
'routes' => require __DIR__ . '/routes.php',
'thumbs' => require __DIR__ . '/thumbs.php',
'yaml.handler' => 'symfony',
'date.handler' => 'intl',
'url' => env("APP_URL"),
'tobimori.seo' => require __DIR__ . '/seo.php',
'tobimori.dreamform' => require __DIR__ . '/dreamform.php',
'tobimori.icon-field' => [
// use generated sprite, requires pnpm run build
// to generate (dev sprite doesn't work since it's not in the public folder)
'folder' => '',
'sprite' => fn() => Url::path(vite()->useHotFile('.never')->asset('assets/sprite.svg'))
],
/** Email */
'email' => require __DIR__ . '/email.php',
'auth' => [
'methods' => ['password', 'password-reset'],
'challenge' => [
'email' => [
'from' => env("KIRBY_MAIL_FROM"),
'subject' => 'Login-Code'
]
]
],
/** Caching */
'cache' => [
'pages' => [
'active' => json_decode(env('KIRBY_CACHE')),
]
],
/** Build Env / Vite / etc. */
'bnomei.dotenv.dir' => fn() => realpath(kirby()->roots()->base()),
'lukaskleinschmidt.kirby-laravel-vite.buildDirectory' => 'dist',
/** Panel */
'johannschopplich.plausible.sharedLink' => env('PLAUSIBLE_SHARED_LINK'),
'distantnative' => [
'retour' => [
'config' => __DIR__ . './../../data/storage/retour/config.yml',
'database' => __DIR__ . './../../data/storage/retour/log.sqlite'
]
],
'panel' => [
'menu' => fn() => array_merge(
[
'site' => Menu::site(),
],
Menu::favorites(kirby()->user()?->favorites()->toPages() ?? new Pages([])),
[
'-',
'images' => Menu::page(null, 'file-image', page('page://images')),
'files' => Menu::page(null, 'file-word', page('page://files')),
'-',
'users',
'plausible',
'retour',
]
)
],
'ready' => fn() => [
'panel' => [
'favicon' => option('debug') ? 'static/panel/favicon-dev.svg' : 'static/panel/favicon-live.svg',
'css' => vite('src/styles/panel.css'),
],
]
];

View File

@@ -0,0 +1,12 @@
<?php
return [
'multiStep' => false,
'mode' => 'htmx',
'useDataAttributes' => true,
'precognition' => true,
'secret' => env('DREAMFORM_SECRET'),
'guards' => [
'available' => ['honeypot']
],
];

View File

@@ -0,0 +1,13 @@
<?php
return [
'transport' => [
'type' => 'smtp',
'host' => env("KIRBY_MAIL_HOST"),
'port' => json_decode(env("KIRBY_MAIL_PORT")),
'security' => true,
'auth' => 'tls',
'username' => env("KIRBY_MAIL_USER"),
'password' => env("KIRBY_MAIL_PASS")
]
];

View File

@@ -0,0 +1,3 @@
<?php
return [];

View File

@@ -0,0 +1,16 @@
<?php
return [
'robots' => [
'pageSettings' => false
],
'canonicalBase' => env("APP_URL"),
'files' => [
'parent' => 'site.find("page://images")',
'template' => 'image'
],
'socialMedia' => [
'twitter' => false,
'youtube' => false
],
];

View File

@@ -0,0 +1,9 @@
<?php
return [
'srcsets' => [
'small' => [300, 500, 800],
'default' => [400, 800, 1000, 1200],
'large' => [800, 1400, 2000, 2600],
]
];

View File

@@ -0,0 +1,15 @@
<?php
use Kirby\Data\Yaml;
return [
'code' => 'de',
'default' => true,
'direction' => 'ltr',
'locale' => [
'LC_ALL' => 'de_DE'
],
'name' => 'Deutsch',
'translations' => Yaml::read(__DIR__ . '/../translations/de.yml'),
'url' => ''
];

View File

@@ -0,0 +1,15 @@
<?php
use Kirby\Data\Yaml;
return [
'code' => 'en',
'default' => false,
'direction' => 'ltr',
'locale' => [
'LC_ALL' => 'en_US'
],
'name' => 'English',
'translations' => Yaml::read(__DIR__ . '/../translations/en.yml'),
'url' => '/en'
];

View File

@@ -0,0 +1,23 @@
<?php
use Kirby\Cms\Page;
use Kirby\Content\Field;
class FilesPage extends Page
{
public function metaDefaults()
{
return [
'robotsIndex' => false
];
}
/**
* Override the page title to be static
* to the template name
*/
public function title(): Field
{
return new Field($this, 'title', t("page.{$this->intendedTemplate()->name()}.title"));
}
}

View File

@@ -0,0 +1,5 @@
<?php
class ImagesPage extends FilesPage
{
}

View File

@@ -0,0 +1,5 @@
<?php
class VideosPage extends FilesPage
{
}

View File

@@ -0,0 +1,13 @@
<?php
use Kirby\Cms\App;
App::plugin('project/extended', []);
// helpers
if (!function_exists('icon')) {
function icon(string $type, array|string|null $class = null, array $attr = []): string
{
return snippet('icon', compact('type', 'class', 'attr'), true);
}
}

View File

@@ -0,0 +1 @@
panel.plugin("project/extended", {})

View File

@@ -0,0 +1,5 @@
<?php
/** @var Kirby\Cms\Site $site */ ?>
<footer></footer>

View File

@@ -0,0 +1,5 @@
<?php
/** @var Kirby\Cms\Site $site */ ?>
<header></header>

View File

@@ -0,0 +1,7 @@
<?php
/** @var Kirby\Cms\Site $site */ ?>
<a class="text-white bg-black border-white outline-none sr-only focus-visible:fixed focus-visible:top-4 focus-visible:left-4 focus-visible:py-2.5 focus-visible:px-4 focus-visible:not-sr-only" href="#main">
<?= t('aria.skipNavigation') ?>
</a>

View File

@@ -0,0 +1,12 @@
<?php
use Kirby\Toolkit\A;
if (isset($type)) : ?>
<svg <?= attr(A::merge($attr ?? [], [
'aria-hidden' => true,
'class' => cls($class ?? 'icon')
])) ?>>
<use xlink:href="<?= vite()->asset('assets/sprite.svg') ?>#<?= $type ?>"></use>
</svg>
<?php endif ?>

View File

@@ -0,0 +1,41 @@
<?php
/** @var Kirby\Cms\Page $page
* @var Kirby\Cms\Site $site
* @var Kirby\Cms\App $kirby */
if (json_decode(env('REQUIRES_LOGIN')) && !$kirby->user()) {
go('/panel');
} ?>
<!DOCTYPE html>
<html lang="<?= $kirby->language()?->code() ?>">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<?php snippet('seo/head') ?>
<link rel="icon" href="/favicon.svg" />
<link rel="mask-icon" href="/favicon.svg" color="#000000" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<meta name="theme-color" content="#000000">
<?= vite([
'src/styles/index.css',
'src/index.ts'
]) ?>
</head>
<body class="flex flex-col min-h-screen antialiased overflow-x-clip">
<?php snippet('core/skip-nav') ?>
<?php snippet('core/nav') ?>
<main class="flex-grow">
<div id="main"></div>
<?= $slot ?>
</main>
<?php snippet('core/footer') ?>
<?php snippet('seo/schemas') ?>
</body>
</html>

View File

@@ -0,0 +1,45 @@
<?php
/** @var Kirby\Cms\Page $page
* @var Kirby\Cms\Site $site
* @var Kirby\Cms\App $kirby */
if (json_decode(env('REQUIRES_LOGIN')) && !$kirby->user()) {
go('/panel');
} ?>
<!DOCTYPE html>
<html lang="<?= $kirby->language()?->code() ?>">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<?php snippet('seo/head') ?>
<link rel="icon" href="/favicon.svg" />
<link rel="mask-icon" href="/favicon.svg" color="#000000" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<meta name="theme-color" content="#000000">
<?= vite([
'src/styles/index.css',
'src/index.ts'
]) ?>
</head>
<body class="min-h-screen antialiased overflow-x-clip">
<?php snippet('core/skip-nav') ?>
<?php snippet('core/nav') ?>
<div data-taxi>
<div class="flex flex-col" data-taxi-view>
<main class="flex-grow">
<div id="main"></div>
<?= $slot ?>
</main>
<?php snippet('core/footer') ?>
</div>
</div>
<?php snippet('seo/schemas') ?>
</body>
</html>

View File

@@ -0,0 +1,18 @@
<?php
/**
* @var Kirby\Cms\StructureObject|Kirby\Content\Content $link
*/ ?>
<?php if ($link->link()->isNotEmpty()) : ?>
<a <?= attr([
'class' => $class ?? '',
'href' => $link->link()->toUrl(),
'target' => $link->newTab()->toBool() ? '_blank' : null,
'rel' => $link->newTab()->toBool() ? 'noopener' : null,
'aria-current' => $link->link()->linkType() === 'page' && $link->link()->toPage()?->isActive() ? 'page' : null,
...($attr ?? [])
]) ?>>
<?= $slot ?? $link->label()->or($link->link()->linkTitle()) ?>
</a>
<?php endif ?>

View File

@@ -0,0 +1,97 @@
<?php
/**
* @var Kirby\Cms\File|Kirby\Filesystem\Asset $image The image to display
* @var string|null $alt An optional alt text, defaults to the file's alt text
* @var int|null $ratio Specify a ratio for the image crop
*
* @var array|null $formats Which formats to render (avif, jpeg, etc.)
* @var string|null $preset Which srcset preset to use
* @var string|null $sizes The sizes attribute for the <img> element
*
* @var string|array|null $class Additional classes for the <picture> element
* @var string|array|null $imgClass Additional classes for the <img> element
* @var array|null $attr Additional attributes for the <picture> element
*
* @var bool|null $clientBlur Whether to use client-side blurhash/thumbhash, defaults to true
* @var bool|null $lazy Whether to use lazy loading, defaults to true
* */
use Kirby\Toolkit\A;
$focus ??= is_a($image, 'Kirby\Cms\File') ? $image?->focus() ?? 'center' : 'center';
$ratio ??= null;
$preset ??= 'default';
$clientBlur ??= true;
$attr ??= [];
$formats ??= ['webp', $image?->extension()];
$lazy ??= true;
if (is_a($image, 'Kirby\Cms\File') || is_a($image, 'Kirby\Filesystem\Asset')) : ?>
<picture <?= attr([
'class' => ['block', $class ?? ''],
'style' => '--ratio: ' . ($ratio ?? round($image->ratio(), 2)) . ';',
...$attr
]) ?>>
<?php if ($image->extension() == 'svg') : ?>
<?= svg($image) ?>
<?php else : ?>
<?php foreach ($formats as $format) :
$widths = option("thumbs.srcsets.{$preset}");
$srcset = [];
$median = $ratio ? $image->crop(median($widths), floor(median($widths) / $ratio)) : $image->resize(median($widths)); ?>
<?php
// Generate srcset array
foreach ($widths as $width) {
$srcset[$width . 'w'] = [
'width' => $width,
'height' => $ratio ? floor($width / $ratio) : null,
'crop' => $ratio ? true : false,
'format' => $format
];
} ?>
<?php if ($lazy) : ?>
<source <?= attr([
'type' => "image/{$format}",
'data-srcset' => $image->srcset($srcset),
'data-sizes' => $sizes ?? 'auto',
]) ?>>
<?php else : ?>
<source <?= attr([
'type' => "image/{$format}",
'srcset' => $image->srcset($srcset),
'sizes' => $sizes ?? '100vw'
]) ?>>
<?php endif; ?>
<?php endforeach; ?>
<img <?= attr([
'data-thumbhash' => $clientBlur ? $image->th() : null,
'src' => !$clientBlur ? $image->thUri() : null,
'data-src' => $median->url(),
'width' => $image->width(),
'height' => $ratio ? floor($image->width() / $ratio) : $image->height(),
'alt' => $alt ?? (is_a($image, 'Kirby\Cms\File') ? $image->alt() : null),
'loading' => $lazy ? "lazy" : null,
'data-sizes' => $sizes ?? 'auto',
'class' => cls(['size-full object-cover', $imgClass ?? ' ']),
'style' => A::join([
"aspect-ratio: " . ($ratio ?? $image->ratio()),
"object-position: {$focus}"
], '; '),
]) ?>>
<?php endif ?>
</picture>
<?php
// Dummy element that will be rendered when specified image is not an image
else : ?>
<picture <?= attr(['class' => ['block', $class ?? ''], ...$attr]) ?>></picture>
<?php endif ?>

View File

@@ -0,0 +1,2 @@
<?php $kirby->response()->code(404); // set status code
echo $site->errorPage()->render(); // render 404 if unmatched template

View File

@@ -0,0 +1,3 @@
<?php
require __DIR__ . '/layout.php';

View File

@@ -0,0 +1,3 @@
<?php
require __DIR__ . '/layout.php';

View File

@@ -0,0 +1,11 @@
<?php
/**
* @var Kirby\Cms\App $kirby
* @var Kirby\Cms\Page $page
* @var Kirby\Cms\Site $site
*/
snippet('layout', slots: true); ?>
<?= $page->blocks()->toBlocks() ?>
<?php endsnippet() ?>

View File

@@ -0,0 +1,69 @@
# ARIA
aria.skipNavigation: Navigation überspringen
# Social Media
twitter: Twitter
facebook: Facebook
instagram: Instagram
linkedin: LinkedIn
youtube: YouTube
vimeo: Vimeo
# Roles
user.admin.title: Administrator
user.admin.description: Hat Zugriff auf alle Inhalte und administrative Tools.
user.editor.title: Editor
user.editor.description: Kann alle Inhalte bearbeiten, aber keine administrativen Tools nutzen. (z.B. Nutzerverwaltung)
# Tabs
tab.content.label: Inhalt
tab.advanced.label: Erweitert
tab.pages.label: Seiten
tab.navigation.label: Navigation & Footer
# Files
file.image.title: Bild
file.image.alt.label: Alternativer Text/Bildbeschreibung
file.image.alt.help: Der alternative Text soll Nutzern mit Seheinschränkung & Suchmaschinen-Crawlern helfen, den Inhalt des Bildes zu verstehen.
file.video.title: Video
file.file.title: Dokument
# Pages
page.layout.title: Layout-Seite
page.error.title: Fehlerseite
page.home.title: Startseite
page.images.title: Bilder
page.videos.title: Videos
page.files.title: Dokumente
# Fields
field.blocks.label: Inhalt
field.image.label: Bild
field.link.label: Link
field.link.label.label: Beschriftung
field.link.link.label: Link
field.link.newTab.label: In neuem Tab öffnen?
field.link.empty: Kein Link angegeben
field.link.anchor.label: Anker (Block-ID)
field.button.label: Button
field.blockId.label: Eindeutige ID (Anker)
field.pages.label: Seiten
field.text.label: Text
field.navigation.label: Navigation
field.footer.label: Footer
# Blocks
block.example.title: Block
# Sections
section.images.label: Alle Bilder
section.videos.label: Alle Videos
section.files.label: Alle Dokumente
section.children.label: Unterseiten
# Other
site.title: Dashboard

View File

@@ -0,0 +1,69 @@
# ARIA
aria.skipNavigation: Skip navigation
# Social Media
twitter: Twitter
facebook: Facebook
instagram: Instagram
linkedin: LinkedIn
youtube: YouTube
vimeo: Vimeo
# Roles
user.admin.title: Administrator
user.admin.description: Has access to all content and administrative tools.
user.editor.title: Editor
user.editor.description: Can edit all content but cannot use administrative tools (e.g., user management).
# Tabs
tab.content.label: Content
tab.advanced.label: Advanced
tab.pages.label: Pages
tab.navigation.label: Navigation & Footer
# Files
file.image.title: Image
file.image.alt.label: Alternative Text/Image Description
file.image.alt.help: The alternative text helps visually impaired users & search engine crawlers understand the content of the image.
file.video.title: Video
file.file.title: Document
# Pages
page.layout.title: Layout Page
page.error.title: Error Page
page.home.title: Home Page
page.images.title: Images
page.videos.title: Videos
page.files.title: Documents
# Fields
field.blocks.label: Content
field.image.label: Image
field.link.label: Link
field.link.label.label: Label
field.link.link.label: Link
field.link.newTab.label: Open in new tab?
field.link.empty: No link provided
field.link.anchor.label: Anchor (Block ID)
field.button.label: Button
field.blockId.label: Unique ID (Anchor)
field.pages.label: Pages
field.text.label: Text
field.navigation.label: Navigation
field.footer.label: Footer
# Blocks
block.example.title: Block
# Sections
section.images.label: All Images
section.videos.label: All Videos
section.files.label: All Documents
section.children.label: Subpages
# Other
site.title: Dashboard