Compare commits

..

3 Commits

Author SHA1 Message Date
Jörg Lohrer 8dc6e061ff main: hugo-artefakte entfernt, bereit für nostr-spa-entwicklung
Entfernt: themes/, public/, resources/, layouts/, assets/, archetypes/,
hugo.toml, .hugo_build.lock, .gitmodules. Kompletter Hugo-Stand ist
im Orphan-Branch 'hugo-archive' eingefroren.

Behalten auf main: content/ (markdown-quelle für publish-skript),
docs/ (specs), static/ (favicons, profilbild), .claude/, LICENSE.

README überarbeitet mit Branch-Übersicht.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 09:51:05 +02:00
Jörg Lohrer 3a5c4d1e00 archive: final hugo build mit neuem post dezentrale-oep-oer
Letzter Commit vor Transition zu nostr-spa. Beinhaltet:
- neuer Post 2025-03-04-dezentrale-oep-oer (content + Hugo-Build)
- aktualisierte public/*.html nach Mastodon-Comment-Entfernung
- .claude/ als Transparenz-Spur der Sessions
- .DS_Store aus Index entfernt (bleibt ignoriert)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 09:49:26 +02:00
Jörg Lohrer 4918175f8b spec: nostr-page auf basis von events — design
SvelteKit-SPA, die Blog-Posts live aus signierten kind:30023-Events
von Public-Relays rendert. Ablösung der Hugo-Seite auf All-Inkl ohne
eigene Infrastruktur in Phase 1; Stubs, eigener Relay und Blossom als
Evolutionspfad.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 09:25:11 +02:00
402 changed files with 651 additions and 17067 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -0,0 +1,13 @@
{
"permissions": {
"allow": [
"WebFetch(domain:hzrd149.github.io)",
"Bash(git add:*)",
"Bash(git commit -m ':*)",
"Bash(git rm:*)",
"Bash(git commit:*)",
"Bash(git checkout:*)",
"Bash(git submodule:*)"
]
}
}

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "themes/tailwind"]
path = themes/tailwind
url = https://github.com/tomowang/hugo-theme-tailwind.git

View File

View File

@ -1,3 +1,34 @@
# joerglohrerde # joerg-lohrer.de
update Persönliche Webseite. Befindet sich in der Transition von einer Hugo-basierten,
statischen Seite hin zu einer SvelteKit-SPA, die Blog-Posts live aus signierten
Nostr-Events (NIP-23, `kind:30023`) rendert.
## Branches
- **`main`** — aktuelle Arbeit. Enthält Markdown-Content (`content/posts/`),
Specs (`docs/`), Assets (`static/`) und wird im Lauf der Migration um die
SvelteKit-SPA und das Publish-Skript erweitert.
- **`spa`** — Feature-Branch für die SvelteKit-SPA-Entwicklung. Wird bei
Cutover nach `main` gemerged.
- **`hugo-archive`** — eingefrorener Zustand der alten Hugo-Seite als
Orphan-Branch (ein Commit ohne Historie). Nicht mehr weiterentwickelt.
Wiederherstellbar über `git checkout hugo-archive && hugo build`.
## Spec
Architektur und Design-Entscheidungen:
[`docs/superpowers/specs/2026-04-15-nostr-page-design.md`](docs/superpowers/specs/2026-04-15-nostr-page-design.md)
## Struktur auf `main`
```
content/posts/ Markdown-Posts (Quelle für Nostr-Events)
static/ Site-Assets (Favicons, Profilbild)
docs/ Specs und Architektur-Dokumentation
.claude/ Claude-Code-Sessions (als Transparenz-Spur)
```
## Lizenz
Siehe [LICENSE](LICENSE).

View File

@ -1,5 +0,0 @@
+++
title = '{{ replace .File.ContentBaseName "-" " " | title }}'
date = {{ .Date }}
draft = true
+++

BIN
assets/.DS_Store vendored

Binary file not shown.

BIN
assets/icons/.DS_Store vendored

Binary file not shown.

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-brand-bluesky"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M6.335 5.144c-1.654 -1.199 -4.335 -2.127 -4.335 .826c0 .59 .35 4.953 .556 5.661c.713 2.463 3.13 2.75 5.444 2.369c-4.045 .665 -4.889 3.208 -2.667 5.41c1.03 1.018 1.913 1.59 2.667 1.59c2 0 3.134 -2.769 3.5 -3.5c.333 -.667 .5 -1.167 .5 -1.5c0 .333 .167 .833 .5 1.5c.366 .731 1.5 3.5 3.5 3.5c.754 0 1.637 -.571 2.667 -1.59c2.222 -2.203 1.378 -4.746 -2.667 -5.41c2.314 .38 4.73 .094 5.444 -2.369c.206 -.708 .556 -5.072 .556 -5.661c0 -2.953 -2.68 -2.025 -4.335 -.826c-2.293 1.662 -4.76 5.048 -5.665 6.856c-.905 -1.808 -3.372 -5.194 -5.665 -6.856z" /></svg>

Before

Width:  |  Height:  |  Size: 847 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-brand-mastodon"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M18.648 15.254c-1.816 1.763 -6.648 1.626 -6.648 1.626a18.262 18.262 0 0 1 -3.288 -.256c1.127 1.985 4.12 2.81 8.982 2.475c-1.945 2.013 -13.598 5.257 -13.668 -7.636l-.026 -1.154c0 -3.036 .023 -4.115 1.352 -5.633c1.671 -1.91 6.648 -1.666 6.648 -1.666s4.977 -.243 6.648 1.667c1.329 1.518 1.352 2.597 1.352 5.633s-.456 4.074 -1.352 4.944z" /><path d="M12 11.204v-2.926c0 -1.258 -.895 -2.278 -2 -2.278s-2 1.02 -2 2.278v4.722m4 -4.722c0 -1.258 .895 -2.278 2 -2.278s2 1.02 2 2.278v4.722" /></svg>

Before

Width:  |  Height:  |  Size: 787 B

View File

@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
class="nostro"
d="m 21.219688,10.632199 v 9.782376 c 0,0.36788 -0.298537,0.666422 -0.666421,0.666422 h -7.997031 c -0.367884,0 -0.666422,-0.298542 -0.666422,-0.666422 v -1.82178 c 0.03645,-2.233152 0.272682,-4.372276 0.768675,-5.34546 0.297363,-0.58532 0.78748,-0.903839 1.350469,-1.074263 1.063686,-0.319694 2.93013,-0.10108 3.722312,-0.138691 0,0 2.392997,0.09521 2.392997,-1.259967 0,-1.0907187 -1.069562,-1.0049187 -1.069562,-1.0049187 -1.178867,0.03055 -2.076831,-0.04937 -2.658626,-0.278557 C 15.421721,9.1077763 15.388811,8.4049219 15.385285,8.1698534 15.337094,5.4548117 11.333878,5.1292411 7.8066742,5.8027121 3.9503743,6.536127 7.8489842,12.063765 7.8489842,19.44257 v 0.984936 c -0.00706,0.362004 -0.299712,0.654662 -0.6640682,0.654662 h -3.95973 c -0.3678829,0 -0.6664195,-0.298534 -0.6664195,-0.666415 V 3.4966903 c 0,-0.3678822 0.2985366,-0.6664194 0.6664195,-0.6664194 h 3.7223109 c 0.3678822,0 0.6664189,0.2985372 0.6664189,0.6664194 0,0.546534 0.6147044,0.8509478 1.0589839,0.5324305 1.3387143,-0.9590801 3.0570663,-1.4703543 4.9799263,-1.4703543 4.307633,0 7.564508,2.5105327 7.564508,8.0734325 z M 14.068901,8.6470424 c 0,-0.7874805 -0.638211,-1.4256909 -1.425691,-1.4256909 -0.787479,0 -1.425692,0.6382104 -1.425692,1.4256909 0,0.7874809 0.638213,1.4256916 1.425692,1.4256916 0.78748,0 1.425691,-0.6382107 1.425691,-1.4256916 z"
id="nostr"
style="fill:currentColor;fill-opacity:1;stroke-width:0.5" />
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

BIN
content/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@ -0,0 +1,135 @@
---
layout: post
title: "Gemeinsam die Bildungszukunft gestalten: Dezentrale OEP und OER als Wegbereiter"
slug: "Gemeinsam die Bildungszukunft gestalten: Dezentrale OEP und OER als Wegbereiter"
description: "Einladung zum offenen Denken und Handeln in der Bildungsgemeinschaft. Der
Beitrag diskutiert, warum eine dezentrale Infrastruktur für Open Educational
Resources (OER) und Open Educational Practices (OEP) notwendig ist, um
nachhaltige, resiliente und interoperable Bildungsräume zu schaffen. Dabei
wird das Potenzial des Nostr-Protokolls für Bildungsnetzwerke beleuchtet"
image: dezentrale-oep-oer.png
cover:
image: dezentrale-oep-oer.png
caption: "Ein in den Sand gezeichneter Strauß mit den Buchstaben 'OER' ein Sinnbild für offene Bildung und freien Wissensaustausch. Die Wortspiel-Verbindung zu 'Nostr' (das dezentralisierte Kommunikationsprotokoll) liegt nahe: 'Nostr' klingt wie ein Teil von 'Ostrich' (Englisch für Strauß). So wie der Ichthys-Fisch einst als geheimes Erkennungszeichen diente, steht dieses Symbol für eine Gemeinschaft, die Wissen offen teilt frei, unabhängig und widerstandsfähig."
alt: "Ein in den Sand gezeichneter Strauß mit den Buchstaben 'OER' ein Sinnbild für offene Bildung und freien Wissensaustausch. Die Wortspiel-Verbindung zu 'Nostr' (das dezentralisierte Kommunikationsprotokoll) liegt nahe: 'Nostr' klingt wie ein Teil von 'Ostrich' (Englisch für Strauß). So wie der Ichthys-Fisch einst als geheimes Erkennungszeichen diente, steht dieses Symbol für eine Gemeinschaft, die Wissen offen teilt frei, unabhängig und widerstandsfähig."
date: 2025-03-04
author:
- Jörg Lohrer
- Steffen Rörtgen
- Bastian Granas
comments:
host: reliverse.social
username: comenius
id: 114104961785328046
tags: [ "Künstliche Intelligenz", "Bewusstsein", "Religionspädagogik", "Community" ]
lang: de
dir: ltr
license: https://creativecommons.org/licenses/by/4.0/deed.de
creator:
- givenName: Jörg
familyName: Lohrer
id: https://orcid.org/0000-0002-9282-0406
type: Person
affiliation:
name: Comenius-Institut
id: https://ror.org/025e8aw85
type: Organization
- givenName: Steffen
familyName: Rörtgen
id: https://orcid.org/0000-0001-6378-2618
type: Person
- givenName: Bastian
familyName: Granas
type: Person
affiliation: ''
keywords:
- OER
- OEP
- Dezentrale Bildung
- Interoperabilität
- Nostr
inLanguage:
- de
about:
- https://w3id.org/kim/hochschulfaechersystematik/n052
- https://w3id.org/kim/hochschulfaechersystematik/n079
- https://w3id.org/kim/hochschulfaechersystematik/n544
learningResourceType:
- https://w3id.org/kim/hcrt/text
- https://w3id.org/kim/hcrt/web_page
educationalLevel:
- https://w3id.org/kim/educationalLevel/level_A
datePublished: '2025-03-04'
---
# Gemeinsam die Bildungszukunft gestalten: Dezentrale OEP und OER als Wegbereiter
*Einladung zum offenen Denken und Handeln in der Bildungsgemeinschaft*
---
### **Warum wir eine neue Perspektive brauchen**
Die aktuelle digitale Bildungslandschaft gleicht einem Flickenteppich isolierter Plattformen, die zwar öffentlich zugänglich, aber jeweils unterschiedlich verortet und mit verschiedenen Laufzeiten finanziert als große Einzelprojekte im digitalen Raum stehen.
Diese „Datensilos“ verhindern nicht nur die Auffindbarkeit von Ressourcen und ihre gemeinschaftliche Weiternutzung, sondern gefährden auch die Nachhaltigkeit offener Bildung: Wenn Fördergelder auslaufen, verschwinden mit den Plattformen nicht nur Materialien sondern auch wertvolle Nutzerinteraktionen wie Kommentare, Sammlungen und auch die kollaborativen Weiterentwicklungen der Bildungsmaterialien aus den Communities.
Doch Bildung sollte resilient sein unabhängig von politischen oder finanziellen Rahmenbedingungen und gewissermaßen auch von der Plattform, auf der man gerade agiert.
Hier setzt die Vision eines **dezentralen Datenraums** an: Statt zentraler Kontrolle verteilt er Daten auf viele Akteure, fördert Interoperabilität sowie Datensouveränität der Nutzer:innen und ermöglicht neue Geschäftsmodelle.
Inspiriert vom Messaging Protokoll "[Nostr](https://nostr.how/de/what-is-nostr)" ursprünglich für zensurresistente soziale Netzwerke entwickelt könnte so eine Infrastruktur entstehen, die Offenheit, Teilhabe und Vernetzung ins Zentrum stellt.
---
### Von OER zu OEP: Offenheit als Haltung
**Open Educational Resources (OER)** als frei verfügbare Bildungsmaterialien sind nur der erste Schritt.
Echte **Open Educational Practices (OEP)** umfassen eine Kultur des Teilens, kollaboratives Lernen und demokratische Bildungsprozesse.
Wie [Kerstin Mayrberger betont, geht es bei OEP im Kern um „Demokratiebildung](https://blog.bildungsserver.de/open-educational-practices-ist-viel-mehr-als-nur-der-einsatz-von-open-educational-resources/)“: Lernende und Lehrende gestalten gemeinsam Inhalte, hinterfragen Strukturen und entwickeln kritisches Denken.
Doch dafür braucht es mehr als nur frei lizenzierte Materialien. Es braucht (freie) Infrastrukturen, die:
1. **Partizipation ermöglichen**: Nutzer:innen behalten die Kontrolle über ihre Daten und Interaktionen.
2. **Resilienz schaffen**: Dezentrale Speicherung verhindert den „Stecker-Ziehen-Effekt“.
3. **Vernetzung fördern**: Plattformübergreifende Zusammenarbeit wird zur Norm, nicht zur Ausnahme.
---
### Wie Nostr die Bildungsinfrastruktur revolutionieren könnte
Die technische Grundlage für vernetzte Bildung sollte also nicht analog zu Systemen entwickelt werden, deren Grundlage ist, Nutzer und Inhalte (oft ökonomisch gewollt) an sich zu binden.
Stattdessen sollte sie strukturell so angelegt sein, die digitale Vernetzung, die wir uns für die Bildung wünschen, bereits grundlegend zu enthalten.
Wir suchen somit nicht nach lokalen Softwarelösungen für die Organisation von OER- und OEP-Communities, sondern nach grundlegenden Technologieansätzen, die diese Anforderungen erfüllen können.
Dadurch rücken neben den Schnittstellenlösungen, die Plattformen entwickeln müssen, um künftig anschlussfähig zu sein, zunehmend die zugrunde liegenden Protokolle für Zusammenarbeit und vernetzte Bildung in den Fokus einer Entwicklung, wenn diese auf Wirkung und Nachhaltigkeit angelegt sein soll.
Das [Nostr-Protokoll](https://nostr.how/de/what-is-nostr) erfüllt diese grundlegenden Anforderungen:
- **Clients & Relays**: Bildungsplattformen agieren als Clients, die mit Relays (dezentralen Servern) verbunden sind. Jede Institution kann eigene Relays betreiben, die Daten synchronisieren ähnlich wie E-Mails über verschiedene Provider versendet werden.
- **Events & Schlüsselpaare**: Lernmaterialien, Kommentare oder Sammlungen werden als „Events“ gespeichert, signiert mit kryptografischen Schlüsseln. So bleibt die Urheberschaft nachvollziehbar, ohne zentrale Autorität.
- **Interoperabilität & Erweiterbarkeit**: Das Protokoll ist modular aufgebaut, sodass verschiedene Eventtypen integriert werden können. So könnten Metadatenstandards wie das [Allgemeine Metadatenprofil (AMB)](https://dini-ag-kim.github.io/amb/latest/) abgebildet werden, um die Publikation und den Konsum von Bildungsmetadaten plattformübergreifend zu erleichtern.
**Beispiel**: Eine Lehrkraft erstellt auf [MUNDO](https://mundo.schule/) eine Merkliste zu „Nachhaltigkeit“. Dieses Event wird via Nostr-Relays an [WirLernenOnline](https://wirlernenonline.de/) übertragen die Liste ist somit auf Relays im Nostr-Netzwerk verfügbar. Selbst wenn MUNDO und WirLernenOnline offline gehen würden, wäre die Merkliste weiterhin verfügbar, da sie nicht auf der Plattform, sondern auf einem (oder mehreren) Relay(s) liegt.
---
### Chancen für Gemeinschaft und Nachhaltigkeit
Ein dezentraler Datenraum fördert nicht nur technische Resilienz, sondern auch neue Formen der Zusammenarbeit:
- **Qualitätssicherung durch Crowdsourcing**: Da Nutzer:innen nicht mehr durch Plattformgrenzen künstlich getrennt werden, können sie übergreifend miteinander und mit Ressourcen interagieren und sich darüber austauschen. Ihr sozialer Graph kann dabei ähnlich dem „Circle of Trust“ der norwegischen [NDLA](https://doi.org/10.25656/01:16993)-Plattform - genutzt werden, um die Relevanz von Ressourcen algorithmisch einzuordnen.
- **Monetarisierung ohne Abhängigkeit**: Services wie Metadaten-Anreicherung oder Premium-Relays (für personalisierte Feeds, zusätzliche Materialien) können monetarisierbar auf dem Protokoll abgebildet werden und könnten zusätzliche Einnahmequellen bieten, während die Infrastruktur gemeinfrei bleibt .
- **Empowerment kleiner Akteure**: Lokale und kleinere Initiativen, die bis heute (2025!) nicht in der Lage sind, sich und ihre Materialien selbst in die öffentliche Bildungsinfrastruktur einzubringen, erhalten erweiterte Möglichkeiten.
---
### Aufruf zum Mitgestalten
Die Umsetzung dieser Vision lebt von der Gemeinschaft. Inspiriert von Projekten wie [ReliLab](https://relilab.org/relilab/) oder [SynLLOER](https://synlloer.blogs.uni-hamburg.de/), laden wir ein:
1. **Erprobt die Dezentralität**: Testet den **Proof of Concept** „[EduFeed](https://www.edufeed.org/)“, der Nostr für Bildungsmetadaten nutzt.
2. **Denkt infrastrukturübergreifend**: Entwickelt OER nicht im Silo, sondern integriert sie in dezentrale Netzwerke.
3. **Engagiert euch politisch**: Fordert Fördergelder für offene Protokolle statt proprietärer Plattformen.
Wie [Niels Winkelmann im Digilog.Blog ](https://digilog.blog/2024/01/08/oep-groesser-denken/)schreibt: „OEP systemisch zu denken ist der Wind in den Segeln für eine Vision offener Bildung“ .
Lasst uns gemeinsam die Segel setzen dezentral, partizipativ und zukunftssicher!
:sailboat: "[for a race we must win](https://www.team-malizia.com/news/the-message-behind-our-slogan-a-race-we-must-win)"

View File

@ -0,0 +1,470 @@
# Nostr-Page auf Basis von Events — Design-Spec
**Datum:** 2026-04-15
**Status:** Entwurf, ausstehende User-Freigabe
**Scope:** Ablösung der Hugo-Seite `joerg-lohrer.de` durch eine SvelteKit-SPA, die Blog-Posts live aus Nostr-Events rendert. Diese Spec beschreibt **nur die SPA und den Event-/URL-Kontrakt**. Publish-Pipeline (Markdown → Event → Relays + Assets-Upload) ist separate Spec.
---
## 1. Gesamtarchitektur
```
Browser JS-loser Client / Bot
│ │
▼ ▼
┌─────────────────────────────┐ ┌───────────────────────────┐
│ All-Inkl (statisches Hosting)│ │ All-Inkl liefert │
│ • index.html (SPA-Shell) │ │ index.html (leere Shell, │
│ • _app/*.js, *.css │ │ kein Post-Inhalt, keine │
│ • .htaccess (SPA-Fallback) │ │ OG-Tags für Posts) │
│ • images/ bzw. Permalink- │ └───────────────────────────┘
│ Pfade für Altbilder │
└──────────────┬──────────────┘
┌─────────────────────────────────────┐
│ Public Nostr-Relays (wss://) │
│ damus.io, nos.lol, nostr.wine, │
│ relay.nostr.band … │
│ (später erweiterbar um eigene) │
└─────────────────────────────────────┘
Publish-Flow (separate Spec, nur Artefakte hier relevant):
Markdown → signiertes kind:30023 Event → Public-Relays
Bilder (Altbestand) → All-Inkl unter Post-Permalink-Pfad
Bilder (neu) → Blossom-Server (Multi-Upload, single URL im Markdown)
```
### Kernprinzipien
- **All-Inkl hostet nur eine statische SPA-Shell** plus Assets: Altbilder (unter Post-Permalink-Pfaden), Site-Icons, `robots.txt`. Kein Post-Body, keine Stubs, kein Backend.
- **Posts existieren als signierte NIP-23-Events auf mehreren Public-Relays.** Die SPA holt sie zur Laufzeit.
- **URL-Struktur bleibt kompatibel zur bestehenden Hugo-Seite.** Backlinks brechen nicht.
- **Minimale eigene Infrastruktur jetzt** (keine eigene Relay-Instanz, kein eigener Blossom-Server). Alles nachrüstbar ohne Bruch.
- **Bewusst akzeptierte Kosten:** kein SEO, keine Social-Previews in Phase 1. Siehe Risiken und Evolutionspfad.
### Kostenübersicht Phase 1
- All-Inkl: unverändert (vorhandener Tarif).
- Public-Relays: 0 €.
- Public-Blossom-Server (nur Neu-Bilder ab Phase 2): 0 €.
- Domain `joerg-lohrer.de`: unverändert.
- **Zusatzkosten: keine.**
---
## 2. URL-Struktur, Routing, Event-Kontrakt
### URL-Schema (kompatibel zur bestehenden Hugo-Struktur)
| URL | Inhalt |
|---|---|
| `/` | SPA-Shell. SPA rendert Startseite (Profilkachel + Post-Liste). |
| `/YYYY/MM/DD/<dtag>.html/` | SPA-Shell (via `.htaccess`-Fallback). SPA-Router extrahiert `<dtag>` und lädt Event. |
| `/archives/` | SPA-Shell, SPA rendert chronologische Liste. |
| `/tag/<name>/` | SPA-Shell, SPA rendert Tag-Filter. |
| `/impressum/` | Statisches HTML (rechtlicher Content, liegt wirklich auf Server). |
| `/YYYY/MM/DD/<dtag>.html/<bildname>` | echte Bilddateien der 18 Altposts, liegen unter dem jeweiligen Post-Permalink. |
| `/favicon.ico`, `/logo.png`, `/robots.txt` | globale Site-Assets. |
**Datum in der URL** dient nur der Backlink-Kompatibilität. Die SPA benötigt zur Event-Abfrage nur den `dtag`; sie fragt Relays mit `kinds:[30023], authors:[<pubkey>], #d:[<dtag>]`. Das Datum ist URL-Dekoration.
### `.htaccess`
```apache
RewriteEngine On
# HTTPS forcieren
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Existierende Datei oder Verzeichnis? Direkt ausliefern (Bilder, _app/*, favicon etc.).
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Alles andere → SPA-Fallback.
RewriteRule ^ /index.html [L]
```
### Event-Kontrakt (NIP-23, `kind:30023`)
Normatives Schema; Publish-Spec muss es einhalten, SPA verlässt sich darauf.
**Pflicht-Tags pro Event:**
- `["d", "<slug>"]` — URL-Slug. Stabiler Identifier über Edits hinweg (replaceable-Semantik).
- `["title", "<post title>"]`
- `["published_at", "<unix-timestamp>"]` — ursprüngliches Veröffentlichungsdatum.
**Empfohlene Tags:**
- `["summary", "<kurzbeschreibung>"]` — genutzt in Listen-Previews.
- `["image", "<url>"]` — Vorschaubild.
- `["t", "<tag>"]` — mehrfach erlaubt, Kategorien/Tags.
**Content:** Markdown. Bilder als Markdown-Syntax mit absoluten URLs.
**Bild-URL-Policy pro Post-Ära:**
- Migrations-Posts (bestehende 18 Posts, 20132024): Bild-URLs auf `joerg-lohrer.de` unter Post-Permalink-Pfad, z. B. `https://joerg-lohrer.de/2023/03/23/gleichnis-vom-saemann.html/bild1.jpeg`. Bilder liegen tatsächlich dort.
- Neue Posts (ab Phase 2): Bild-URLs auf Blossom-Server, z. B. `https://blossom.primal.net/abc123…def.jpeg`. Upload zu 23 Blossom-Servern parallel (BUD-03-Pattern), Markdown referenziert jeweils nur eine URL.
Die SPA unterscheidet die beiden Eras nicht — sie rendert Markdown, der Browser lädt die absolute URL, wo sie auch liegt.
### SPA-Routing
SvelteKit mit `adapter-static`, `ssr: false`, Fallback-Page `index.html`. Routen:
- `/` → Home
- `/[year]/[month]/[day]/[dtag].html/` → PostView (nur `dtag` genutzt)
- `/archives/` → Archives
- `/tag/[name]/` → TagView
- `/impressum/` → eigener Impressum-Pfad (oder statisch außerhalb der SPA)
**Hinweis zum `.html`-Suffix im Routing:** SvelteKit unterstützt statische Dateiendungen in dynamischen Segmenten nicht direkt. Lösung: Entweder den `.html`-Suffix im Parameter-Wert mitbehandeln (`[dtag]` matched den String inklusive `.html`, davon wird beim Auslesen `.html` abgeschnitten) oder den Pfad als Catch-All-Route `[...slug]` aufnehmen und die Teile im Load-Handler selbst parsen. Details in der Implementation.
### Relay-Konfiguration
Fest im Bundle hinterlegte Default-Liste (Konfig-Datei, nicht hartcodiert):
```ts
// src/lib/nostr/config.ts
export const READ_RELAYS = [
'wss://relay.damus.io',
'wss://nos.lol',
'wss://relay.nostr.band',
'wss://nostr.wine',
]
// TODO bei Implementierung: npub1f7jar3qnu269uyx5p0e4v24hqxjnxysxudvujza2ur5ehltvdeqsly2fx9
// in hex decodieren (nip19.decode) und hier eintragen.
export const AUTHOR_PUBKEY_HEX = '<hex wird bei Implementierung aus npub abgeleitet>'
```
Später erweiterbar um eigenen Relay per Konfig-Änderung, kein Code-Umbau.
---
## 3. SPA-Komponenten & Datenfluss
### Stack
- **Framework:** SvelteKit, Adapter `adapter-static`, `ssr: false`, Prerender-Disabled.
- **Nostr-SDK:** `applesauce-relay`, `applesauce-loaders`, `applesauce-signers` (höherstufig, RxJS-basiert, tree-shakable).
- **Markdown-Rendering:** `marked` + `DOMPurify` + `highlight.js` (35 Sprachen registriert).
- **Signing:** NIP-07 (Browser-Extension wie Alby oder nos2x).
### Dateistruktur
```
src/
├── app.html # SPA-Shell <head>-Defaults
├── lib/
│ ├── nostr/
│ │ ├── config.ts # Relays, Pubkey
│ │ ├── pool.ts # RelayPool Singleton (applesauce-relay)
│ │ ├── loaders.ts # loadPostList, loadPost, loadReplies, loadReactions
│ │ ├── signer.ts # NIP-07 Wrapper (applesauce-signers)
│ │ └── outbox.ts # NIP-65 Read-Relay-Resolution für fremde Autoren
│ ├── render/
│ │ ├── markdown.ts # renderMarkdown(md: string): string — SINGLE EXPORT
│ │ └── naddr.ts # nip19.naddrEncode Helper
│ └── components/
│ ├── PostCard.svelte
│ ├── PostView.svelte
│ ├── ReplyList.svelte
│ ├── Reactions.svelte
│ └── ReplyComposer.svelte
└── routes/
├── +layout.svelte
├── +page.svelte
├── archives/+page.svelte
├── tag/[name]/+page.svelte
├── impressum/+page.svelte
└── [year]/[month]/[day]/[dtag=html_extension]/+page.svelte # s. Hinweis unten
```
### Datenfluss: Post-Seite
1. Browser ruft `/2024/01/26/offenheit-das-wesentliche.html/` auf.
2. All-Inkl `.htaccess``/index.html` (Fallback, keine Datei unter dem Pfad).
3. SPA bootet, SvelteKit-Router matcht Route, extrahiert `dtag`.
4. `loadPost(dtag)` fragt via `applesauce-loaders` den `RelayPool` mit Filter `{ kinds:[30023], authors:[PUBKEY], '#d':[dtag] }`.
5. Observable emittiert Event (bei Versionen: neueste gewinnt, replaceable-Semantik via `applesauce`).
6. `renderMarkdown(event.content)` → sanitized HTML → `{@html}` in `PostView`.
7. Parallel: `loadReplies(event)` (kind:1 mit `#a` oder `#e`) und `loadReactions(event)` (kind:7), nonblocking.
### Datenfluss: Home/Archiv
```
loadPostList() → req({ kinds:[30023], authors:[PUBKEY], limit:100 })
→ Observable streamt Events
→ Dedup per d-Tag, sortiert nach published_at desc
→ PostCard-Liste rendert reaktiv
```
### Datenfluss: Kommentar schreiben (NIP-07)
```
ReplyComposer öffnet
→ signer.getPublicKey() # Alby/nos2x prompted ggf.
→ User tippt, klickt Senden
→ Event bauen (kind:1, Tags: ['a', addr], ['e', eventId], ['p', authorPk])
→ signer.signEvent(event) # Extension prompted zur Freigabe
→ pool.publish(writeRelays, signedEvent)
→ bestehende ReplyList-Subscription zeigt Event optimistisch sofort an
```
`writeRelays` kommt bevorzugt aus dem NIP-65-Outbox-Event des Signers; Fallback: `READ_RELAYS`.
### State-Management
RxJS-Observables direkt in Svelte konsumiert:
```svelte
<script>
import { loadPost } from '$lib/nostr/loaders'
export let data
const post$ = loadPost(data.dtag)
</script>
{#if $post$}
<article class="prose">{@html renderMarkdown($post$.content)}</article>
{:else}
<p>Lade …</p>
{/if}
```
Keine separaten Svelte-Stores. Observable ist der Store.
### Fehler- und Loading-Zustände
- **Soft-Timeout 8s:** „noch am Suchen …".
- **Hard-Timeout 15s:** Fallback-Hinweis mit Habla-Deeplink (`https://habla.news/a/<naddr>`).
- **Kein Event gefunden:** 404-Komponente mit Habla-Link.
- **Alle Relays offline:** Banner + Retry-Button.
- **Replies/Reactions:** best-effort, Fehler silently — dürfen die Post-Anzeige nicht blockieren.
### Markdown-Rendering (Isolation für Zukunft)
Alles Rendering-Zeug in `src/lib/render/markdown.ts`. Externer Export genau eine Funktion:
```ts
export function renderMarkdown(md: string): string
```
Kein Import von `marked` oder `DOMPurify` außerhalb dieser Datei. Das macht Austausch (z. B. zu `svelte-markdown`, `markdown-it` oder `unified`) später zu einem lokal begrenzten Refactor.
Implementierung (Skizze):
```ts
import { marked } from 'marked'
import DOMPurify from 'dompurify'
import hljs from 'highlight.js/lib/core'
import javascript from 'highlight.js/lib/languages/javascript'
import bash from 'highlight.js/lib/languages/bash'
hljs.registerLanguage('javascript', javascript)
hljs.registerLanguage('bash', bash)
marked.use({
breaks: true,
gfm: true,
renderer: {
code(code, lang) {
const highlighted = lang && hljs.getLanguage(lang)
? hljs.highlight(code, { language: lang }).value
: hljs.highlightAuto(code).value
return `<pre><code class="hljs language-${lang ?? ''}">${highlighted}</code></pre>`
},
link(href, title, text) {
const internal = href?.startsWith('/') || href?.includes('joerg-lohrer.de')
const attrs = internal ? '' : ' target="_blank" rel="noopener"'
return `<a href="${href}"${attrs}>${text}</a>`
},
},
})
export function renderMarkdown(md: string): string {
const raw = marked.parse(md) as string
return DOMPurify.sanitize(raw, { ADD_ATTR: ['target', 'rel'] })
}
```
### Sicherheit
- **DOMPurify für allen gerenderten Content** — Hauptposts (von dir signiert) und Replies (von Dritten).
- **Pubkey-Whitelist:** PostsLoader filtert strikt auf `authors:[PUBKEY]`. Fremde Events für Hauptinhalte nicht anzeigen. Replies/Reactions explizit ausgenommen, aber sanitized.
- **Privat-Key liegt nie im Bundle, nicht auf All-Inkl, nicht im Browser.** Signieren ausschließlich lokal (Publish-Spec) oder via NIP-07 (Besucher-Kommentare).
### Bundle-Budget
Schätzung gzip:
- SvelteKit Runtime: ~15 KB
- applesauce-relay + -loaders + -signers: ~30 KB
- rxjs (tree-shaken): ~15 KB
- marked + DOMPurify: ~25 KB
- highlight.js Core + 3 Sprachen: ~15 KB
- App-Code: ~10 KB
- **Total: ~110 KB gzip** — vertretbar.
---
## 4. Hosting, Deployment, Migrationspfad
### Hosting bei All-Inkl
Webhosting-Paket, Standardfeatures:
- statische Dateiauslieferung
- `mod_rewrite` (Standard)
- HTTPS (Let's Encrypt inklusive, ggf. schon aktiv)
Keine PHP, kein MySQL, keine Cronjobs, kein Backend.
### Dateistruktur auf Webspace
```
/
├── index.html # SPA-Shell
├── _app/ # SvelteKit-Bundle
├── .htaccess
├── robots.txt
├── favicon.ico
├── impressum/
│ └── index.html # statische HTML-Datei
├── 2024/01/26/offenheit-das-wesentliche.html/
│ ├── bild1.jpeg # Altbilder
│ └── bild2.jpeg
├── 2023/03/23/gleichnis-vom-saemann.html/
│ └── …
└── …
```
### Upload-Mechanik
- **SvelteKit-Bundle:** `npm run build``build/` → rsync/FTP in Webspace-Root. npm-Script `deploy`.
- **Altbilder:** einmalig per rsync aus `content/posts/` an die Permalink-Pfade übertragen.
- **Neue Bilder:** nicht auf All-Inkl (Phase 2, Blossom-Upload via Publish-Spec).
**Credentials:** FTP-Login in `.env` des lokalen Repos, nicht committed.
### Migrationspfad (die 18 bestehenden Posts)
Um Verwechslung mit den „Phasen" im Evolutionspfad (Abschnitt 5) zu vermeiden, werden die Migrationsschritte mit **Schritt AE** bezeichnet.
**Schritt A — Pre-Launch:**
Hugo-Seite bleibt live, nichts anfassen.
**Schritt B — SPA entwickeln:**
Lokal bauen, gegen Public-Relays mit Test-Events validieren.
**Schritt C — Posts als Events publizieren (Publish-Spec):**
Alle 18 `.md` zu `kind:30023` signieren und zu 45 Public-Relays pushen.
`d`-Tag = bisheriger Hugo-Slug; `published_at` = Frontmatter-Datum.
Verifikation: Events in Habla-Client gegenchecken.
**Schritt D — Cutover:**
1. Altbilder in Permalink-Pfade hochladen.
2. SPA-Bundle in Webspace-Root deployen.
3. `index.html` und `.htaccess` ersetzen (alte Hugo-Version wird überschrieben).
4. Alte, nicht mehr benötigte Hugo-Artefakte können bleiben oder gelöscht werden; `.htaccess`-Fallback macht sie harmlos.
**Schritt E — Validierung:**
- Alle 18 URLs im Browser prüfen (Inhalt stimmt, Bilder laden).
- Stichprobenhaft `curl -A "Mozilla/5.0" <url>` → Shell wird ausgeliefert.
- Link auf Mastodon posten → Preview fehlt (erwartet im Minimal-Launch).
**Rollback-Fähigkeit:**
Alter Hugo-`public/`-Stand als ZIP lokal archivieren. Rollback = zurückkopieren.
### URL-Kompatibilität (verifiziert)
Hugo-URL: `https://joerg-lohrer.de/2024/01/26/offenheit-das-wesentliche.html/`
Neu: Pfad existiert nicht als Datei → `.htaccess``/index.html` → SPA routed via `dtag`.
Für externe Links: identische URL, identische Inhaltsanzeige. Backlinks aus Mastodon, Google, Bookmarks funktionieren weiter.
---
## 5. Testing, Risiken, Evolution
### Testing-Strategie
**Unit-Tests (Vitest):**
- `renderMarkdown()`: Input/Output, XSS-Vektoren (`javascript:`-URLs, `<script>` in Content).
- `naddr`-Encoder: Pubkey + Kind + d-Tag → erwarteter Bech32-String.
- URL-Parser: `/2024/01/26/foo.html/``{ dtag: 'foo' }`.
**Integration-Tests:**
- Mock-Relay (in-memory Fake oder `nostr-relay-tray` in Testmodus).
- PostsLoader: mehrere Versionen desselben `d`-Tags → neueste wins.
- Signer: Test-Key signiert, PostLoader ruft ab, Inhalt matcht.
**End-to-End (Playwright):**
- Happy Path: Start → Liste → Klick → Post rendert.
- Deep-Link: `/2024/01/26/offenheit-das-wesentliche.html/` direkt.
- Kommentar mit Mock-NIP-07-Signer.
**Manuelle Tests vor Go-Live:**
- Alle 18 Post-URLs durchklicken, Visual-Parity-Check gegen alte Hugo-Seite.
- `curl`-Tests mit verschiedenen User-Agents.
- Offline-Fall: WLAN aus → Fehlermeldung lesbar, Habla-Fallback verfügbar.
- Reales NIP-07-Kommentar via Alby auf Test-Post.
### Risiken & Mitigationen
| Risiko | Wahrsch. | Auswirkung | Mitigation |
|---|---|---|---|
| Public-Relays alle down | niedrig | hoch | 45 Relays parallel, Timeout-UI, Habla-Fallback |
| Relay löscht Events | niedrig | mittel | Mehrere Relays, bezahltes nostr.wine als Anker |
| Dependency-Break | mittel | hoch | `package-lock.json` committen, `npm ci`, Staging vor Prod |
| `.htaccess` rewritet Bilder irrtümlich | niedrig | mittel | Regel prüft `-f` vor Fallback |
| Google-Rankings brechen | **hoch** | **mittel** | Akzeptiert; Stubs in Phase 3 nachrüstbar |
| Mastodon-Preview leer | **hoch** | **niedrig** | Akzeptiert; Teaser-Text im Toot kompensiert |
| XSS über Reply | niedrig | hoch | DOMPurify ohne Ausnahmen |
| All-Inkl ändert Apache-Config | sehr niedrig | mittel | Support-Ticket, Standard-Feature |
| Privat-Key-Leak | niedrig | **katastrophal** | Key niemals in Repo, Bundle, Server. Evtl. NIP-46 Bunker |
| Reaktions-Spam | mittel | niedrig | Aggregiert anzeigen, Author-Blocklist |
### Nicht Teil dieser Spec
- **Publish-Pipeline** (Signieren, Upload, GitHub Action): separate Spec. Diese Spec definiert nur Event- und URL-Kontrakt.
- **Eigener Relay/Blossom:** Evolutionspfad, nicht jetzt.
- **Impressum-Text:** rechtliche Inhalte, Umsetzung.
- **Visuelles Design:** Orientierung an PaperMod, Details in Implementation.
### Evolutionspfad
**Phase 1 (jetzt):** Minimal-Launch. SPA auf All-Inkl, Public-Relays, Altbilder auf All-Inkl, Kommentare via NIP-07. Kein SEO, keine Social-Previews.
**Phase 2 (nah):** Blossom für neue Bilder (public Blossom-Server, BUD-03-Multi-Upload, eine URL im Markdown). SPA unverändert.
**Phase 3 (bei Bedarf):** Meta-Stubs nachrüsten für SEO/Social-Previews. Publish-Pipeline erweitern, SPA unverändert.
**Phase 4 (ideologisch):** Eigener strfry-Relay (Homeserver oder VPS), zu Publish-Liste und SPA-Read-Liste hinzu.
**Phase 5 (vollständig dezentral):** Eigener Blossom-Server. Neue Posts uploaden dorthin, alte optional migrieren.
Jeder Phasenwechsel: additiv oder lokal begrenzter Refactor, kein Rewrite.
### Success-Kriterien Phase 1
- Alle 18 alten Post-URLs liefern korrekten Inhalt (Visual-Parity, nicht pixelgenau).
- Neuer Post publizieren (Publish-Spec) < 30 s lokal.
- First Contentful Paint < 1,5 s auf Desktop/LAN.
- Time-to-Post-Rendered < 3 s (Shell + Relay + Event + Rendering).
- Lighthouse Accessibility > 90.
- NIP-07-Kommentar funktioniert in Chrome + Firefox mit Alby.
---
## Anhang: Begriffe
- **NIP-23:** Nostr-Langform-Events, `kind:30023`, replaceable per `d`-Tag.
- **NIP-07:** Browser-Extension-Signer-Protokoll (Alby, nos2x, Flamingo).
- **NIP-65:** Outbox-Model, `kind:10002`, definiert Read/Write-Relays pro Autor.
- **naddr:** Bech32-kodierter Pointer auf ein parameterized-replaceable Event (Pubkey + Kind + d-Tag + Relays).
- **Blossom:** Content-addressed Blob-Hosting für Nostr, Dateien über SHA256-Hash adressiert.
- **BUD-03:** Blossom-User-Description-03, Multi-Server-Mirror-Spezifikation.
- **Replaceable Event:** Event, das alte Versionen mit gleichem (Pubkey, Kind, d-Tag) ersetzt. Relays halten nur die neueste Version.

140
hugo.toml
View File

@ -1,140 +0,0 @@
baseURL = 'https://joerg-lohrer.de/'
languageCode = 'de'
defaultContentLanguage = 'de'
title = 'Jörg Lohrer'
theme = 'papermod'
# SEO keywords and description for your site.
keywords = "OER, Religionspädagogik, Bildung, Religion, Hugo"
subtitle = "Jörg Lohrer - Webseite"
[permalinks]
posts = "/:year/:month/:day/:slug.html"
[outputs]
home = [ "HTML", "RSS", "JSON" ]
[menus]
[[menus.main]]
name = 'Home'
pageRef = '/'
weight = 10
[[menus.main]]
name = 'Impressum'
pageRef = '/Impressum'
weight = 30
[[menus.main]]
name = 'Blog'
pageRef = '/archives'
weight = 20
[[menus.main]]
name = 'Mastodon'
pre = '<i class="fa fa-heart"></i>'
url = 'https://reliverse.social/@joerglohrer'
weight = 40
[menus.main.params]
rel = 'external'
[params.header]
logo = "joerg-profil-2024.webp"
[params]
social = true
comments = true
[[params.jsonLD]]
enabled = true
# Konfiguration PaperMod-Theme
[params.profileMode]
enabled = true
title = "Hi 🖖"
subtitle = "Willkommen auf meinem Blog 🤗"
imageUrl = "joerg-profil-2024.webp"
imageTitle = "Mein Profilbild"
imageWidth = 120
imageHeight = 120
[[params.profileMode.buttons]]
name = "Archiv"
url = "/archives"
[[params.profileMode.buttons]]
name = "tag"
url = "/tag"
[[params.socialIcons]]
name = "Mastodon"
url = "https://reliverse.social/@joerglohrer"
[[params.socialIcons]]
name = "email"
url = "mailto:lohrer@comenius?subject=Kontakt%20%C3%BCber%20joerg-lohrer.de&body=Hallo%20J%C3%B6rg,%0D%0A%0D%0Aich%20nehme%20%C3%BCber%20deine%20Webseite%20Kontakt%20mit%20dir%20auf."
[[params.socialIcons]]
name = "linkedin"
url = "https://www.linkedin.com/in/joerglohrer"
[[params.socialIcons]]
name = "rss"
url = "/index.xml"
[[params.socialIcons]]
name = "cv"
url = "/index.json"
# Social Icons Tailwind-Theme
[params.social_media]
[[params.social_media.items]]
enabled = true
title = 'Mastodon'
icon = 'brand-mastodon'
link = 'https://reliverse.social/@joerglohrer'
[[params.social_media.items]]
enabled = true
title = 'nostr'
icon = 'brand-nostr'
link = 'https://nostter.app/npub1f7jar3qnu269uyx5p0e4v24hqxjnxysxudvujza2ur5ehltvdeqsly2fx9'
[[params.social_media.items]]
enabled = true
title = 'Bluesky'
icon = 'brand-bluesky'
link = 'https://bsky.app/profile/joerglohrer.bsky.social'
[[params.social_media.items]]
enabled = true
title = 'Instagram'
icon = 'brand-instagram'
link = 'https://www.instagram.com/joerglohrer'
[taxonomies]
category = "category"
tag = "tag"
series = "series"
[markup.goldmark.renderer]
unsafe = true
[markup.highlight]
noClasses = false
[pwa]
enabled = false
icon = "logo.png" # should be in assets
icon_sizes = [192, 512]
# will be used as the manifest.json file and merge the default one
# https://developer.mozilla.org/en-US/docs/Web/Manifest
# https://web.dev/add-manifest/
[pwa.manifest]
description = "Webseite Jörg Lohrer"

View File

@ -1,191 +0,0 @@
{{ with .Params.comments }}
<section id="comments" class="article-content">
<h2>Kommentare</h2>
<p>Mit einem Mastodon- oder Fediverse-Account kannst du <a href="https://{{ .host }}/@{{ .username }}/{{ .id }}">hier antworten</a></p>
<p id="mastodon-comments-list"><button id="load-comment">Kommentare laden</button></p>
<div id="comments-wrapper">
<noscript><p>Loading comments relies on JavaScript. Try enabling JavaScript and reloading, or visit <a href="https://{{ .host }}/@{{ .username }}/{{ .id }}">the original post</a> on Mastodon.</p></noscript>
</div>
<noscript>You need JavaScript to view the comments.</noscript>
<script src="/js/purify.min.js"></script>
<script type="text/javascript">
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function emojify(input, emojis) {
let output = input;
emojis.forEach(emoji => {
let picture = document.createElement("picture");
let source = document.createElement("source");
source.setAttribute("srcset", escapeHtml(emoji.url));
source.setAttribute("media", "(prefers-reduced-motion: no-preference)");
let img = document.createElement("img");
img.className = "emoji";
img.setAttribute("src", escapeHtml(emoji.static_url));
img.setAttribute("alt", `:${ emoji.shortcode }:`);
img.setAttribute("title", `:${ emoji.shortcode }:`);
img.setAttribute("width", "20");
img.setAttribute("height", "20");
picture.appendChild(source);
picture.appendChild(img);
output = output.replace(`:${ emoji.shortcode }:`, picture.outerHTML);
});
return output;
}
function loadComments() {
let commentsWrapper = document.getElementById("comments-wrapper");
document.getElementById("load-comment").innerHTML = "Loading";
fetch('https://{{ .host }}/api/v1/statuses/{{ .id }}/context')
.then(function(response) {
return response.json();
})
.then(function(data) {
let descendants = data['descendants'];
if(
descendants &&
Array.isArray(descendants) &&
descendants.length > 0
) {
commentsWrapper.innerHTML = "";
descendants.forEach(function(status) {
console.log(descendants)
if( status.account.display_name.length > 0 ) {
status.account.display_name = escapeHtml(status.account.display_name);
status.account.display_name = emojify(status.account.display_name, status.account.emojis);
} else {
status.account.display_name = status.account.username;
};
let instance = "";
if( status.account.acct.includes("@") ) {
instance = status.account.acct.split("@")[1];
} else {
instance = "{{ .host }}";
}
const isReply = status.in_reply_to_id !== "{{ .id }}";
let op = false;
if( status.account.acct == "{{ .username }}" ) {
op = true;
}
status.content = emojify(status.content, status.emojis);
let avatarSource = document.createElement("source");
avatarSource.setAttribute("srcset", escapeHtml(status.account.avatar));
avatarSource.setAttribute("media", "(prefers-reduced-motion: no-preference)");
let avatarImg = document.createElement("img");
avatarImg.className = "avatar";
avatarImg.setAttribute("src", escapeHtml(status.account.avatar_static));
avatarImg.setAttribute("alt", `@${ status.account.username }@${ instance } avatar`);
let avatarPicture = document.createElement("picture");
avatarPicture.appendChild(avatarSource);
avatarPicture.appendChild(avatarImg);
let avatar = document.createElement("a");
avatar.className = "avatar-link";
avatar.setAttribute("href", status.account.url);
avatar.setAttribute("rel", "external nofollow");
avatar.setAttribute("title", `View profile at @${ status.account.username }@${ instance }`);
avatar.appendChild(avatarPicture);
let instanceBadge = document.createElement("a");
instanceBadge.className = "instance";
instanceBadge.setAttribute("href", status.account.url);
instanceBadge.setAttribute("title", `@${ status.account.username }@${ instance }`);
instanceBadge.setAttribute("rel", "external nofollow");
instanceBadge.textContent = instance;
let display = document.createElement("span");
display.className = "display";
display.setAttribute("itemprop", "author");
display.setAttribute("itemtype", "http://schema.org/Person");
display.innerHTML = status.account.display_name;
let header = document.createElement("header");
header.className = "author";
header.appendChild(display);
header.appendChild(instanceBadge);
let permalink = document.createElement("a");
permalink.setAttribute("href", status.url);
permalink.setAttribute("itemprop", "url");
permalink.setAttribute("title", `View comment at ${ instance }`);
permalink.setAttribute("rel", "external nofollow");
permalink.textContent = new Date( status.created_at ).toLocaleString('en-US', {
dateStyle: "long",
timeStyle: "short",
});
let timestamp = document.createElement("time");
timestamp.setAttribute("datetime", status.created_at);
timestamp.appendChild(permalink);
let main = document.createElement("main");
main.setAttribute("itemprop", "text");
main.innerHTML = status.content;
let interactions = document.createElement("footer");
if(status.favourites_count > 0) {
let faves = document.createElement("a");
faves.className = "faves";
faves.setAttribute("href", `${ status.url }/favourites`);
faves.setAttribute("title", `Favorites from ${ instance }`);
faves.textContent = status.favourites_count;
interactions.appendChild(faves);
}
let comment = document.createElement("article");
comment.id = `comment-${ status.id }`;
comment.className = isReply ? "comment comment-reply" : "comment";
comment.setAttribute("itemprop", "comment");
comment.setAttribute("itemtype", "http://schema.org/Comment");
comment.appendChild(avatar);
comment.appendChild(header);
comment.appendChild(timestamp);
comment.appendChild(main);
comment.appendChild(interactions);
if(op === true) {
comment.classList.add("op");
avatar.classList.add("op");
avatar.setAttribute(
"title",
"Blog post author; " + avatar.getAttribute("title")
);
instanceBadge.classList.add("op");
instanceBadge.setAttribute(
"title",
"Blog post author: " + instanceBadge.getAttribute("title")
);
}
commentsWrapper.innerHTML += DOMPurify.sanitize(comment.outerHTML);
});
}
});
}
document.getElementById("load-comment").addEventListener("click", loadComments);
</script>
</section>
{{ end }}

View File

@ -1,242 +0,0 @@
<!DOCTYPE html>
<html lang="de" dir="auto">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>Premium, Freemium, Mium mium mium | Jörg Lohrer</title>
<meta name="keywords" content="OER, Freemium, MOOC">
<meta name="description" content="Zur Produktion von sattmachenden Bildungsinhalten">
<meta name="author" content="Jörg Lohrer">
<link rel="canonical" href="http://localhost:1313/2013/02/07/premium-freemium-mium-mium-mium.html/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.fcb38834b6dee4645dbe7c77d6c5278e12448b758b3f769e48a2d86d35709cb2.css" integrity="sha256-/LOINLbe5GRdvnx31sUnjhJEi3WLP3aeSKLYbTVwnLI=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://localhost:1313/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://localhost:1313/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://localhost:1313/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://localhost:1313/apple-touch-icon.png">
<link rel="mask-icon" href="http://localhost:1313/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="de" href="http://localhost:1313/2013/02/07/premium-freemium-mium-mium-mium.html/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://localhost:1313/" accesskey="h" title="Jörg Lohrer (Alt + H)">Jörg Lohrer</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
<ul class="lang-switch"><li>|</li>
</ul>
</div>
</div>
<ul id="menu">
<li>
<a href="http://localhost:1313/" title="Jörg Lohrer">
<span>Home</span>
</a>
</li>
<li>
<a href="http://localhost:1313/archives/" title="Archive">
<span>Blog</span>
</a>
</li>
<li>
<a href="http://localhost:1313/impressum/" title="Impressum">
<span>Impressum</span>
</a>
</li>
<li>
<a href="https://reliverse.social/@joerglohrer" title="Mastodon">
<span><i class="fa fa-heart"></i>Mastodon</span>&nbsp;
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="12" width="12">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
<path d="M15 3h6v6"></path>
<path d="M10 14L21 3"></path>
</svg>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<h1 class="post-title entry-hint-parent">
Premium, Freemium, Mium mium mium
</h1>
<div class="post-description">
Zur Produktion von sattmachenden Bildungsinhalten
</div>
<div class="post-meta"><span title='2013-02-07 00:00:00 +0000 UTC'>Februar 7, 2013</span>&nbsp;·&nbsp;Jörg Lohrer
</div>
</header>
<figure class="entry-cover">
<img loading="eager" src="http://localhost:1313/2013/02/07/premium-freemium-mium-mium-mium.html/my-very-hungry-caterpillar.jpg" alt="">
</figure>
<div class="post-content"><h1 id="premium-freemium-mium-mium-mium">Premium, Freemium, Mium mium mium<a hidden class="anchor" aria-hidden="true" href="#premium-freemium-mium-mium-mium">#</a></h1>
<p>Wer leckere Bildungsangebote macht, findet immer reichlich Abnehmer. Und im digitalen Zeitalter kann ein einzelnes Produkt dank der vorhandenen Replikatormaschinen unendlich vervielfacht konsumiert werden. Das ist kein Traum mehr, sondern längst cloudgewordene Wirklichkeit.</p>
<p>Nun wird versucht über ein komplexes Rechtemanagement den Produzenten ein lukratives Einkommen zu sichern. Doch während im Dienstleitungssektor der Bildung die einen noch an Vertriebswegen tüfteln, sind die Teilnehmenden in den offenen und massiven Online-Kursen (MOOCs) schon einen Schritt weiter. Hier wird allmählich begriffen, dass nicht die Her- und Bereitstellung, Aufbereitung und didaktische Darbietung von Bildung sich in barer Münze auszahlt, sondern das vernetzende Lernen selbst, also der Prozess, die eigentliche Qualität darstellt, die ihr Geld wirklich wert wäre.</p>
<p>![](my-very-hungry-caterpillar.jpg =240x)
Foto: <a href="https://www.flickr.com/photos/fizzkitten/4454153264/">365.79 My very hungry caterpillar - Relly Annett-Baker</a> <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">CC BY-NC-SA</a></p>
<p>Wo früher noch für ein Produkt bezahlt wurde, wird morgen ein Vorgang monetarisiert werden müssen. Übergangslösungen sind bezahlte Dienstleitungen, Werbeeinblendungen, Freischaltcodes, digitales Rechtemanagement oder Crowdfunding. Insgesamt zeigt sich zugleich, dass Geld immer weniger einen materialisierbaren Gegenwert erhält und sich somit eventuell die Substanz der Währung allmählich aufzulösen beginnt. Doch genausowenig wie man Geld essen kann, wird man von Bildung satt. Die Frage, die sich stellt, ist also keine geringere als die nach einer Kalibrierung der Geldfunktionen.
Gegenseitige Anerkennung, Verlässlichkeit und Loyalität, Kooperation und Ideenreichtum, Unterstützung und Feedback sind im Rahmen eines offenen Online-Kurses ohnehin unbezahlbar und treten verblüffenderweise da am stärksten auf, wo kein Geldtransfer im Spiel ist. Das zeigt einmal mehr, dass man sich die besten Dinge im Leben mit Geld eben gerade nicht kaufen kann.
Doch satt bin ich noch immer nicht.</p>
</div>
<footer class="post-footer">
<ul class="post-tags">
</ul>
</footer>
</article>
</main>
<footer class="footer">
<span>&copy; 2025 <a href="http://localhost:1313/">Jörg Lohrer</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
<a rel="me" href="https://reliverse.social/@joerglohrer">Mastodon</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

View File

@ -1,272 +0,0 @@
<!DOCTYPE html>
<html lang="de" dir="auto">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>Erlebnispädagogik im Handbuch Jugend Evangelische Perspektiven | Jörg Lohrer</title>
<meta name="keywords" content="Erlebnispädagogik, Jugendliche">
<meta name="description" content="Artikel unter CC-BY Lizenz">
<meta name="author" content="Jörg Lohrer">
<link rel="canonical" href="http://localhost:1313/2013/05/29/erlebnispadagogik-im-handbuch-jugend-evangelische-perspektive.html/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.fcb38834b6dee4645dbe7c77d6c5278e12448b758b3f769e48a2d86d35709cb2.css" integrity="sha256-/LOINLbe5GRdvnx31sUnjhJEi3WLP3aeSKLYbTVwnLI=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://localhost:1313/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://localhost:1313/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://localhost:1313/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://localhost:1313/apple-touch-icon.png">
<link rel="mask-icon" href="http://localhost:1313/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="de" href="http://localhost:1313/2013/05/29/erlebnispadagogik-im-handbuch-jugend-evangelische-perspektive.html/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://localhost:1313/" accesskey="h" title="Jörg Lohrer (Alt + H)">Jörg Lohrer</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
<ul class="lang-switch"><li>|</li>
</ul>
</div>
</div>
<ul id="menu">
<li>
<a href="http://localhost:1313/" title="Jörg Lohrer">
<span>Home</span>
</a>
</li>
<li>
<a href="http://localhost:1313/archives/" title="Archive">
<span>Blog</span>
</a>
</li>
<li>
<a href="http://localhost:1313/impressum/" title="Impressum">
<span>Impressum</span>
</a>
</li>
<li>
<a href="https://reliverse.social/@joerglohrer" title="Mastodon">
<span><i class="fa fa-heart"></i>Mastodon</span>&nbsp;
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="12" width="12">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
<path d="M15 3h6v6"></path>
<path d="M10 14L21 3"></path>
</svg>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<h1 class="post-title entry-hint-parent">
Erlebnispädagogik im Handbuch Jugend Evangelische Perspektiven
</h1>
<div class="post-description">
Artikel unter CC-BY Lizenz
</div>
<div class="post-meta"><span title='2013-05-29 00:00:00 +0000 UTC'>Mai 29, 2013</span>&nbsp;·&nbsp;Jörg Lohrer
</div>
</header>
<div class="post-content"><h1 id="erlebnispädagogik-im-handbuch-jugend--evangelische-perspektiven">Erlebnispädagogik im Handbuch Jugend Evangelische Perspektiven<a hidden class="anchor" aria-hidden="true" href="#erlebnispädagogik-im-handbuch-jugend--evangelische-perspektiven">#</a></h1>
<p>Das
<a href="http://ci-muenster.de/bookshop/artikel/buecher/Bildung-im-Kindes-und-Jugendalter/A40097_Handbuch_Jugend_2013.php"><img loading="lazy" src="http://ws.assoc-amazon.de/widgets/q?_encoding=UTF8&amp;ASIN=3847400746&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=DE&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=httpwwwjoergl-21" alt="" />
</a>
<strong>Handbuch Jugend Evangelische Perspektiven</strong>, welches 2013 erschienen ist, hat auf Seite 343-345 folgenden Artikel von mir zur Erlebnispädagogik abgedruckt.
<a href="http://creativecommons.org/licenses/by/2.0/de/">CC BY</a> Jörg Lohrer</p>
<h2 id="erlebnispädagogik">Erlebnispädagogik<a hidden class="anchor" aria-hidden="true" href="#erlebnispädagogik">#</a></h2>
<h3 id="ziele-und-arbeitsformen">Ziele und Arbeitsformen<a hidden class="anchor" aria-hidden="true" href="#ziele-und-arbeitsformen">#</a></h3>
<p>Erlebnispädagogik arbeitet mit einem pädagogischen Konzept zielorientiert und bevorzugt in der Natur oder dem naturnahen Raum vorrangig an der Förderung von Selbst- und Sozialkompetenzen. Dabei grenzt sich Erlebnispädagogik bewusst von Nervenkitzel-Aktionismus und der eskalierenden Suche nach dem Kick nach immer mehr und phantastischeren Erlebnissen ab. Die Förderung von Zutrauen in die eigenen Fähigkeiten, der Umgang mit Ängsten, das Erfahren und Überwinden von Grenzen, die Vemittlung von sozialen Kompetenzen können Zielsetzungen für erlebnispädagogische Maßnahmen in der evangelischen Jugendbildung sein. Dabei geht es auch immer um eine Erweiterung der eigenen Handlungskompetenzen zur Lebensbewältigung durch ein angstfreies Lernen in der Gruppe.</p>
<p>Erlebnispädagogik arbeitet mit Wahrnehmungs- und Vertrauensübungen, Kooperations- und Problemlösungsaufgaben, abenteuerlichen Aktionen, persönlichen Herausforderungen und Grenzerfahrungen. Angebote und Maßnahmen mit erlebnispädagogischem Charakter sind zum Beispiel Kanu- und Fahrrad-Touren, Kletteraktionen, kooperative Abenteuerspiele, Natursensibilisierung, Trekkingtouren, Nieder- und Hochseilparcours oder Geocaching.</p>
<p>Erlebnispädagogische Maßnahmen finden u.a. Anwendung im Bereich der Kooperation von Jugendverbandsarbeit und Schule, bei Klassenfahrten, der Präventionsarbeit, bei gruppendynamischen Prozessen, Mitarbeiterschulungen, der Entwicklung von Teamarbeit und in etlichen weiteren Praxisfeldern evangelischer Jugendbildung.</p>
<p>Mit den Arbeitsprinzipien Respekt, Selbstbestimmung, Vertrauen, Kooperation, Verantwortung und Ganzheitlichkeit korrespondiert die Erlebnispädagogik mit dem Profil der evangelischen Jugendarbeit. Ebenso liegen Chancen in einer Verknüpfung von erlebnispädagogischen Aktionen mit einer erfahrungsbezogenen Verkündigung. Erlebnispädagogische Maßnahmen werden als Jugendbildungsveranstaltungen gefördert, wenn sozial-ökologische Inhalte und/oder politisch-kulturelle Schwerpunktthemen mit gesellschaftlichem Bezug im Mittelpunkt der Maßnahme stehen.</p>
<h3 id="entstehung-prinzipien-methoden">Entstehung, Prinzipien, Methoden<a hidden class="anchor" aria-hidden="true" href="#entstehung-prinzipien-methoden">#</a></h3>
<p>Der Bundesverband Individual- und Erlebnispädagogik e.V. (BE) nennt weit in die Vergangenheit zurück reichende Wurzeln der Erlebnispädagogik. Als wichtige Autoren, auf die das Konzept vom handlungsorientierten Lernen zurückgeführt wird, werden Platon (427347 v.Chr.), Rousseau (17121778), Pestalozzi (17461827) und schließ- lich Kurt Hahn (18861974) als Urvater der Erlebnispädagogik genannt. Ihre heutige Vielfalt und weite Verbreitung hat die Erlebnispädagogik allerdings erst im 20. Jahrhundert und schließlich in den letzten Jahrzehnten entwickelt. Erlebnispädagogik wird nicht nur im Bereich der Erziehung von Kindern und Jugendlichen angewandt, sondern findet inzwischen auch vielfältige Beachtung in der Arbeit mit nahezu allen Altersgruppen zu unterschiedlichen Problem- und Zielstellungen in der präventiven Kurzzeitpädagogik, der intensiven sozialpädagogischen Einzelbetreuung, im Rahmen der beruflichen Fort und Weiterbildung oder in Führungskräftetrainings (vgl. <a href="https://www.bundesverband-erlebnispaedagogik.de/">www.bundesverband- erlebnispaedagogik.de</a>).</p>
<p>Als Grundprinzipien können unter anderem benannt werden: Handlungsorientierung, Ganzheitlichkeit, Eigenverantwortung, Freiwilligkeit, Sicherheit und Nachhaltig- keit. Dabei sind die pädagogischen, kompetenz- und ressourcenorientierten Angebote der Erlebnispädagogik stets eingebettet in die aktuelle Rechtsgrundlage und (Bildungs-) Politik.</p>
<p>Methodische Aspekte sind z.B.: der hohe Stellenwert des Erlebnisses und das Arbeiten mit erlebnispädagogischen Lernszenarien, nicht-alltäglichen Herausforderungen und Wagnissen, Einsatz verschiedener Medien und der Natur als bevorzugtem Lern- und Erfahrungsraum.
Neben einer zunehmende Gruppenselbststeuerung baut die Erlebnispädagogik auf Lern- und Wirkungsmodelle wie das Komfortzonenmodell, das metaphorische Modell, Aktions- und Reflexionswelle oder das FlowModell.
Erlebnispädagogik hat als Lernszenariotechnik zwar eine eigene Strukturlogik, dient jedoch ebenso als Methode im nicht genuin erlebnispädagogischen Kontext und entwickelt somit Reichweite, Relevanz und pädagogische Innovationskraft in Konfirmandenarbeit, Religionsunterricht und Gemeindepädagogik.</p>
<h3 id="aktuelle-fragestellungen-und-entwicklungsperspektiven-qualität-und-wirkung">Aktuelle Fragestellungen und Entwicklungsperspektiven: Qualität und Wirkung<a hidden class="anchor" aria-hidden="true" href="#aktuelle-fragestellungen-und-entwicklungsperspektiven-qualität-und-wirkung">#</a></h3>
<p>Als partizipatorisches Angebot setzt die Erlebnispädagogik auf das Prinzip der Freiwilligkeit und der selbstbestimmten Teilnahme. Unter dem Motto challenge by choice hat eine subjektorientierte Erlebnispädagogik stets zu gewährleisten, dass die Teilnehmenden den Grad ihrer Beteiligung und Verantwortungsübernahme selbst bestimmen können. Reiserechtliche Bestimmungen, Versicherung und Haftung sind daher aktuell handlungsleitendend bei der Erstellung von erlebnispädagogischen Angeboten und Konzeptionen. Hier gab es in den letzten Jahren zahlreiche Entwicklungen, die eine Qualitätssicherung der Mitarbeitendenbildung in Pädagogik und Sicherheitstechnik hinsichtlich geltender Kriterien voraussetzen und notwendig machen. Entsprechende Zusatzqualifikationen sollten daher immer mindestens durch die jeweiligen Fachsportverbände zertifizierbar sein. Mit dem <a href="https://www.bundesverband-erlebnispaedagogik.de/qualitaet/beq-qualitaetssiegel.html">Gütesiegel „Qualität erlebnispädagogischer Programme und Angebote Mit Sicherheit pädagogisch!“ (beQ)</a> hat der Bundesverband Individual- und Erlebnispädagogik e.V. (BE) ein Zertifizierungsverfahren entwickelt, das ein bundeseinheitliches Qualitätsmanagement fördern will.</p>
<p>Die Wirkungsforschung erlebnispädagogischer Lernarrangements untersucht deren Substanz, Akzeptanz und Nachhaltigkeit hinsichtlich ihrer Qualität von Konzept, Struktur, Prozess und Ergebnis. Studien konnten bislang Indizien für Impulse zur Kompetenzentwicklung nachweisen, die wissenschaftliche Evaluation gestaltet sich jedoch genauso komplex wie das Spektrum der erlebnispädagogischen Handlungsfelder und so fehlt es bislang an validen Studien, die das Wirkungspotenzial eindeutig beschreiben können.</p>
<p>Im Kontext evangelischer Jugendbildung stellt sich bei der Verwendung erlebnispädagogischer Methoden immer auch die Frage nach einer Verknüpfung von christlichen Inhalten mit der handlungsorientierten Pädagogik. Die Assoziation von Natur und Schöpfung ist beispielsweise ebenso naheliegend wie die Reflexion von religiösen Erfahrungen in erlebnispädagogischen Lernsettings. Inwiefern sich dabei Unverfügbares inszenieren lässt, bleibt dabei ebenso eine Herausforderung, wie bei der oben beschriebenen Wirkungsforschung. In den vergangenen Jahren haben sich einige Konzepte zur Erprobung erlebnispädagogischer Methoden im christlichen Kontext entwickelt, die zunehmend auch theologisch und religionsdidaktisch reflektiert werden. Eine überregionale Organisation dieser Einzelinitiativen auf Bundesebene wäre der nächste Schritt hin zu einem evangelischen Profil erlebnispädagogischer Jugendbildungsarbeit.</p>
<h3 id="literatur">Literatur<a hidden class="anchor" aria-hidden="true" href="#literatur">#</a></h3>
<p><img loading="lazy" src="http://ws.assoc-amazon.de/widgets/q?_encoding=UTF8&amp;ASIN=3866870493&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=DE&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=httpwwwjoergl-21" alt="" />
Großer, Achim/Oberländer, Rainer/Lohrer, Jörg/Wiedmayer, Jörg (2005/2011): Sinn gesucht Gott erfahren. Erlebnispädagogik im christlichen Kontext (Band 1 (2005)/Band 2 (2011)). Stuttgart: Buch und Musik.
<img loading="lazy" src="http://ws.assoc-amazon.de/widgets/q?_encoding=UTF8&amp;ASIN=3497022934&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=DE&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=httpwwwjoergl-21" alt="" />
Heckmair, Bernd/Michl, Werner (2008): Erleben und Lernen. Einführung in die Erlebnispädagogik. München: Reinhardt.
<img loading="lazy" src="http://ws.assoc-amazon.de/widgets/q?_encoding=UTF8&amp;ASIN=3940562866&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=DE&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=httpwwwjoergl-21" alt="" />
Reiners, Annette (2007): Praktische Erlebnispädagogik. Augsburg: ZIEL.
<img loading="lazy" src="http://ws.assoc-amazon.de/widgets/q?_encoding=UTF8&amp;ASIN=3936369348&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=DE&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=httpwwwjoergl-21" alt="" />
Pum, Viktoria/Pirner, Manfred L./Lohrer, Jörg (Hrsg.) (2011): Erlebnispädagogik im christlichen Kontext. Dokumentation einer Tagung der Evangelischen Akademie Bad Boll, 2. bis 4. März 2009. Bad Boll: Evangelische Akademie.</p>
<h4 id="links">Links<a hidden class="anchor" aria-hidden="true" href="#links">#</a></h4>
<ul>
<li>Bundesverband Individual- und Erlebnispädagogik e.V. (BE): <a href="https://www.bundesverband-erlebnispaedagogik.de/">https://www.bundesverband-erlebnispaedagogik.de/</a></li>
<li>Fachportal für Erlebnispädagogik im christlichen Kontext des Evangelischen Jugendwerks in Württemberg: <a href="https://www.ejwue.de/arbeitsbereiche/erlebnispaedagogik/">https://www.ejwue.de/arbeitsbereiche/erlebnispaedagogik/</a></li>
<li>Informationsdienst Erlebnispädagogik mit Literaturliste: <a href="http://erlebnispaedagogik.de/">http://erlebnispaedagogik.de/</a></li>
<li>Bundesweite Klassenfahrten, Aus- und Weiterbildungsangebote der Gesellschaft zur Förderung der Erlebnispädagogik (GFE): <a href="https://www.erlebnistage.de/">https://www.erlebnistage.de/</a></li>
</ul>
</div>
<footer class="post-footer">
<ul class="post-tags">
</ul>
</footer>
</article>
</main>
<footer class="footer">
<span>&copy; 2025 <a href="http://localhost:1313/">Jörg Lohrer</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
<a rel="me" href="https://reliverse.social/@joerglohrer">Mastodon</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>

View File

@ -1,248 +0,0 @@
<!DOCTYPE html>
<html lang="de" dir="auto">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>Telegram Bot für Octopi | Jörg Lohrer</title>
<meta name="keywords" content="Telegram, Octopi, Raspberry, 3DDruck">
<meta name="description" content="Schnittstelle zwischen Telegram und OctoPrint">
<meta name="author" content="Jörg Lohrer">
<link rel="canonical" href="http://localhost:1313/2017/10/23/telegram-octopi.html/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.fcb38834b6dee4645dbe7c77d6c5278e12448b758b3f769e48a2d86d35709cb2.css" integrity="sha256-/LOINLbe5GRdvnx31sUnjhJEi3WLP3aeSKLYbTVwnLI=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://localhost:1313/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://localhost:1313/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://localhost:1313/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://localhost:1313/apple-touch-icon.png">
<link rel="mask-icon" href="http://localhost:1313/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="de" href="http://localhost:1313/2017/10/23/telegram-octopi.html/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://localhost:1313/" accesskey="h" title="Jörg Lohrer (Alt + H)">Jörg Lohrer</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
<ul class="lang-switch"><li>|</li>
</ul>
</div>
</div>
<ul id="menu">
<li>
<a href="http://localhost:1313/" title="Jörg Lohrer">
<span>Home</span>
</a>
</li>
<li>
<a href="http://localhost:1313/archives/" title="Archive">
<span>Blog</span>
</a>
</li>
<li>
<a href="http://localhost:1313/impressum/" title="Impressum">
<span>Impressum</span>
</a>
</li>
<li>
<a href="https://reliverse.social/@joerglohrer" title="Mastodon">
<span><i class="fa fa-heart"></i>Mastodon</span>&nbsp;
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="12" width="12">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
<path d="M15 3h6v6"></path>
<path d="M10 14L21 3"></path>
</svg>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<h1 class="post-title entry-hint-parent">
Telegram Bot für Octopi
</h1>
<div class="post-description">
Schnittstelle zwischen Telegram und OctoPrint
</div>
<div class="post-meta"><span title='2017-10-23 00:00:00 +0000 UTC'>Oktober 23, 2017</span>&nbsp;·&nbsp;Jörg Lohrer
</div>
</header>
<figure class="entry-cover">
<img loading="eager" src="http://localhost:1313/2017/10/23/telegram-octopi.html/octopi1.png" alt="">
</figure>
<div class="post-content"><p>Das <a href="http://plugins.octoprint.org/plugins/telegram/">OctoPrint-Telegram-Plugin</a> schafft eine Schnittstelle zwischen Telegram und OctoPrint.
Hier die Anleitung auf Englisch: <a href="https://github.com/fabianonline/OctoPrint-Telegram/blob/stable/README.md">https://github.com/fabianonline/OctoPrint-Telegram/blob/stable/README.md</a></p>
<p>Das dauert eine Weile:
<img loading="lazy" src="octopi1.png" alt="" />
</p>
<p>Token eingeben:
<img loading="lazy" src="octopi2.png" alt="" />
</p>
<p>Heisst aber nicht, dass jetzt alles gleich klappt:
<img loading="lazy" src="octopi3.png" alt="" />
</p>
<p>Es müssen dem Benutzer noch die Rechte “Command” und “Notify” gegeben werden:
<img loading="lazy" src="octopi4.png" alt="" />
</p>
</div>
<footer class="post-footer">
<ul class="post-tags">
</ul>
</footer>
</article>
</main>
<footer class="footer">
<span>&copy; 2025 <a href="http://localhost:1313/">Jörg Lohrer</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
<a rel="me" href="https://reliverse.social/@joerglohrer">Mastodon</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

View File

@ -1,262 +0,0 @@
<!DOCTYPE html>
<html lang="de" dir="auto">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>Lutherkürbis - Reformation an Halloween | Jörg Lohrer</title>
<meta name="keywords" content="Lutherrose, Reformation, Halloween, Luther">
<meta name="description" content="Schablone und Bastelanleitung für einen Kürbis zur Reformation">
<meta name="author" content="Jörg Lohrer">
<link rel="canonical" href="http://localhost:1313/2017/10/31/lutherkuerbis.html/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.fcb38834b6dee4645dbe7c77d6c5278e12448b758b3f769e48a2d86d35709cb2.css" integrity="sha256-/LOINLbe5GRdvnx31sUnjhJEi3WLP3aeSKLYbTVwnLI=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://localhost:1313/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://localhost:1313/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://localhost:1313/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://localhost:1313/apple-touch-icon.png">
<link rel="mask-icon" href="http://localhost:1313/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="de" href="http://localhost:1313/2017/10/31/lutherkuerbis.html/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://localhost:1313/" accesskey="h" title="Jörg Lohrer (Alt + H)">Jörg Lohrer</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
<ul class="lang-switch"><li>|</li>
</ul>
</div>
</div>
<ul id="menu">
<li>
<a href="http://localhost:1313/" title="Jörg Lohrer">
<span>Home</span>
</a>
</li>
<li>
<a href="http://localhost:1313/archives/" title="Archive">
<span>Blog</span>
</a>
</li>
<li>
<a href="http://localhost:1313/impressum/" title="Impressum">
<span>Impressum</span>
</a>
</li>
<li>
<a href="https://reliverse.social/@joerglohrer" title="Mastodon">
<span><i class="fa fa-heart"></i>Mastodon</span>&nbsp;
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="12" width="12">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
<path d="M15 3h6v6"></path>
<path d="M10 14L21 3"></path>
</svg>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<h1 class="post-title entry-hint-parent">
Lutherkürbis - Reformation an Halloween
</h1>
<div class="post-description">
Schablone und Bastelanleitung für einen Kürbis zur Reformation
</div>
<div class="post-meta"><span title='2017-10-31 00:00:00 +0000 UTC'>Oktober 31, 2017</span>&nbsp;·&nbsp;Jörg Lohrer
</div>
</header>
<figure class="entry-cover">
<img loading="eager" src="http://localhost:1313/2017/10/31/lutherkuerbis.html/kuerbis-titelbild.jpg" alt="">
</figure>
<div class="post-content"><h1 id="lutherkürbis---reformation-an-halloween">Lutherkürbis - Reformation an Halloween<a hidden class="anchor" aria-hidden="true" href="#lutherkürbis---reformation-an-halloween">#</a></h1>
<p>Das Symbol der Lutherrose ist auch heute noch in vielen Wappen enthalten und wird als Dekoelement genutzt (<a href="https://www.t-online.de/leben/familie/id_65982142/lutherrose-entstehung-und-bedeutung.html">Quelle: epd/imago</a>)</p>
<p>Aus einer <a href="https://duckduckgo.com/?q=lutherrose&amp;t=h_&amp;iax=images&amp;ia=images">Fotovorlage der Lutherrose</a> wird mit einem <a href="https://image.online-convert.com/convert-to-svg">Online-Konverter eine Schablone als verlustfrei skalierbare Vektorgrafik</a> erzeugt:</p>
<p><a href="https://material.rpi-virtuell.de/wp-content/uploads/2018/10/Lutherrose.pdf"><img loading="lazy" src="lutherrose.png" alt="" />
</a>
<a href="https://material.rpi-virtuell.de/wp-content/uploads/2018/10/Lutherrose.pdf">Lutherrose PDF-Vorlage</a></p>
<h2 id="bastel-anleitung">Bastel-Anleitung<a hidden class="anchor" aria-hidden="true" href="#bastel-anleitung">#</a></h2>
<p>Einen Kürbis aufschneiden:
<img loading="lazy" src="kuerbis-aufschneiden.jpg" alt="" />
</p>
<p>entkernen und aushöhlen:
<img loading="lazy" src="kuerbis-entkernen.jpg" alt="" />
</p>
<p>Schablone aufbringen:
<img loading="lazy" src="schablone-aufbringen.jpg" alt="" />
</p>
<p>Ausschneiden:
<img loading="lazy" src="kuerbis-ausschneiden.jpg" alt="" />
</p>
<p>Mit Kerze oder elektrischem Licht ausstatten:
<img loading="lazy" src="kuerbis-titelbild.jpg" alt="" />
</p>
<p>Fertig!</p>
<p>Diese Idee inklusive der Schablone steht unter <a href="https://creativecommons.org/publicdomain/zero/1.0/deed.de">CC0-Lizenz</a>. Du darfst das Werk kopieren, verändern, verbreiten und aufführen, sogar zu kommerziellen Zwecken, ohne um weitere Erlaubnis bitten zu müssen.</p>
<h4 id="weitere-quellen">Weitere Quellen<a hidden class="anchor" aria-hidden="true" href="#weitere-quellen">#</a></h4>
<ul>
<li>How to Make a Paper Cut-Out Luther Rose <a href="https://www.youtube.com/watch?v=b5FCaNZPU98">YouTube</a> | <a href="http://www.kellyklages.com/lutherrose.pdf">PDF</a></li>
</ul>
</div>
<footer class="post-footer">
<ul class="post-tags">
</ul>
</footer>
</article>
</main>
<footer class="footer">
<span>&copy; 2025 <a href="http://localhost:1313/">Jörg Lohrer</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
<a rel="me" href="https://reliverse.social/@joerglohrer">Mastodon</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 MiB

View File

@ -1,246 +0,0 @@
<!DOCTYPE html>
<html lang="de" dir="auto">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>Pflanzenschild mit QR-Code | Jörg Lohrer</title>
<meta name="keywords" content="QR-Code, 3DDruck">
<meta name="description" content="Mit einem QR-Code-Generator lassen sich verlustfrei skalierbare Vektorgrafiken (SVG) erstellen">
<meta name="author" content="Jörg Lohrer">
<link rel="canonical" href="http://localhost:1313/2019/03/26/pflanzenschild-qr-code.html/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.fcb38834b6dee4645dbe7c77d6c5278e12448b758b3f769e48a2d86d35709cb2.css" integrity="sha256-/LOINLbe5GRdvnx31sUnjhJEi3WLP3aeSKLYbTVwnLI=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://localhost:1313/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://localhost:1313/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://localhost:1313/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://localhost:1313/apple-touch-icon.png">
<link rel="mask-icon" href="http://localhost:1313/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="de" href="http://localhost:1313/2019/03/26/pflanzenschild-qr-code.html/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://localhost:1313/" accesskey="h" title="Jörg Lohrer (Alt + H)">Jörg Lohrer</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
<ul class="lang-switch"><li>|</li>
</ul>
</div>
</div>
<ul id="menu">
<li>
<a href="http://localhost:1313/" title="Jörg Lohrer">
<span>Home</span>
</a>
</li>
<li>
<a href="http://localhost:1313/archives/" title="Archive">
<span>Blog</span>
</a>
</li>
<li>
<a href="http://localhost:1313/impressum/" title="Impressum">
<span>Impressum</span>
</a>
</li>
<li>
<a href="https://reliverse.social/@joerglohrer" title="Mastodon">
<span><i class="fa fa-heart"></i>Mastodon</span>&nbsp;
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="12" width="12">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
<path d="M15 3h6v6"></path>
<path d="M10 14L21 3"></path>
</svg>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<h1 class="post-title entry-hint-parent">
Pflanzenschild mit QR-Code
</h1>
<div class="post-description">
Mit einem QR-Code-Generator lassen sich verlustfrei skalierbare Vektorgrafiken (SVG) erstellen
</div>
<div class="post-meta"><span title='2019-03-26 00:00:00 +0000 UTC'>März 26, 2019</span>&nbsp;·&nbsp;Jörg Lohrer
</div>
</header>
<figure class="entry-cover">
<img loading="eager" src="http://localhost:1313/2019/03/26/pflanzenschild-qr-code.html/cura-plugin-change-filment-at-z.png" alt="">
</figure>
<div class="post-content"><h1 id="pflanzenschild-mit-qr-code">Pflanzenschild mit QR-Code<a hidden class="anchor" aria-hidden="true" href="#pflanzenschild-mit-qr-code">#</a></h1>
<p>Mit einem QR-Code-Generator lassen sich verlustfrei skalierbare Vektorgrafiken (SVG) erstellen:
<a href="https://keremerkan.net/qr-code-and-2d-code-generator/"></a></p>
<p>Dann noch mit Thingiverse ein Dreieck designen (80x40x1.4mm) und den QR-Code obendrauf:
<a href="https://www.tinkercad.com/embed/dcnCyqLFX1P?editbtn=1"></a></p>
<p>Mit dem Cura-Plugin <a href="https://www.thingiverse.com/thing:2077884/#files">Change Filament at Z</a> den 3D-Druck im Layer unterbrechen, wo ein Filament(Farb)-Wechsel stattfinden soll:
<img loading="lazy" src="cura-plugin-change-filment-at-z.png" alt="" />
</p>
<p>Et voilà:
<a href="https://twitter.com/joerglohrer/status/1110580168035176449"></a>
<img loading="lazy" src="qr-code-pflanzenschild.jpg" alt="" />
</p>
</div>
<footer class="post-footer">
<ul class="post-tags">
</ul>
</footer>
</article>
</main>
<footer class="footer">
<span>&copy; 2025 <a href="http://localhost:1313/">Jörg Lohrer</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
<a rel="me" href="https://reliverse.social/@joerglohrer">Mastodon</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 446 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

View File

@ -1,472 +0,0 @@
<!DOCTYPE html>
<html lang="de" dir="auto">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>VR - Virtual Reality | Jörg Lohrer</title>
<meta name="keywords" content="Immersion, Präsenz, Virtuelle Realität, Sidequest, Oculus, Meta">
<meta name="description" content="Tutorials der Oculus Quest 2">
<meta name="author" content="Jörg Lohrer">
<link rel="canonical" href="http://localhost:1313/2021/08/15/virtual-reality.html/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.fcb38834b6dee4645dbe7c77d6c5278e12448b758b3f769e48a2d86d35709cb2.css" integrity="sha256-/LOINLbe5GRdvnx31sUnjhJEi3WLP3aeSKLYbTVwnLI=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://localhost:1313/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://localhost:1313/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://localhost:1313/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://localhost:1313/apple-touch-icon.png">
<link rel="mask-icon" href="http://localhost:1313/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="de" href="http://localhost:1313/2021/08/15/virtual-reality.html/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://localhost:1313/" accesskey="h" title="Jörg Lohrer (Alt + H)">Jörg Lohrer</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
<ul class="lang-switch"><li>|</li>
</ul>
</div>
</div>
<ul id="menu">
<li>
<a href="http://localhost:1313/" title="Jörg Lohrer">
<span>Home</span>
</a>
</li>
<li>
<a href="http://localhost:1313/archives/" title="Archive">
<span>Blog</span>
</a>
</li>
<li>
<a href="http://localhost:1313/impressum/" title="Impressum">
<span>Impressum</span>
</a>
</li>
<li>
<a href="https://reliverse.social/@joerglohrer" title="Mastodon">
<span><i class="fa fa-heart"></i>Mastodon</span>&nbsp;
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="12" width="12">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
<path d="M15 3h6v6"></path>
<path d="M10 14L21 3"></path>
</svg>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<h1 class="post-title entry-hint-parent">
VR - Virtual Reality
</h1>
<div class="post-description">
Tutorials der Oculus Quest 2
</div>
<div class="post-meta"><span title='2021-08-15 00:00:00 +0000 UTC'>August 15, 2021</span>&nbsp;·&nbsp;Jörg Lohrer
</div>
</header>
<figure class="entry-cover">
<img loading="eager" src="http://localhost:1313/2021/08/15/virtual-reality.html/04-aframe.jpg" alt="">
</figure>
<div class="post-content"><h1 id="vr---virtual-reality">VR - Virtual Reality<a hidden class="anchor" aria-hidden="true" href="#vr---virtual-reality">#</a></h1>
<h1 id="ausschreibung-torsten--jörg">Ausschreibung Torsten &amp; Jörg<a hidden class="anchor" aria-hidden="true" href="#ausschreibung-torsten--jörg">#</a></h1>
<p>Ausgehend vom Lernbaustein <a href="https://relilab.org/vr/">https://relilab.org/vr/</a> beschäftigen wir uns in diesem Workshop mit Immersion und praktischen Beispielen im Themenbereich VR/AR. Neben der Vermittlung von theoretischen Grundlagen besprechen wir die Einsatzmöglichkeit im Religionsunterricht am Beispiel einer Reihe zu Schöpfungsmythen. Darüber hinnaus bieten wir die Gelegenheit zu Erfahrungsaustausch, Diskussion und exemplarischen Erlebnismöglichkeiten in der virtuellen Realität.</p>
<h1 id="theorie">Theorie<a hidden class="anchor" aria-hidden="true" href="#theorie">#</a></h1>
<h2 id="immersion--präsenz">Immersion &amp; Präsenz<a hidden class="anchor" aria-hidden="true" href="#immersion--präsenz">#</a></h2>
<p><a href="https://www.immersivelearning.institute/">https://www.immersivelearning.institute/</a>
<a href="https://omnia360.de/blog/was-ist-immersion/">https://omnia360.de/blog/was-ist-immersion/</a>
<a href="https://en.wikipedia.org/wiki/Immersive_learning">https://en.wikipedia.org/wiki/Immersive_learning</a>
<img loading="lazy" src="01-immersion-wikipedia.jpg" alt="" />
<a href="https://www.sciencedirect.com/science/article/pii/S0360131519303276">https://www.sciencedirect.com/science/article/pii/S0360131519303276</a></p>
<h2 id="forschung">Forschung<a hidden class="anchor" aria-hidden="true" href="#forschung">#</a></h2>
<p>A Public Database of 360 Videos with Corresponding Ratings of Arousal and Valence
<a href="https://vhil.stanford.edu/360-video-database/">https://vhil.stanford.edu/360-video-database/</a></p>
<p><a href="https://www.researchgate.net/publication/335733502_Getting_your_game_on_Using_virtual_reality_to_improve_real_table_tennis_skills">https://www.researchgate.net/publication/335733502_Getting_your_game_on_Using_virtual_reality_to_improve_real_table_tennis_skills</a></p>
<blockquote>
<p>&ldquo;Diese Studie ergänzt die spärliche, aber wachsende Literatur, indem sie den Transfer von Fertigkeiten aus der realen Welt durch Virtual Reality in einer sportlichen Aufgabe demonstriert.&rdquo;</p>
</blockquote>
<p><a href="https://mixed.de/vr-und-philosophie-youtuber-zeigt-ungewoehnliche-vr-apps/amp/">https://mixed.de/vr-und-philosophie-youtuber-zeigt-ungewoehnliche-vr-apps/amp/</a>
Der norwegische Forscher Joakim Vindenes unterhält einen Blog, Podcast und Youtube-Kanal, in denen er außergewöhnliche VR-Apps vorstellt und sich mit der philosophischen Dimension des Mediums auseinandersetzt.</p>
<p><a href="https://www.youtube.com/watch?v=VY5HaEhUm2Q">https://www.youtube.com/watch?v=VY5HaEhUm2Q</a>
A look at what it would be like to plug into an infinite VR experience machine.</p>
<h2 id="religionen">Religionen<a hidden class="anchor" aria-hidden="true" href="#religionen">#</a></h2>
<p><a href="https://www.matrise.no/2019/06/hinduism-and-virtual-reality/">https://www.matrise.no/2019/06/hinduism-and-virtual-reality/</a></p>
<p><a href="https://www.matrise.no/2020/01/the-existential-problem-of-vr-existentialism/">https://www.matrise.no/2020/01/the-existential-problem-of-vr-existentialism/</a></p>
<h2 id="empathie">Empathie<a hidden class="anchor" aria-hidden="true" href="#empathie">#</a></h2>
<p><a href="https://www.youtube.com/watch?v=L6m79wqNiMA&amp;feature=youtu.be&amp;t=150">https://www.youtube.com/watch?v=L6m79wqNiMA&amp;feature=youtu.be&amp;t=150</a></p>
<blockquote>
<p>&ldquo;VR is a storytelling vehicle, but it&rsquo;s an empathy vehicle.&rdquo;</p>
</blockquote>
<h2 id="therapie">Therapie<a hidden class="anchor" aria-hidden="true" href="#therapie">#</a></h2>
<p>Feeling Good during the COVID19 Epidemic
Virtual Reality Can Help Us to Overcome the Psychological Burden of Coronavirus - <a href="https://www.covidfeelgood.com/home">https://www.covidfeelgood.com/home</a></p>
<p>Die Verkörperung von Mitgefühl in der virtuellen Realität und ihre Auswirkungen auf Patienten mit Depressionen
<a href="https://scitec-media.ch/2016/03/04/game-technologien-helfen-gegen-depressionen/">https://scitec-media.ch/2016/03/04/game-technologien-helfen-gegen-depressionen/</a>
<a href="https://www.youtube.com/watch?v=GwxJVCESc-E">https://www.youtube.com/watch?v=GwxJVCESc-E</a>
<a href="https://www.cambridge.org/core/journals/bjpsych-open/article/embodying-selfcompassion-within-virtual-reality-and-its-effects-on-patients-with-depression/1A1217651159D085145A7999CFFFF772">https://www.cambridge.org/core/journals/bjpsych-open/article/embodying-selfcompassion-within-virtual-reality-and-its-effects-on-patients-with-depression/</a></p>
<h2 id="theater">Theater<a hidden class="anchor" aria-hidden="true" href="#theater">#</a></h2>
<p><a href="https://www.brendanabradley.com/futurestages">https://www.brendanabradley.com/futurestages</a></p>
<h2 id="körperlichkeit">Körperlichkeit<a hidden class="anchor" aria-hidden="true" href="#körperlichkeit">#</a></h2>
<p><a href="https://www.matrise.no/2018/07/virtual-embodiment/">https://www.matrise.no/2018/07/virtual-embodiment/</a>
<a href="https://www.matrise.no/2020/10/virtual-reality-depersonalization-derealization/">https://www.matrise.no/2020/10/virtual-reality-depersonalization-derealization/</a></p>
<h1 id="praxis">Praxis<a hidden class="anchor" aria-hidden="true" href="#praxis">#</a></h1>
<h2 id="padlets">Padlets<a hidden class="anchor" aria-hidden="true" href="#padlets">#</a></h2>
<ul>
<li>[https://padlet.com/petiteprof79/xrinfo(https://padlet.com/petiteprof79/xrinfo)] XR-Info - Stephanie Wössner | CC BY-SA @petiteprof79</li>
<li><a href="https://padlet.com/strsa/ar">https://padlet.com/strsa/ar</a> Augmented Reality (AR) &amp; 360°, (VR) | Gestartet von Tobias Erles (@Mr_Airless) und Sabine Strauss (@Sallythechin) beim Barcamp #wildcampen18, erweitert bei #wildcampen19 zusammen mit Jan Hartwig (@hartifical)</li>
</ul>
<h2 id="artikel">Artikel<a hidden class="anchor" aria-hidden="true" href="#artikel">#</a></h2>
<ul>
<li><a href="https://www.bpb.de/lernen/digitale-bildung/werkstatt/298516/virtual-und-augmented-reality-im-klassenraum-ein-ueberblick-bildungsrelevanter-angebote">Virtual und Augmented Reality im Klassenraum? Ein Überblick bildungsrelevanter Angebote - Steffen Jauch am 16.10.2029 bei bpb</a></li>
</ul>
<h2 id="unterricht">Unterricht<a hidden class="anchor" aria-hidden="true" href="#unterricht">#</a></h2>
<ul>
<li>Eine <a href="https://www.lmz-bw.de/medien-und-bildung/medienwissen/virtual-und-augmented-reality/virtual-reality-unterrichtsbeispiele/">Auswahl an Unterrichtsbeispielen mit Virtual Reality Szenarien</a> von Stephanie Wössner <a href="https://twitter.com/petiteprof79">@petiteprof79</a></li>
</ul>
<h2 id="communities">Communities<a hidden class="anchor" aria-hidden="true" href="#communities">#</a></h2>
<p><a href="https://educatorsinvr.com/">https://educatorsinvr.com/</a></p>
<h1 id="religiöse-erfahrungsräume">Religiöse Erfahrungsräume<a hidden class="anchor" aria-hidden="true" href="#religiöse-erfahrungsräume">#</a></h1>
<h2 id="im-oculus-store">im Oculus Store<a hidden class="anchor" aria-hidden="true" href="#im-oculus-store">#</a></h2>
<h3 id="wander">Wander<a hidden class="anchor" aria-hidden="true" href="#wander">#</a></h3>
<p><a href="https://www.oculus.com/experiences/quest/2078376005587859/">https://www.oculus.com/experiences/quest/2078376005587859/</a></p>
<h2 id="filme">Filme<a hidden class="anchor" aria-hidden="true" href="#filme">#</a></h2>
<p>[https://mixed.de/beruehrender-oculus-film-zeigt-worauf-es-im-leben-ankommt/(https://mixed.de/beruehrender-oculus-film-zeigt-worauf-es-im-leben-ankommt/)]</p>
<h2 id="in-sidequest">In Sidequest<a hidden class="anchor" aria-hidden="true" href="#in-sidequest">#</a></h2>
<h3 id="vanishing-grace">Vanishing Grace<a hidden class="anchor" aria-hidden="true" href="#vanishing-grace">#</a></h3>
<p>[https://sidequestvr.com/app/772/vanishing-grace-pre-alpha-demo(https://sidequestvr.com/app/772/vanishing-grace-pre-alpha-demo)]</p>
<blockquote>
<p>Vanishing Grace ist eine emotionale Reise über die Opfer, die wir bringen müssen, um unseren Platz in der Welt einzunehmen.</p>
</blockquote>
<h3 id="cubism">Cubism<a hidden class="anchor" aria-hidden="true" href="#cubism">#</a></h3>
<p>[https://sidequestvr.com/app/403/cubism-demo(https://sidequestvr.com/app/403/cubism-demo)]</p>
<h3 id="deism">Deism<a hidden class="anchor" aria-hidden="true" href="#deism">#</a></h3>
<blockquote>
<p>The virtual reality god simulator
[https://sidequestvr.com/app/85/deisim(https://sidequestvr.com/app/85/deisim)]</p>
</blockquote>
<h3 id="liminal">Liminal<a hidden class="anchor" aria-hidden="true" href="#liminal">#</a></h3>
<p><a href="https://sidequestvr.com/app/1042/liminal">https://sidequestvr.com/app/1042/liminal</a>
Wählen Sie aus, wie Sie sich fühlen und was Sie leisten wollen: Ruhe, Energie, Schmerzlinderung und Ehrfurcht.</p>
<h1 id="3d-modelle">3D-Modelle<a hidden class="anchor" aria-hidden="true" href="#3d-modelle">#</a></h1>
<p><a href="https://sketchfab.com/3d-models/abandoned-warehouse-interior-scene-1d5285f2e0fd4211a27c8042496d5959#">https://sketchfab.com/3d-models/abandoned-warehouse-interior-scene-1d5285f2e0fd4211a27c8042496d5959#</a></p>
<p><img loading="lazy" src="02-mittelalterliche-kirche.jpg" alt="" />
<a href="https://creativecommons.org/licenses/by-nc/4.0/">CC BY-NC</a> Medieval Church, Calatrava la Nueva, Spain
Processed in Reality Capture from 76 Faro laser scans and 4100 photographs
<a href="https://sketchfab.com/3d-models/medieval-church-calatrava-la-nueva-spain-171a047c08bc4dd588cca5ac744e8065">https://sketchfab.com/3d-models/medieval-church-calatrava-la-nueva-spain-171a047c08bc4dd588cca5ac744e8065</a></p>
<h2 id="avatare">Avatare<a hidden class="anchor" aria-hidden="true" href="#avatare">#</a></h2>
<h2 id="erfahrungswelten">Erfahrungswelten:<a hidden class="anchor" aria-hidden="true" href="#erfahrungswelten">#</a></h2>
<h3 id="360-grad-filme">360 Grad Filme<a hidden class="anchor" aria-hidden="true" href="#360-grad-filme">#</a></h3>
<ul>
<li><a href="https://www.youtube.com/watch?v=dMZfIUr0gEs">Kölner Dom in 360°: Privatkonzert | WDR</a>
Der Domchor gibt ein nächtliches Konzert und der einzige Zuschauer bist du. Unter Leitung des Domkapellmeisters Professor Eberhard Metternich singt der Chor das Ave Maria von Franz Biebl in einer eher ungewöhnlichen Aufstellung. Und du stehst mittendrin. <a href="https://dom360.wdr.de/privatkonzert-bei-nacht/">https://dom360.wdr.de/privatkonzert-bei-nacht/</a>]</li>
<li><a href="https://www.youtube.com/watch?v=QwC5d75iTcA">INSIDE AUSCHWITZ - Das ehemalige Konzentrationslager in 360° | WDR
</a></li>
</ul>
<h3 id="anne-frank-vr">Anne Frank VR<a hidden class="anchor" aria-hidden="true" href="#anne-frank-vr">#</a></h3>
<p><a href="https://www.annefrank.org/de/uber-uns/was-wir-tun/unsere-publikationen/das-anne-frank-haus-virtual-reality/">https://www.annefrank.org/</a></p>
<h3 id="within">Within<a hidden class="anchor" aria-hidden="true" href="#within">#</a></h3>
<p>[https://www.with.in/watch/the-ellen-fund-presents-gorillas-in-vr(https://www.with.in/watch/the-ellen-fund-presents-gorillas-in-vr)]
[https://account.altvr.com/channels/VRChurch(https://account.altvr.com/channels/VRChurch)]</p>
<h1 id="programmierung">Programmierung<a hidden class="anchor" aria-hidden="true" href="#programmierung">#</a></h1>
<ul>
<li><a href="https://circuitstream.com/blog/programming-development-guides/">Learn VR Development: Tips, tricks, and guides to develop VR and AR applications</a></li>
<li><a href="https://www.reddit.com/r/learnVRdev/">Reddit - Learn Virtual Reality Development</a></li>
</ul>
<h2 id="mozilla-hubs">Mozilla Hubs<a hidden class="anchor" aria-hidden="true" href="#mozilla-hubs">#</a></h2>
<h3 id="dokumentation-httpshubsmozillacomdocswelcomehtmlhttpshubsmozillacomdocswelcomehtml">Dokumentation [https://hubs.mozilla.com/docs/welcome.html(https://hubs.mozilla.com/docs/welcome.html)]<a hidden class="anchor" aria-hidden="true" href="#dokumentation-httpshubsmozillacomdocswelcomehtmlhttpshubsmozillacomdocswelcomehtml">#</a></h3>
<h3 id="vorlagen">Vorlagen<a hidden class="anchor" aria-hidden="true" href="#vorlagen">#</a></h3>
<p><a href="https://v3l.de/relilabvr">https://v3l.de/relilabvr</a> (relilab-VR-Hub mit Videos, Bildern, &hellip;)</p>
<p>[https://hubs.mozilla.com/Av38AUU/detailed-tinted-room(https://hubs.mozilla.com/Av38AUU/detailed-tinted-room)]
[https://hubs.mozilla.com/scenes/juMbRem/dramainvrhome(https://hubs.mozilla.com/scenes/juMbRem/dramainvrhome)]</p>
<h3 id="avatare-erstellen">Avatare erstellen<a hidden class="anchor" aria-hidden="true" href="#avatare-erstellen">#</a></h3>
<h3 id="mozilla-hubs---glb">Mozilla Hubs - GLB<a hidden class="anchor" aria-hidden="true" href="#mozilla-hubs---glb">#</a></h3>
<h4 id="online-dienst---readyplayer">Online Dienst - Readyplayer<a hidden class="anchor" aria-hidden="true" href="#online-dienst---readyplayer">#</a></h4>
<p><a href="https://twitter.com/joerglohrer/status/1388023150626099201">https://twitter.com/joerglohrer/status/1388023150626099201</a>
<img loading="lazy" src="03-avatare-erstellen.jpg" alt="" />
</p>
<p>[https://readyplayer.me/(https://readyplayer.me/)]</p>
<p>Beispiel: (<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA - Wolfprint 3D</a>)
<a href="https://d1a370nemizbjq.cloudfront.net/10b05c49-593a-4616-82e9-adcea09aa66c.glb">https://d1a370nemizbjq.cloudfront.net/10b05c49-593a-4616-82e9-adcea09aa66c.glb</a></p>
<p>Hubs by Mozilla</p>
<ul>
<li><a href="https://hubs.mozilla.com/docs/intro-avatars.html">Creating Custom Avatars</a></li>
<li><a href="https://hubs.mozilla.com/docs/creators-advanced-avatar-customization.html">Advanced Avatar Customization</a></li>
</ul>
<p><a href="http://tryquilt.io/">http://tryquilt.io/</a>]</p>
<p><a href="https://github.com/MozillaReality/hubs-avatar-pipelines/tree/master/Blender/AvatarBot">Blender files for AvatarBot</a>
<a href="https://youtube.com/playlist?list=PLCxaiaRxTL6-3pxUsfSa7lzKruGu5UEat">Creating an Avatar using Hubs components in Blender</a></p>
<h4 id="online-editoren">Online Editoren<a hidden class="anchor" aria-hidden="true" href="#online-editoren">#</a></h4>
<p>[https://modelviewer.dev/editor/(https://modelviewer.dev/editor/)]</p>
<h4 id="software">Software<a hidden class="anchor" aria-hidden="true" href="#software">#</a></h4>
<h5 id="makehuman">MakeHuman<a hidden class="anchor" aria-hidden="true" href="#makehuman">#</a></h5>
<p><a href="http://makehumancommunity.org/">http://makehumancommunity.org/</a></p>
<p><a href="https://www.youtube.com/watch?v=kQjp5DYsR_c&amp;t=86s">https://www.youtube.com/watch?v=kQjp5DYsR_c&amp;t=86s</a></p>
<h3 id="tutorials-altspace--blender--unity">Tutorials Altspace / Blender / Unity<a hidden class="anchor" aria-hidden="true" href="#tutorials-altspace--blender--unity">#</a></h3>
<p><a href="http://edvschwab.de/Altspace/Kurz%20Doku%20Blender.pdf">http://edvschwab.de/Altspace/Kurz%20Doku%20Blender.pdf</a>
[http://edvschwab.de/Altspace/Kurz%20Doku%20Unity.pdf(http://edvschwab.de/Altspace/Kurz%20Doku%20Unity.pdf)]</p>
<h2 id="sidequest">Sidequest<a hidden class="anchor" aria-hidden="true" href="#sidequest">#</a></h2>
<p><a href="https://sidequestvr.com/">https://sidequestvr.com/</a>
Installation:
<a href="https://sidequestvr.com/setup-howto">https://sidequestvr.com/setup-howto</a></p>
<p><a href="https://www.google.com/amp/s/www.androidcentral.com/how-put-custom-songs-beat-saber-oculus-quest%3famp">How to put custom songs onto Beat Saber on Oculus Quest</a></p>
<h2 id="aframe">Aframe<a hidden class="anchor" aria-hidden="true" href="#aframe">#</a></h2>
<p><img loading="lazy" src="04-aframe.jpg" alt="" />
<a href="https://codepen.io/joerglohrer/full/dyXQqWG">https://codepen.io/joerglohrer/full/dyXQqWG</a>
<a href="https://aframe.io/">https://aframe.io/</a>
<a href="https://www.codecademy.com/learn/learn-a-frame">https://www.codecademy.com/learn/learn-a-frame</a>
VR development within VR with Oculus Quest + Firefox Reality + Glitch +
<a href="https://rocketvirtual.com/index.html">https://rocketvirtual.com/index.html</a>
<a href="https://michael-mcanally.medium.com/where-to-begin-with-vr-in-a-browser-d818f713a8a8">Where to begin with VR in a browser?</a>
<a href="https://www.reddit.com/r/WebVR/comments/equgdt/vr_development_within_vr_with_oculus_quest/">https://www.reddit.com/r/WebVR/comments/equgdt/vr_development_within_vr_with_oculus_quest/</a></p>
<p><a href="https://aframe-model-viewer.glitch.me/">https://aframe-model-viewer.glitch.me/</a></p>
<p><a href="https://klausw.github.io/a-frame-car-sample/index.html">https://klausw.github.io/a-frame-car-sample/index.html</a></p>
<h2 id="threejs">ThreeJS<a hidden class="anchor" aria-hidden="true" href="#threejs">#</a></h2>
<p><a href="https://threejs.org/">https://threejs.org/</a>
<a href="https://www.jesuisundev.com/en/understand-threejs/">https://www.jesuisundev.com/en/understand-threejs/</a></p>
<h2 id="tour-creator-google"><del>Tour Creator Google</del><a hidden class="anchor" aria-hidden="true" href="#tour-creator-google">#</a></h2>
<p>&ldquo;Starting June 30, 2021, the Google Expeditions and Tour Creator <a href="https://support.google.com/tourcreator/?hl=en">will no longer be accessible</a>.&rdquo;</p>
<h2 id="unity">Unity<a hidden class="anchor" aria-hidden="true" href="#unity">#</a></h2>
<p><a href="https://unity.com/de/learn/get-started">https://unity.com/de/learn/get-started</a></p>
<h1 id="optik">Optik<a hidden class="anchor" aria-hidden="true" href="#optik">#</a></h1>
<h2 id="pupillendistanz-pd-messen---ipd-interpupillary-distance">Pupillendistanz (PD) messen - IPD (interpupillary distance)<a hidden class="anchor" aria-hidden="true" href="#pupillendistanz-pd-messen---ipd-interpupillary-distance">#</a></h2>
<p><a href="https://apps.apple.com/de/app/eyemeasure/id1417435049">https://apps.apple.com/de/app/eyemeasure/id1417435049</a>
Die kostenfreie App misst den Augenabstand auf 0,5 mm genau ab iPhoneX oder iPadPro
<img loading="lazy" src="05-pupillendistanz.jpg" alt="" />
Oder einfach mit Lineal:
<a href="https://imgur.com/a/gyYKB">https://imgur.com/a/gyYKB</a></p>
<h1 id="oculus-quest">Oculus Quest<a hidden class="anchor" aria-hidden="true" href="#oculus-quest">#</a></h1>
<h2 id="tutorials">Tutorials<a hidden class="anchor" aria-hidden="true" href="#tutorials">#</a></h2>
<h3 id="deutsch">Deutsch<a hidden class="anchor" aria-hidden="true" href="#deutsch">#</a></h3>
<p><a href="https://twitter.com/StubeDie">https://twitter.com/StubeDie</a></p>
<h3 id="englisch">Englisch<a hidden class="anchor" aria-hidden="true" href="#englisch">#</a></h3>
<h4 id="foren">Foren<a hidden class="anchor" aria-hidden="true" href="#foren">#</a></h4>
<p><a href="https://www.reddit.com/r/OculusQuest/">https://www.reddit.com/r/OculusQuest/</a>
<a href="https://www.reddit.com/r/OculusQuest2/">https://www.reddit.com/r/OculusQuest2/</a></p>
<h2 id="streaming--playthrough--livecasting--obs">Streaming / Playthrough / Livecasting / OBS<a hidden class="anchor" aria-hidden="true" href="#streaming--playthrough--livecasting--obs">#</a></h2>
<p><a href="https://bsaber.com/queststreamingguide/">Oculus Quest Recording / Live Streaming Guide</a>
<a href="https://restream.io/blog/ultimate-guide-to-twitch/">How to stream on Twitch: the ultimate guide</a></p>
<h2 id="file-transfer">File Transfer<a hidden class="anchor" aria-hidden="true" href="#file-transfer">#</a></h2>
<p>3 different ways
<a href="https://www.youtube.com/watch?v=APbbuJF4Ma4">https://www.youtube.com/watch?v=APbbuJF4Ma4</a>
<a href="https://www.android.com/filetransfer/">https://www.android.com/filetransfer/</a>
<a href="https://support.oculus.com/2255729571307786/">Wie übertrage ich Bilder oder Videos von meinem Computer auf mein Oculus Quest 2 oder Quest?</a></p>
<p>Facebook video downloader here - <a href="https://fbdown.net/">https://fbdown.net/</a></p>
<h2 id="brillenträger">Brillenträger<a hidden class="anchor" aria-hidden="true" href="#brillenträger">#</a></h2>
<p>Sehstärke-Linsen Einsätze
<a href="https://mixed.de/vr-optiker-sehstaerke-linsen-test/">https://mixed.de/vr-optiker-sehstaerke-linsen-test/</a></p>
<ul>
<li><a href="https://vroptiker.de/sehstaerke-linsen-einsaetze/oculus-quest2/">https://vroptiker.de/sehstaerke-linsen-einsaetze/oculus-quest2/</a></li>
<li><a href="https://widmovr.com/product/oculus-quest-2-prescription-lens-adapters/">https://widmovr.com/product/oculus-quest-2-prescription-lens-adapters/</a></li>
</ul>
<h2 id="not-to-do">Not to do<a hidden class="anchor" aria-hidden="true" href="#not-to-do">#</a></h2>
<h3 id="sonnenlicht-in-die-linse">Sonnenlicht in die Linse)<a hidden class="anchor" aria-hidden="true" href="#sonnenlicht-in-die-linse">#</a></h3>
<p>Sonnenlicht kann durch die Linsen gebündelt werden und das Display beschödigen.</p>
<h3 id="linsen-reinigen">Linsen reinigen<a hidden class="anchor" aria-hidden="true" href="#linsen-reinigen">#</a></h3>
<h3 id="grips---handhalterungen">Grips - Handhalterungen<a hidden class="anchor" aria-hidden="true" href="#grips---handhalterungen">#</a></h3>
<p><a href="https://www.youtube.com/watch?v=_52xWr_R4uM&amp;feature=youtu.be&amp;t=388">https://www.youtube.com/watch?v=_52xWr_R4uM&amp;feature=youtu.be&amp;t=388</a></p>
<h3 id="headstrap">Headstrap<a hidden class="anchor" aria-hidden="true" href="#headstrap">#</a></h3>
<h4 id="vive-deluxe-audio-strap">VIVE DELUXE AUDIO STRAP<a hidden class="anchor" aria-hidden="true" href="#vive-deluxe-audio-strap">#</a></h4>
<p><a href="https://www.vive.com/de/accessory/vive-deluxe-audio-strap/">https://www.vive.com/de/accessory/vive-deluxe-audio-strap/</a></p>
<p>FrankenQuest 2
<a href="https://uploadvr.com/frankenquest-2-quest-2/">https://uploadvr.com/frankenquest-2-quest-2/</a>
Adapter zum 3D-Druck:
<a href="https://www.thingiverse.com/thing:4622970">https://www.thingiverse.com/thing:4622970</a>
Variante mit Kabelklemme (oben oder unten):
<a href="https://www.thingiverse.com/thing:4628600/files">https://www.thingiverse.com/thing:4628600/files</a>
<img loading="lazy" src="06-vr-adapter-3ddruck.jpg" alt="" />
:::success
Druck skaliert auf 101%
:::
Install guide
Remove the Quest 2 straps following this guide: <a href="https://www.youtube.com/watch?v=PejiYjR7_44&amp;feature=youtu.be&amp;t=110">https://www.youtube.com/watch?v=PejiYjR7_44&amp;feature=youtu.be&amp;t=110</a>
Snap the DAS onto the adaptor (pushing the round front section in first like in the picture).
Snap the adaptor onto Quest 2.
Use the velcro loop to attach the head strap to the headset.
<img loading="lazy" src="07-vive-straps-3ddruck.jpg" alt="" />
</p>
<p>Oculus Quest 2 Comfort Head Strap Mods!</p>
<h4 id="3ddruck">3DDruck<a hidden class="anchor" aria-hidden="true" href="#3ddruck">#</a></h4>
<p>Oculus Quest 2 Elite Strap_V2_NAVIDA DESIGN
[https://www.thingiverse.com/thing:4630780/files(https://www.thingiverse.com/thing:4630780/files)]
Oculus Link Cable Clip for Deluxe Audio Strap &ldquo;DAS&rdquo;
<a href="https://www.thingiverse.com/thing:4666749">https://www.thingiverse.com/thing:4666749</a></p>
<p>Überblick:
<a href="https://www.youtube.com/watch?v=sUhMk19PVq4">https://www.youtube.com/watch?v=sUhMk19PVq4</a>
<a href="https://www.youtube.com/watch?v=CN9fYlUGVtk">https://www.youtube.com/watch?v=CN9fYlUGVtk</a></p>
<h3 id="lens-adaptor">Lens Adaptor<a hidden class="anchor" aria-hidden="true" href="#lens-adaptor">#</a></h3>
<h4 id="für-brillen">Für Brillen<a hidden class="anchor" aria-hidden="true" href="#für-brillen">#</a></h4>
<p>[https://www.thingiverse.com/thing:3653631(https://www.thingiverse.com/thing:3653631)]
Für Linsen
[https://www.thingiverse.com/thing:3642004(https://www.thingiverse.com/thing:3642004)]</p>
<p>Esimen Upgrade K3</p>
<h3 id="batterie">Batterie<a hidden class="anchor" aria-hidden="true" href="#batterie">#</a></h3>
<p><a href="https://www.androidcentral.com/best-oculus-quest-battery-pack">https://www.androidcentral.com/best-oculus-quest-battery-pack</a></p>
</div>
<footer class="post-footer">
<ul class="post-tags">
</ul>
</footer>
</article>
</main>
<footer class="footer">
<span>&copy; 2025 <a href="http://localhost:1313/">Jörg Lohrer</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
<a rel="me" href="https://reliverse.social/@joerglohrer">Mastodon</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 KiB

View File

@ -1,375 +0,0 @@
<!DOCTYPE html>
<html lang="de" dir="auto">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>WordPress Werkstatt PHP | Jörg Lohrer</title>
<meta name="keywords" content="ACF, WordPress, Formulare, JSON, Plugin">
<meta name="description" content="Advanced Custom Fields und Formulareingaben">
<meta name="author" content="Jörg Lohrer">
<link rel="canonical" href="http://localhost:1313/2021/11/17/wordpress-werkstatt.html/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.fcb38834b6dee4645dbe7c77d6c5278e12448b758b3f769e48a2d86d35709cb2.css" integrity="sha256-/LOINLbe5GRdvnx31sUnjhJEi3WLP3aeSKLYbTVwnLI=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://localhost:1313/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://localhost:1313/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://localhost:1313/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://localhost:1313/apple-touch-icon.png">
<link rel="mask-icon" href="http://localhost:1313/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="de" href="http://localhost:1313/2021/11/17/wordpress-werkstatt.html/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://localhost:1313/" accesskey="h" title="Jörg Lohrer (Alt + H)">Jörg Lohrer</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
<ul class="lang-switch"><li>|</li>
</ul>
</div>
</div>
<ul id="menu">
<li>
<a href="http://localhost:1313/" title="Jörg Lohrer">
<span>Home</span>
</a>
</li>
<li>
<a href="http://localhost:1313/archives/" title="Archive">
<span>Blog</span>
</a>
</li>
<li>
<a href="http://localhost:1313/impressum/" title="Impressum">
<span>Impressum</span>
</a>
</li>
<li>
<a href="https://reliverse.social/@joerglohrer" title="Mastodon">
<span><i class="fa fa-heart"></i>Mastodon</span>&nbsp;
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="12" width="12">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
<path d="M15 3h6v6"></path>
<path d="M10 14L21 3"></path>
</svg>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<h1 class="post-title entry-hint-parent">
WordPress Werkstatt PHP
</h1>
<div class="post-description">
Advanced Custom Fields und Formulareingaben
</div>
<div class="post-meta"><span title='2021-11-17 00:00:00 +0000 UTC'>November 17, 2021</span>&nbsp;·&nbsp;Jörg Lohrer
</div>
</header>
<figure class="entry-cover">
<img loading="eager" src="http://localhost:1313/2021/11/17/wordpress-werkstatt.html/04-termine-neu.png" alt="">
</figure>
<div class="post-content"><h1 id="wordpress-werkstatt-php">WordPress Werkstatt PHP<a hidden class="anchor" aria-hidden="true" href="#wordpress-werkstatt-php">#</a></h1>
<p>Zunächst wird auf relilab.org das kostenfreie <a href="https://de.wordpress.org/plugins/advanced-custom-fields/">Plugin ACF - Advanced Custom Fields</a> installiert und aktiviert.
Dies ermöglicht weitere individuelle Beitragsfelder für die Beiträge.
Nun kann manuell aktiviert oder eine Feldgruppe importiert werden - hier mittels <a href="#ACF-JSON-Export">dieser JSON-Datei</a>, die das abkürzt:
<img loading="lazy" src="h01-json-import.png" alt="" />
mit dem Ergebnis, dass unter allen WordPress-Beiträgen jetzt zwei Terminfelder erscheinen, die ausgefüllt werden können:
<img loading="lazy" src="02-terminfelder.png" alt="" />
Zudem gibt es neu eine Kategorie &ldquo;Termine&rdquo;, die aktiviert werden kann mit Unterkategorien, die später Übersichtsseiten ermöglichen:
<img loading="lazy" src="03-kategorien.png" alt="" />
Jetzt wird das <a href="https://github.com/rpi-virtuell/relilab-termine">Plugin relilab-termine</a> installiert und aktiviert
Nun kann mittels Shortcode <code>[relilab_termine]</code> eine Terminübersicht als WordPress-Block erzeugt werden:
<img loading="lazy" src="04-termine-neu.png" alt="" />
</p>
<h2 id="json">JSON<a hidden class="anchor" aria-hidden="true" href="#json">#</a></h2>
<h4 id="acf-json-export">ACF-JSON-Export:<a hidden class="anchor" aria-hidden="true" href="#acf-json-export">#</a></h4>
<pre tabindex="0"><code class="language-json=" data-lang="json=">[
{
&#34;key&#34;: &#34;group_6193936e4f12c&#34;,
&#34;title&#34;: &#34;Termin&#34;,
&#34;fields&#34;: [
{
&#34;key&#34;: &#34;field_619393f8e62e0&#34;,
&#34;label&#34;: &#34;Startet am&#34;,
&#34;name&#34;: &#34;relilab_startdate&#34;,
&#34;type&#34;: &#34;date_time_picker&#34;,
&#34;instructions&#34;: &#34;&#34;,
&#34;required&#34;: 0,
&#34;conditional_logic&#34;: 0,
&#34;wrapper&#34;: {
&#34;width&#34;: &#34;&#34;,
&#34;class&#34;: &#34;&#34;,
&#34;id&#34;: &#34;&#34;
},
&#34;display_format&#34;: &#34;d.m.Y H:i&#34;,
&#34;return_format&#34;: &#34;Y-m-d H:i&#34;,
&#34;first_day&#34;: 1
},
{
&#34;key&#34;: &#34;field_619394a3e62e1&#34;,
&#34;label&#34;: &#34;Endet am&#34;,
&#34;name&#34;: &#34;relilab_enddate&#34;,
&#34;type&#34;: &#34;date_time_picker&#34;,
&#34;instructions&#34;: &#34;&#34;,
&#34;required&#34;: 0,
&#34;conditional_logic&#34;: 0,
&#34;wrapper&#34;: {
&#34;width&#34;: &#34;&#34;,
&#34;class&#34;: &#34;&#34;,
&#34;id&#34;: &#34;&#34;
},
&#34;display_format&#34;: &#34;d.m.Y H:i&#34;,
&#34;return_format&#34;: &#34;Y-m-d H:i&#34;,
&#34;first_day&#34;: 1
}
],
&#34;location&#34;: [
[
{
&#34;param&#34;: &#34;post_type&#34;,
&#34;operator&#34;: &#34;==&#34;,
&#34;value&#34;: &#34;post&#34;
}
]
],
&#34;menu_order&#34;: 0,
&#34;position&#34;: &#34;normal&#34;,
&#34;style&#34;: &#34;default&#34;,
&#34;label_placement&#34;: &#34;left&#34;,
&#34;instruction_placement&#34;: &#34;label&#34;,
&#34;hide_on_screen&#34;: &#34;&#34;,
&#34;active&#34;: true,
&#34;description&#34;: &#34;&#34;,
&#34;show_in_rest&#34;: 0,
&#34;acfe_display_title&#34;: &#34;&#34;,
&#34;acfe_autosync&#34;: &#34;&#34;,
&#34;acfe_form&#34;: 0,
&#34;acfe_meta&#34;: &#34;&#34;,
&#34;acfe_note&#34;: &#34;&#34;
}
]
</code></pre><h2 id="php">PHP<a hidden class="anchor" aria-hidden="true" href="#php">#</a></h2>
<h3 id="software">Software<a hidden class="anchor" aria-hidden="true" href="#software">#</a></h3>
<h4 id="php-storm">PHP-Storm<a hidden class="anchor" aria-hidden="true" href="#php-storm">#</a></h4>
<p><a href="https://www.jetbrains.com/de-de/phpstorm/">https://www.jetbrains.com/de-de/phpstorm/</a></p>
<h5 id="shortcode-zum-sprechen-bringen">Shortcode zum Sprechen bringen<a hidden class="anchor" aria-hidden="true" href="#shortcode-zum-sprechen-bringen">#</a></h5>
<p><a href="https://developer.wordpress.org/reference/functions/add_shortcode/">https://developer.wordpress.org/reference/functions/add_shortcode/</a>
In PhpStorm
<img loading="lazy" src="05-php-storm.png" alt="" />
<code>add_shortcode( string $tag, callable $callback )</code></p>
<p>alle Termine listen, die
<a href="https://www.advancedcustomfields.com/resources/orde-posts-by-custom-fields/">https://www.advancedcustomfields.com/resources/orde-posts-by-custom-fields/</a></p>
<p><img loading="lazy" src="06-termine-listen.png" alt="" />
</p>
<p>PHP-Storm nutzt als External Library dann WordPress
<img loading="lazy" src="07-external-library.png" alt="" />
</p>
<h3 id="plugin">Plugin<a hidden class="anchor" aria-hidden="true" href="#plugin">#</a></h3>
<p>Unsere Funktion:</p>
<pre tabindex="0"><code>/**
*Plugin Name: relilab Termine
*/
add_shortcode(&#39;termine&#39;,&#39;termineAusgeben&#39;);
function termineAusgeben( $atts ) {
$posts = get_posts(array(
&#39;post_type&#39; =&gt; &#39;post&#39;,
&#39;posts_per_page&#39; =&gt; -1,
&#39;category&#39; =&gt; &#39;termine&#39;,
&#39;meta_key&#39; =&gt; &#39;relilab_startdate&#39;,
&#39;orderby&#39; =&gt; &#39;meta_value&#39;,
&#39;order&#39; =&gt; &#39;DESC&#39;
));
// ob_start();
global $post;
?&gt;
&lt;ul&gt;
&lt;?php
foreach ($posts as $post) {
setup_postdata( $post )
?&gt;
&lt;li&gt;
&lt;a href=&#34;&lt;?php the_permalink(); ?&gt;&#34;&gt;&lt;?php the_title(); ?&gt; (date: &lt;?php the_field(&#39;relilab_startdate&#39;); ?&gt;)&lt;/a&gt;
&lt;/li&gt;
&lt;?php
}
?&gt;
&lt;/ul&gt;
&lt;?php
wp_reset_postdata();
// return ob_get_clean();
}
</code></pre>
</div>
<footer class="post-footer">
<ul class="post-tags">
</ul>
</footer>
</article>
</main>
<footer class="footer">
<span>&copy; 2025 <a href="http://localhost:1313/">Jörg Lohrer</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
<a rel="me" href="https://reliverse.social/@joerglohrer">Mastodon</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

View File

@ -1,350 +0,0 @@
<!DOCTYPE html>
<html lang="de" dir="auto">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>Moodle Server mit Ubuntu 20 LTS und Iomad | Jörg Lohrer</title>
<meta name="keywords" content="Moodle, Ubuntu, Linux, Iomad, Server, MySql, Datenbank">
<meta name="description" content="Installation von Iomad zur Moodle-Instanz-Verwaltung">
<meta name="author" content="Jörg Lohrer">
<link rel="canonical" href="http://localhost:1313/2022/02/16/moodle-iomad-linux.html/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.fcb38834b6dee4645dbe7c77d6c5278e12448b758b3f769e48a2d86d35709cb2.css" integrity="sha256-/LOINLbe5GRdvnx31sUnjhJEi3WLP3aeSKLYbTVwnLI=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://localhost:1313/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://localhost:1313/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://localhost:1313/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://localhost:1313/apple-touch-icon.png">
<link rel="mask-icon" href="http://localhost:1313/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="de" href="http://localhost:1313/2022/02/16/moodle-iomad-linux.html/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://localhost:1313/" accesskey="h" title="Jörg Lohrer (Alt + H)">Jörg Lohrer</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
<ul class="lang-switch"><li>|</li>
</ul>
</div>
</div>
<ul id="menu">
<li>
<a href="http://localhost:1313/" title="Jörg Lohrer">
<span>Home</span>
</a>
</li>
<li>
<a href="http://localhost:1313/archives/" title="Archive">
<span>Blog</span>
</a>
</li>
<li>
<a href="http://localhost:1313/impressum/" title="Impressum">
<span>Impressum</span>
</a>
</li>
<li>
<a href="https://reliverse.social/@joerglohrer" title="Mastodon">
<span><i class="fa fa-heart"></i>Mastodon</span>&nbsp;
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="12" width="12">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
<path d="M15 3h6v6"></path>
<path d="M10 14L21 3"></path>
</svg>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<h1 class="post-title entry-hint-parent">
Moodle Server mit Ubuntu 20 LTS und Iomad
</h1>
<div class="post-description">
Installation von Iomad zur Moodle-Instanz-Verwaltung
</div>
<div class="post-meta"><span title='2022-02-16 00:00:00 +0000 UTC'>Februar 16, 2022</span>&nbsp;·&nbsp;Jörg Lohrer
</div>
</header>
<figure class="entry-cover">
<img loading="eager" src="http://localhost:1313/2022/02/16/moodle-iomad-linux.html/title-gif.gif" alt="">
</figure>
<div class="post-content"><h1 id="moodle-server-mit-ubuntu-20-lts-und-iomad">Moodle Server mit Ubuntu 20 LTS und Iomad<a hidden class="anchor" aria-hidden="true" href="#moodle-server-mit-ubuntu-20-lts-und-iomad">#</a></h1>
<h2 id="ubuntu-server-image-herunterladen">Ubuntu Server-Image herunterladen<a hidden class="anchor" aria-hidden="true" href="#ubuntu-server-image-herunterladen">#</a></h2>
<p><a href="https://releases.ubuntu.com/20.04/">https://releases.ubuntu.com/20.04/</a></p>
<h2 id="virtualbox-mit-dem-ubuntu-image-einrichten">Virtualbox mit dem Ubuntu Image einrichten<a hidden class="anchor" aria-hidden="true" href="#virtualbox-mit-dem-ubuntu-image-einrichten">#</a></h2>
<h3 id="netzwerkbrücke-aktivieren">Netzwerkbrücke aktivieren<a hidden class="anchor" aria-hidden="true" href="#netzwerkbrücke-aktivieren">#</a></h3>
<p><img loading="lazy" src="01-netzwerkbruecke.png" alt="" />
</p>
<h3 id="ip-adresse-ermitteln">IP-Adresse ermitteln<a hidden class="anchor" aria-hidden="true" href="#ip-adresse-ermitteln">#</a></h3>
<p><code>ifconfig </code> -&gt; 192.168.178.132</p>
<h3 id="auf-dem-mac-oder-pc-die-auflösung-des-hosts-verknüpfen">Auf dem Mac (oder PC) die Auflösung des Hosts verknüpfen<a hidden class="anchor" aria-hidden="true" href="#auf-dem-mac-oder-pc-die-auflösung-des-hosts-verknüpfen">#</a></h3>
<p>auf dem Mac <code>sudo nano /etc/hosts</code> die IP eintragen und moodle.local zuweisen:
<img loading="lazy" src="02-hosts-eintragen.png" alt="" />
</p>
<h2 id="moodle-server-auf-virtualbox-vorbereiten">Moodle Server auf Virtualbox vorbereiten<a hidden class="anchor" aria-hidden="true" href="#moodle-server-auf-virtualbox-vorbereiten">#</a></h2>
<p><code>sudo -i</code>wechselt auf root</p>
<h3 id="ssh-zugriff-ermöglichen">SSH Zugriff ermöglichen<a hidden class="anchor" aria-hidden="true" href="#ssh-zugriff-ermöglichen">#</a></h3>
<p><a href="https://linuxconfig.org/allow-ssh-root-login-on-ubuntu-20-04-focal-fossa-linux">Allow SSH root login on Ubuntu 20.04 Focal Fossa Linux</a></p>
<h3 id="shellbefehle-zur-installation">Shellbefehle zur Installation:<a hidden class="anchor" aria-hidden="true" href="#shellbefehle-zur-installation">#</a></h3>
<pre tabindex="0"><code class="language-shell=" data-lang="shell=">sudo apt update &amp;&amp; apt upgrade -y
apt install mariadb-server
sudo apt install apache2 libapache2-mod-fcgid
sudo apt install php php-cli php-fpm php-json php-common php-mysql php-zip php-gd php-mbstring php-curl php-xml php-pear php-bcmath php-intl php-xmlrpc php-soap
a2enconf php7.4-fpm
sudo a2enmod actions fcgid alias proxy_fcgi setenvif
a2dismod php7.4
a2dismod mpm_prefork
a2dismod mpm_worker
a2enmod mpm_event
systemctl restart php7.4-fpm apache2
</code></pre><h3 id="anlegen-etcapache2sites-availablemoodleconf">anlegen: /etc/apache2/sites-available/moodle.conf<a hidden class="anchor" aria-hidden="true" href="#anlegen-etcapache2sites-availablemoodleconf">#</a></h3>
<pre tabindex="0"><code class="language-shell=" data-lang="shell=">############################
&lt;VirtualHost *:80&gt;
ServerName moodle.local
ServerAdmin webmaster@localhost
DocumentRoot /var/www/moodle
&lt;FilesMatch \.php$&gt;
SetHandler &#34;proxy:unix:/var/run/php/php7.4-fpm.sock|fcgi://localhost/&#34;
&lt;/FilesMatch&gt;
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
&lt;/VirtualHost&gt;
####################################################################
</code></pre><h3 id="weitere-shellbefehle-zur-installation">Weitere Shellbefehle zur Installation:<a hidden class="anchor" aria-hidden="true" href="#weitere-shellbefehle-zur-installation">#</a></h3>
<pre tabindex="0"><code class="language-shell=" data-lang="shell=">a2ensite moodle.conf
systemctl reload apache2
mkdir /var/www/moodle
echo &#39;&lt;?php phpinfo(); ?&gt;&#39; &gt; /var/www/moodle/info.php
</code></pre><h3 id="host-eintrag-hinzufügen-192168178xxx-moodlelocal">host eintrag hinzufügen: &ldquo;192.168.178.xxx moodle.local&rdquo;<a hidden class="anchor" aria-hidden="true" href="#host-eintrag-hinzufügen-192168178xxx-moodlelocal">#</a></h3>
<p>192.168.178.xxx moodle.local
192.168.178.xxx <a href="https://www.moodle.local">www.moodle.local</a></p>
<h3 id="im-browser-öffnen-httpmoodlelocalinfophp">im Browser öffnen: <a href="http://moodle.local/info.php">http://moodle.local/info.php</a><a hidden class="anchor" aria-hidden="true" href="#im-browser-öffnen-httpmoodlelocalinfophp">#</a></h3>
<h3 id="maschine-speichern-und-klonen">maschine speichern und klonen<a hidden class="anchor" aria-hidden="true" href="#maschine-speichern-und-klonen">#</a></h3>
<h2 id="anschließend-iomad-moodle-installieren">Anschließend IOMAD moodle installieren:<a hidden class="anchor" aria-hidden="true" href="#anschließend-iomad-moodle-installieren">#</a></h2>
<p><a href="https://www.iomad.org/wp-content/uploads/2021/03/Iomad-Installation-Guide.pdf">https://www.iomad.org/wp-content/uploads/2021/03/Iomad-Installation-Guide.pdf</a></p>
<h3 id="datenbank-für-moodle-erzeugen-via-ssh">Datenbank für moodle erzeugen via SSH:<a hidden class="anchor" aria-hidden="true" href="#datenbank-für-moodle-erzeugen-via-ssh">#</a></h3>
<pre tabindex="0"><code class="language-shell=" data-lang="shell=">
mysql
CREATE DATABASE moodledb;
CREATE USER &#39;moodleowner&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;$mdb2passwd&#39;;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON moodledb.* TO &#39;moodleowner&#39;@&#39;localhost&#39;;
GRANT FILE ON *.* TO &#39;moodleowner&#39;@&#39;localhost&#39;;
quit
</code></pre><h3 id="installation-iomad">Installation iomad<a hidden class="anchor" aria-hidden="true" href="#installation-iomad">#</a></h3>
<pre tabindex="0"><code class="language-shell=" data-lang="shell=">cd /var/www/moodle
git clone https://github.com/iomad/iomad.git
cd iomad
git checkout -b myiomad origin/IOMAD_310_STABLE
mkdir /var/www/moodledata &amp;&amp; chmod 777 /var/www/moodledata
</code></pre><p><strong>ändern!!!</strong>: <code>/etc/apache2/sites-available/moodle.conf -&gt; DocumentRoot /var/www/moodle/iomad</code></p>
<p><code>systemctl restart php7.4-fpm apache2</code></p>
<h3 id="httpmoodlelocal-aufrufen-und-configphp-datei-mit-hilfe-des-assistenten-generieren-lassen"><a href="http://moodle.local">http://moodle.local</a> aufrufen und config.php Datei mit Hilfe des Assistenten generieren lassen<a hidden class="anchor" aria-hidden="true" href="#httpmoodlelocal-aufrufen-und-configphp-datei-mit-hilfe-des-assistenten-generieren-lassen">#</a></h3>
<p>![](03-config generieren.png)</p>
<p><strong>ändern!!!</strong>: <code>/moodle</code> entfernen</p>
<h3 id="configphp">config.php<a hidden class="anchor" aria-hidden="true" href="#configphp">#</a></h3>
<pre tabindex="0"><code class="language-shell=" data-lang="shell=">&lt;?php // Moodle configuration file
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG-&gt;dbtype = &#39;mariadb&#39;;
$CFG-&gt;dblibrary = &#39;native&#39;;
$CFG-&gt;dbhost = &#39;localhost&#39;;
$CFG-&gt;dbname = &#39;moodledb&#39;;
$CFG-&gt;dbuser = &#39;moodleowner&#39;;
$CFG-&gt;dbpass = &#39;$mdb2passwd&#39;;
$CFG-&gt;prefix = &#39;mdl_&#39;;
$CFG-&gt;dboptions = array (
&#39;dbpersist&#39; =&gt; 0,
&#39;dbport&#39; =&gt; &#39;&#39;,
&#39;dbsocket&#39; =&gt; &#39;&#39;,
&#39;dbcollation&#39; =&gt; &#39;utf8mb4_general_ci&#39;,
);
$CFG-&gt;wwwroot = &#39;http://moodle.local&#39;;
$CFG-&gt;dataroot = &#39;/var/www/moodledata&#39;;
$CFG-&gt;admin = &#39;admin&#39;;
$CFG-&gt;directorypermissions = 0777;
require_once(__DIR__ . &#39;/lib/setup.php&#39;);
// There is no php closing tag in this file,
// it is intentional because it prevents trailing whitespace problems!
</code></pre>
</div>
<footer class="post-footer">
<ul class="post-tags">
</ul>
</footer>
</article>
</main>
<footer class="footer">
<span>&copy; 2025 <a href="http://localhost:1313/">Jörg Lohrer</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
<a rel="me" href="https://reliverse.social/@joerglohrer">Mastodon</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 761 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Some files were not shown because too many files have changed in this diff Show More