Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ Jekyll, is built and verified by GitHub Actions, and is deployed to GitHub Pages
The project documentation remains in the
[OpenTaberna wiki](https://wiki.opentaberna.de).

## Languages

`index.md` is the English page at `/`, `de/index.md` the German page at `/de/`.
Both carry `hreflang` alternates and a language switch; the layout picks its few
interface strings from the page's `lang`. A content change to one page belongs in
the other in the same change. `check_site.rb` fails if the German page, its
alternates or its search terms go missing.

## Local verification

Install Ruby 3.3 and Bundler, then run:
Expand Down
9 changes: 9 additions & 0 deletions _includes/head.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
<meta name="author" content="OpenTaberna">
<meta name="theme-color" content="#ff6410">
<link rel="canonical" href="{{ page_url }}">
<link rel="alternate" hreflang="en" href="{{ '/' | absolute_url }}">
<link rel="alternate" hreflang="de" href="{{ '/de/' | absolute_url }}">
<link rel="alternate" hreflang="x-default" href="{{ '/' | absolute_url }}">
<link rel="describedby" type="text/markdown" href="{{ '/llms.txt' | absolute_url }}">

<meta property="og:type" content="website">
Expand All @@ -17,7 +20,13 @@
<meta property="og:description" content="{{ page_desc | escape }}">
<meta property="og:url" content="{{ page_url }}">
<meta property="og:image" content="{{ '/wiki/taberna_logo.png' | absolute_url }}">
{%- if page.lang == "de" %}
<meta property="og:locale" content="de_DE">
<meta property="og:locale:alternate" content="en_GB">
{%- else %}
<meta property="og:locale" content="en_GB">
<meta property="og:locale:alternate" content="de_DE">
{%- endif %}
<meta name="twitter:card" content="summary">

<link rel="icon" href="{{ '/wiki/taberna_logo.png' | relative_url }}" type="image/png">
Expand Down
24 changes: 16 additions & 8 deletions _layouts/default.html
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
<!DOCTYPE html>
<html lang="{{ site.lang }}">
{%- assign de = page.lang == "de" -%}
<html lang="{{ page.lang | default: site.lang }}">
{%- include head.html -%}
<body>
<a class="skip-link" href="#content">Skip to content</a>
<a class="skip-link" href="#content">{% if de %}Zum Inhalt springen{% else %}Skip to content{% endif %}</a>

<header class="masthead">
<a class="brand" href="{{ '/' | relative_url }}" aria-label="OpenTaberna home">
<a class="brand" href="{{ page.url }}" aria-label="{% if de %}OpenTaberna Startseite{% else %}OpenTaberna home{% endif %}">
<img src="{{ '/wiki/taberna_logo.png' | relative_url }}" alt="" width="42" height="42">
<span>
<span class="brand-name">OpenTaberna</span>
<span class="brand-note">Open-source commerce</span>
<span class="brand-note">{% if de %}Open-Source-E-Commerce{% else %}Open-source commerce{% endif %}</span>
</span>
</a>
<a class="header-link" href="{{ site.organization.github }}">GitHub</a>
<nav class="header-nav">
{%- if de %}
<a class="header-link lang-switch" href="{{ '/' | relative_url }}" hreflang="en" lang="en">English</a>
{%- else %}
<a class="header-link lang-switch" href="{{ '/de/' | relative_url }}" hreflang="de" lang="de">Deutsch</a>
{%- endif %}
<a class="header-link" href="{{ site.organization.github }}">GitHub</a>
</nav>
</header>

<main id="content" class="content">
Expand All @@ -22,14 +30,14 @@
<footer class="site-foot">
<div>
<p class="footer-label">OpenTaberna</p>
<p>Headless commerce, open from end to end.</p>
<p>{% if de %}Headless-Commerce, offen von Anfang bis Ende.{% else %}Headless commerce, open from end to end.{% endif %}</p>
</div>
<div>
<p class="footer-label">For machines</p>
<p class="footer-label">{% if de %}Für Maschinen{% else %}For machines{% endif %}</p>
<p><a href="{{ '/llms.txt' | relative_url }}">llms.txt</a> · <a href="{{ '/sitemap.xml' | relative_url }}">sitemap.xml</a></p>
</div>
<div>
<p class="footer-label">Contact</p>
<p class="footer-label">{% if de %}Kontakt{% else %}Contact{% endif %}</p>
<p><a href="mailto:{{ site.organization.email }}">{{ site.organization.email }}</a></p>
</div>
</footer>
Expand Down
1 change: 1 addition & 0 deletions assets/css/site.css
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ a:hover { text-decoration-thickness: 2px; }
.brand > span { display: grid; }
.brand-name { font-weight: 720; letter-spacing: -0.02em; line-height: 1.2; }
.brand-note { color: var(--fg-muted); font-family: var(--mono); font-size: 0.7rem; }
.header-nav { display: flex; gap: 1.25rem; }
.header-link { color: var(--fg-muted); font-size: 0.92rem; text-decoration: none; }
.header-link:hover { color: var(--fg); }

Expand Down
89 changes: 89 additions & 0 deletions de/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
layout: default
lang: de
title: Open-Source-Shopsystem, headless und selbst gehostet
permalink: /de/
description: >-
OpenTaberna ist ein Open-Source-Shopsystem, headless und selbst gehostet: Baue
deinen eigenen modernen Webshop und automatisiere dein E-Commerce von Anfang bis
Ende. Eine freie Shopware-Alternative.
---

<section class="hero" aria-labelledby="hero-title">
<div>
<p class="eyebrow">Open-Source-E-Commerce, selbst gehostet</p>
<h1 id="hero-title">Das Open-Source-Shopsystem, das wirklich dir gehört.</h1>
<p class="lede">OpenTaberna ist eine moderne, selbst gehostete Webshop-Plattform: Headless-E-Commerce, durchgehend Open Source, das den Ablauf im Onlinehandel von Anfang bis Ende automatisiert.</p>
</div>
<img class="hero-logo" src="/wiki/taberna_logo.png" alt="OpenTaberna-Logo" width="1024" height="1024">
</section>

## Was OpenTaberna ist

Wir haben OpenTaberna gestartet, weil Shopware teuer ist und sich mit kaum etwas
verbinden ließ, das wir anbinden mussten. Also haben wir eine Open-Source-Alternative
zu Shopware gebaut. OpenTaberna trennt Storefront, Verwaltung und Backend und stellt
die Automatisierung in den Mittelpunkt: vom Katalog über Checkout und Lagerbestand bis
zu Zahlung und Versand.

Es ist ein Headless-Shop von Grund auf und standardmäßig selbst gehostet. Du betreibst
ihn auf deinen eigenen Servern, wählst Schnittstellen, Dienste und Deployment selbst
und baust den individuellen Webshop, den dein Geschäft braucht, statt deinen Betrieb
an ein geschlossenes Produkt anzupassen.

## Woraus es besteht

<ul class="projects">
<li class="project">
<h3><a href="https://github.com/OpenTaberna/fastapi">fastapi</a></h3>
<p>Das Python-Backend verantwortet API, Commerce-Domäne, Integrationen und den automatisierten Bestellablauf.</p>
</li>
<li class="project">
<h3><a href="https://github.com/OpenTaberna/frontend">frontend</a></h3>
<p>Die Angular-Storefront bietet Kundinnen und Kunden Katalog, Konto, Warenkorb und Checkout.</p>
</li>
<li class="project">
<h3><a href="https://github.com/OpenTaberna/admin_frontend">admin_frontend</a></h3>
<p>Das rollengeschützte Backoffice verwaltet Produkte, Lagerbestand, Bestellungen und Retouren.</p>
</li>
<li class="project">
<h3><a href="https://github.com/OpenTaberna/wiki">wiki</a></h3>
<p>Das Dokumentations-Repository ist die einzige verbindliche Quelle für Einrichtung, Architektur und Betrieb.</p>
</li>
</ul>

## So fängst du an

<div class="callout">
<p class="callout-kicker">Beginne mit der Dokumentation</p>
<p>Lies das <a href="https://wiki.opentaberna.de">OpenTaberna-Wiki</a> und folge dann dem versionierten <a href="https://github.com/OpenTaberna/wiki/blob/main/Getting-Started.md">Getting-Started-Guide</a> (auf Englisch).</p>
<p>Die Einrichtungsanleitung steht dort und nicht hier, damit das Wiki die eine aktuelle Quelle bleibt.</p>
</div>

## Lizenz und Absicht

OpenTaberna ist vollständig Open Source. Wir wollen mit dem Projekt kein Geld verdienen:
Du darfst es betreiben, forken, für deine eigenen Zwecke pflegen oder weiterverkaufen,
im Rahmen der Lizenzen in den jeweiligen Repositories.

## Gründer

<div class="people">
<article class="person">
<p class="person-role">Gründer</p>
<h3><a href="https://philipptheserver.com">Philipp Lehmann</a></h3>
<p>Infrastruktur-Engineer und Open-Source-Entwickler.</p>
<p class="person-links"><a href="https://github.com/PhilippTheServer">GitHub</a> · <a href="https://orcid.org/0009-0002-3922-2471">ORCID</a></p>
</article>
<article class="person">
<p class="person-role">Gründer</p>
<h3><a href="https://github.com/maltonoloco">Malte Kottmann</a></h3>
<p>Gründer von und Mitwirkender an OpenTaberna.</p>
<p class="person-links"><a href="https://github.com/maltonoloco">GitHub</a></p>
</article>
</div>

## Kontakt

Fragen, Zusammenarbeit und Anfragen zum Projekt gern an
[root@vaultops.de](mailto:root@vaultops.de).
2 changes: 2 additions & 0 deletions llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ sitemap: false

> OpenTaberna is an open-source, self-hosted headless shop system: build a modern, custom web shop and automate e-commerce end to end. A free Shopware alternative. The project exists as an open alternative to expensive, hard-to-integrate commerce platforms such as Shopware.

A German version of the website is at {{ site.url }}/de/.

## Project repositories

- [fastapi](https://github.com/OpenTaberna/fastapi): Python backend for the API, commerce domain, integrations and automated order workflow.
Expand Down
33 changes: 32 additions & 1 deletion scripts/check_site.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def internal_target(reference)
end

required = %w[
index.html robots.txt llms.txt sitemap.xml CNAME
index.html de/index.html robots.txt llms.txt sitemap.xml CNAME
assets/css/site.css wiki/taberna_logo.png
]
required.each do |path|
Expand All @@ -62,6 +62,37 @@ def internal_target(reference)
if sitemap && !sitemap.include?("https://#{DOMAIN}/")
fail!("sitemap.xml: does not contain the canonical site URL")
end
if sitemap && !sitemap.include?("https://#{DOMAIN}/de/")
fail!("sitemap.xml: does not contain the German page")
end

languages = {
"index.html" => { lang: "en", locale: "en_GB", switch: "/de/" },
"de/index.html" => { lang: "de", locale: "de_DE", switch: "/" },
}
languages.each do |path, expected|
html = read(path)
next unless html

fail!("#{path}: <html> is not lang=\"#{expected[:lang]}\"") unless html.include?(%(<html lang="#{expected[:lang]}">))
fail!("#{path}: og:locale is not #{expected[:locale]}") unless html.include?(%(<meta property="og:locale" content="#{expected[:locale]}">))
{ "en" => "https://#{DOMAIN}/", "de" => "https://#{DOMAIN}/de/", "x-default" => "https://#{DOMAIN}/" }.each do |hreflang, href|
unless html.include?(%(<link rel="alternate" hreflang="#{hreflang}" href="#{href}">))
fail!("#{path}: has lost the hreflang=#{hreflang} alternate")
end
end
fail!("#{path}: has lost the language switch to #{expected[:switch]}") unless html.match?(/<a class="[^"]*\blang-switch\b[^"]*"[^>]*href="#{Regexp.escape(expected[:switch])}"/)
end

german = read("de/index.html")
if german
h1 = german[%r{<h1[^>]*>(.*?)</h1>}m, 1].to_s.downcase
%w[open-source shopsystem].each { |term| fail!("de/index.html: h1 has lost #{term.inspect}") unless h1.include?(term) }
description = german[/<meta name="description" content="([^"]*)"/, 1].to_s.downcase
%w[open-source selbst gehostet webshop shopware].each do |term|
fail!("de/index.html: meta description has lost #{term.inspect}") unless description.include?(term)
end
end

html_files = Dir.glob(File.join(SITE, "**", "*.html")).sort
fail!("no HTML pages were built") if html_files.empty?
Expand Down
Loading