Kundenprojekt

Eine Website ohne ein einziges Formular

Eine Stadtteilapotheke braucht weniger Reichweite als Bindung, und eine Nutzerschaft jenseits der 60 braucht kein Dialogfeld vor dem Inhalt. Fast alles, was auf dieser Seite steht, ergibt sich aus diesen beiden Randbedingungen.

rund 2.850

automatisierte Prüfungen, davon rund 590 Gegenproben, die die Prüfungen selbst absichern

null

Anfragen an fremde Server beim Seitenaufruf

Für wen ich gebaut habe

Die meisten, die auf die Website kommen, sind über 60, haben oft ein älteres Gerät und tun sich mit kleiner Schrift schwer. Es ist eine Stadtteilapotheke und keine Kette, in einem Viertel mit hohem Anteil an Menschen mit Migrationsgeschichte.

Der Umsatz einer Apotheke hängt weit überwiegend an verschreibungspflichtigen Arzneimitteln, und die Rezepte dafür stellt der Arzt aus. Daran ändert eine Website nichts, weil über den Weg des Rezepts die Entfernung entscheidet. Die Seite ist deshalb nicht als Neukundenmaschine angelegt, sondern auf Bindung: Vorbestellung, Botendienst, Auffindbarkeit.

Deshalb habe ich auf viele kleine Dinge geachtet. Die Telefonnummer steht im Kopf als Wählverknüpfung, auch auf dem Handy sichtbar und nicht im Menü versteckt, denn Anrufen ist bei einer Apotheke keine Nebenaktion. Die acht Beratungssprachen des Teams stehen auf der Seite, formuliert ohne Verfügbarkeitszusage, weil nicht jederzeit jede Sprache besetzt ist. Im Viertel schafft das mehr Vertrauen als ein Foto. Und die Sprache bleibt konkret, „Rezept vorbestellen“ statt „digitale Arzneimittelversorgung“.

Keine Gesundheitsdaten

Im öffentlichen Bereich der Website gibt es kein einziges Formular. Rezepte, Vorbestellungen und E-Rezepte laufen ausschließlich über die Plattform des Partners.

Ein eigener Rezept-Upload hätte Gesundheitsdaten nach Art. 9 DSGVO auf den Server der Apotheke gebracht. Das heißt Verschlüsselung bei Übertragung und Speicherung, Zugriffs- und Löschkonzept, Eintrag im Verarbeitungsverzeichnis, Auftragsverarbeitungsvertrag und wahrscheinlich eine Datenschutz-Folgenabschätzung. Dazu kommt die apothekerliche Schweigepflicht nach § 203 StGB, die den Hoster zur mitwirkenden Person macht.

Ausschlaggebend war aber die Wartungsperspektive. Die Apotheke pflegt die Seite selbst, mit minimaler Betreuung. Ein System, das Rezeptfotos vorhält, braucht dauerhafte Aufmerksamkeit, also Aktualisierungen, Überwachung und im Ernstfall eine Meldung an die Aufsichtsbehörde binnen 72 Stunden.

Eine un­be­treu­te Website mit Ge­sund­heits­da­ten ist die Kom­bi­na­tion, die ir­gend­wann teuer wird.

Aus derselben Überlegung gibt es kein Kontaktformular. Es hätte Menschen dazu verleitet, Beschwerden hineinzuschreiben, und damit wären dieselben Daten auf demselben Server gelandet, nur durch die Hintertür. Bei der E-Mail-Adresse steht stattdessen der Hinweis auf den richtigen Weg, Portal oder Telefon.

AufrufBesucherin
Öffentlicher BereichWebsite der Apotheke

Kein Formular

Keine Rezept- oder Vorbestelleingaben auf dieser Website.

Website-Grenze

Externer Link
Neuer Tab angefordert

Plattform des Anbieters
Der Kontaktweg verlässt die Website per Link, ohne dort Rezept- oder Vorbestelleingaben entgegenzunehmen.

Barrierefreiheit als Zielsetzung

Barrierefreiheit war hier nicht durch die Auftragslage erzwungen. Ich habe sie mir als Ziel gesetzt, weil die Nutzerschaft sie braucht. Was daraus wurde, ist messbar:

  • Fließtext mindestens 18 Pixel, Zeilenhöhe 1,6
  • Kontrast im Fließtext mindestens 7:1. Das ist der Wert, den die WCAG für die höchste ihrer drei Stufen nennt, nicht das übliche Mindestmaß
  • Klickflächen mindestens 48 Pixel
  • vollständig per Tastatur bedienbar, Fokus jederzeit sichtbar
  • reduzierte Bewegung wird respektiert
  • semantisches HTML, genau eine Hauptüberschrift je Seite
  • geprüft bei 320, 360 und 375 Pixeln Breite sowie bei 200 Prozent Zoom

Auch die Schriftwahl ist funktional. Für den Fließtext läuft Atkinson Hyperlegible, eine Schrift, die für Menschen mit eingeschränktem Sehvermögen gezeichnet wurde.

Das reicht bis in die Silbentrennung. Deutsche Komposita wie „Kompressionsstrümpfe“ passen auf schmalen Bildschirmen in keine Zeile, und der Browser brach sie ohne Trennstrich um. Die Regel lautet jetzt, dass ein Wort, das nicht passt, mit Trennstrich bricht und nie ohne. Dafür muss die Sprachauszeichnung stimmen, sonst trennt der Browser nach englischen Regeln an den falschen Stellen.

Der 360-Grad-Rundgang ist nach denselben Maßstäben gebaut. Für den Szenenwechsel gibt es beschriftete Schaltflächen statt schwebender Pfeile im Panorama. So lässt sich das Ziel erkennen, ohne die Bedeutung eines Symbols kennen zu müssen. Der Betrachter ist auch keine Tastaturfalle. Die verwendete Bibliothek schaltet den Fokusring auf ihrem eigenen Element ab, und ich habe ihn zurückgeholt, weil man sonst unsichtbar darin säße.

Keine Anfrage an Dritte

Beim Aufruf der Seite geht keine einzige Anfrage an einen Dritten hinaus. Das ist eine Anforderung, die durchgehend eingehalten und automatisiert überwacht wird.

  • Schriften und Bilder liefert die Seite selbst aus. Das dynamische Einbinden von Google Fonts ist in Deutschland abgemahnt worden.
  • Statt einer eingebetteten Karte gibt es ein Foto und einen Verweis auf den Routenplaner, denn ein Link überträgt beim Seitenaufruf nichts.
  • Der 360-Grad-Rundgang läuft auf eigenem Server, aus eigenen Panoramen, mit einer selbst gehosteten Bibliothek von rund 21 Kilobyte.
  • Es gibt keine Reichweitenmessung und keine eingebundenen Dienste.
  • Für Besucher gibt es keine Cookies und nichts im lokalen Speicher des Browsers.

Geprüft werden dabei nicht nur Cookies, sondern auch localStorage, sessionStorage, IndexedDB, CacheStorage und Service Worker. Ausgehende Verweise sind einzeln dokumentiert. Ein automatisierter Test vergleicht die tatsächlich vorhandenen Ziele mit dieser Liste und schlägt an, sobald ein weiteres auftaucht.

Den Rundgang gäbe es auch bei einem großen Kartendienst. Eingebettet hätte er beim Seitenaufruf von dort geladen, also eine Anfrage an einen fremden Server ausgelöst. Stattdessen habe ich ihn selbst gebaut. Die Auflösung ist auf 4096 Pixel begrenzt, weil ältere Mobilgeräte darüber nicht zuverlässig darstellen. Geladen wird erst auf Klick, und ohne JavaScript oder 3D-Unterstützung bleibt ein Standbild stehen statt eines kaputten Knopfes. Die Startansicht ist mit diesem Standbild deckungsgleich, Blickrichtung und Bildwinkel wurden überlagert geprüft. Die Bibliothek fügt selbst einen Herkunftsverweis nach außen ein. Er wird entfernt, weil er die dokumentierte Liste der ausgehenden Ziele verfälscht hätte.

Bei den Bildern ging die Rechtelage der Ästhetik vor. Aufnahmen aus fremden Quellen habe ich nicht verwendet, solange die Rechte nicht dokumentiert waren, auch dann nicht, als sie greifbar gewesen wären. Stockfotos und erzeugte Bilder kamen nicht in Frage, und weil keine Kundinnen und Kunden erkennbar sein sollten, sind drei von acht Panoramen ausgeschieden. Beim Hochladen werden Metadaten entfernt, denn Produktfotos aus der Offizin tragen sonst Standortdaten mit sich.

Pflichtangaben, die die Maske erzwingt

Die Apotheke pflegt Angebote, Stellenanzeigen und Leistungen selbst, und nach dem Livegang liest niemand gegen. Also muss die Eingabemaske verhindern, was schiefgehen kann, nicht die Schulung.

  • Der Grundpreis wird aus Preis, Füllmenge und Einheit berechnet und immer als Euro je Kilogramm oder Liter ausgegeben. Die frühere Ausnahme für kleine Packungen ist 2022 entfallen. Er steht unmittelbar beim Preis, nicht in einer Fußnote.
  • Bei Preisermäßigungen verlangt § 11 PAngV den niedrigsten Preis der letzten 30 Tage. Das Eingabefeld heißt deshalb wörtlich „Niedrigster eigener Preis der letzten 30 Tage“ und nicht „bisheriger Preis“. Steht im Feld, was die Vorschrift verlangt, wird mit höherer Wahrscheinlichkeit der richtige Wert eingetragen.
  • Die Angebotsverwaltung lässt keine Arzneimittel zu, weil die Pflichtangaben nach § 4 HWG in einer selbst gepflegten Maske nicht zuverlässig darstellbar sind. Die Kategorieliste hat bewusst keine Auffangkategorie, durch die doch eines hineinrutschen könnte.
  • Der Zusatz „(m/w/d)“ wird nicht geprüft, sondern erzeugt. Eingegeben wird die reine Berufsbezeichnung, und die Ausgabe ergänzt den Zusatz, damit ihn niemand vergessen kann.
  • Abgelaufene Angebote und Stellenanzeigen verschwinden von selbst. Abgelaufene Stellen antworten mit Statuscode 410 und tragen kein aktives Stellenmarkup mehr.
  • Angebote haben bewusst keine eigene Adresse; Direktaufrufe werden umgeleitet. Damit entfällt die ganze Fehlerklasse, statt behandelt zu werden.
Redaktionsmaske mit Beispielwerten: Preis 12,50 €, eigene Preisermäßigung, niedrigster eigener Preis der letzten 30 Tage 15,00 €, Füllmenge 200 ml und Grundpreis 62,50 €/l.
Die zugeschnittene und entsättigte Rohaufnahme mit erfundenen Beispielwerten zeigt, dass das Preisermäßigungsfeld den niedrigsten eigenen Preis der letzten 30 Tage ausdrücklich benennt.

Dieselbe Logik trägt die Wortwahl. Die Apotheke hat keine Versanderlaubnis nach § 11a ApoG, deshalb vermeidet die Website durchgehend Shop-, Kauf- und Versandbegriffe und spricht von Vorbestellen, Reservieren, Abholen und Botendienst. Beim Botendienst wäre „liefern“ zulässig, weil § 17 Abs. 2 ApBetrO die Zustellung ausdrücklich erlaubt. Die Trennung wird trotzdem sprachlich durchgehalten, damit kein Eindruck eines Versandhändlers entsteht. Ein automatisierter Test prüft die Wortliste auf jeder Seite.

Im Impressum steht die Firmierung wörtlich aus dem Handelsregisterauszug statt aus Name und Rechtsformzusatz zusammengesetzt. Die Angaben richten sich nach dem DDG und nicht mehr nach dem TMG, und ein Verweis auf die 2025 eingestellte EU-Streitschlichtungsplattform fehlt bewusst. Die Berufshaftpflicht steht mit Versicherer, Anschrift und räumlichem Geltungsbereich nach DL-InfoV. Die Versicherungsscheinnummer fehlt, weil sie nicht verlangt ist.

Angaben aus externen Quellen gleiche ich mit der jeweiligen Quelle ab. Bei der Prüfung des Impressums stellte sich heraus, dass dort noch die frühere Aufsichtsbehörde genannt war. Ich habe die zuständige Behörde ermittelt und die Angabe korrigiert.

Öffnungszeiten

Falsche Öffnungszeiten bedeuten Kunden vor verschlossener Tür. Entsprechend ist dieser Teil gebaut:

  • Feiertage werden berechnet, nicht eingetragen, und zwar ausdrücklich die hessischen, mit Fronleichnam, ohne Reformationstag und Allerheiligen. Müsste sie jemand pflegen, wäre der erste vergessene Karfreitag eine Frage der Zeit.
  • Die Zeitzone ist explizit gesetzt und nicht von der Serverkonfiguration übernommen.
  • Der Status wird im Browser berechnet, nicht auf dem Server. Sonst friert er in einem Zwischenspeicher ein und zeigt sonntags den Freitagstext.
  • Acht Statusfälle sind einzeln geprüft, darunter der schwierigste, „Geöffnet bis 13:00, dann wieder ab 14:30“. Ein bloßes „geöffnet bis 13:00“ wäre wahr und würde trotzdem jemanden um 13:30 vor die Tür führen.
  • Die Wochentage sind feste Felder statt einer freien Liste, damit kein Tag doppelt vorkommt und keiner fehlt.

Prüfszenario mit Mittagspause · nicht der aktuelle Wochenplan

8:30–13:00Geöffnet
13:00–14:30Pause
14:30–18:30Geöffnet
  1. 09:00 Uhr · vor der Pause

    Geöffnet bis 13:00, dann wieder ab 14:30

  2. 13:30 Uhr · in der Pause

    Jetzt geschlossen, ab 14:30 wieder geöffnet

  3. 15:00 Uhr · nach der Pause

    Geöffnet bis 18:30

Im Pausenfall nennt der Status sowohl die Schließung als auch die Wiederöffnung um 14:30 Uhr.

Ohne JavaScript erscheint die Wochentabelle, aber kein Status.

Keine Aussage ist besser als eine falsche.

Die Prüfungen prüfen sich gegenseitig

Sehr viele Zusicherungen dieses Projekts sind Abwesenheitsprüfungen: kein verbotener Begriff, keine Drittanfrage, kein Stellenmarkup auf abgelaufenen Anzeigen, kein Cookie und nichts im lokalen Speicher des Browsers. Solche Prüfungen melden auch dann Erfolg, wenn der Prüfmechanismus defekt ist, und das macht sie gefährlich.

Deshalb hat jede von ihnen eine Gegenprobe, einen künstlichen Wert, bei dem die Prüfung zwingend anschlagen muss, über dieselbe Prüfstrecke wie der echte Wert. Schlägt sie dort nicht an, scheitert der ganze Lauf.

Echter WertSeiteninhalt ohne Formular
Gegenprobe-WertDerselbe Inhalt mit eingefügtem Formular und Eingabefeld
Beide Werte durchlaufenDieselbe Prüffunktion

Suche nach form, input, textarea und select.

Beim echten WertKein Treffer erwartet
Bei der GegenprobeTreffer zwingend

Kein Treffer: Lauf scheitert.

Dieselbe Prüffunktion muss den echten Inhalt passieren lassen und das eingefügte Formular erkennen, sonst scheitert der Lauf.

Beim Einbau der Gegenproben kam tatsächlich heraus, dass eine Prüfung mit dem Titel „kein Heilungsversprechen“ nur nach einem technischen Markup gesucht hatte. Die eigentliche Zusicherung war ungedeckt. Der Fund entstand vor der Veröffentlichung, im Zuge genau dieser Absicherung.

Ergänzend prüfen die Läufe nicht Attribute im Quelltext, sondern die berechnete Darstellung. Ein Element, das als verborgen markiert ist und trotzdem sichtbar wird, lässt den Lauf scheitern.

Übergabe

Die Apotheke pflegt die Seite selbst, ein- bis zweimal im Monat, überwiegend am Handy. Also gehört zur Lieferung mehr als Code.

Eine Anleitung in Alltagssprache ist aus dem Redaktionsbereich heraus erreichbar, dort, wo sie gebraucht wird, und nicht in einem Repository. Ein Notfallzettel passt gedruckt auf eine A4-Seite und enthält keine Zugangsdaten. Der erste Punkt darin ist der häufigste Notfall: Eine falsche Angabe steht online, und statt auf den Entwickler zu warten, zieht man den Inhalt im Redaktionsbereich zurück.

Für alles technisch Messbare gibt es Prüfungen. Für die Voraussetzungen, auf denen das Ganze ruht, wie Behördenzuständigkeit, Versanderlaubnis oder Fundstellen der Rechtsvorschriften, gibt es keine. Sie stehen deshalb in einer Liste der Annahmen, jede mit Prüfdatum, Zuständigkeit und einer jährlichen Durchsicht im Januar. Was ein Prüflauf überwacht und was ein Mensch bestätigen muss, wird getrennt geführt.

Was ich bewusst nicht gebaut habe

  • Kein NewsletterEr existiert bereits über die Partnerplattform. Ein zweiter Kanal, der nach drei Ausgaben einschläft, schadet mehr, als er nutzt, und er hätte das erste Formular auf den Server gebracht.
  • Keine eingebettete KarteAuf einer Apothekenseite will niemand eine Karte erkunden, sondern eine Route finden.
  • Kein Erkennungsskript für die Partner-AppDas übliche Verfahren mit Wartezeit und Rückfall ist unzuverlässig und erzeugt leere Tabs.
  • Keine Einbettung der PartnerplattformDer Wechsel zu einem externen, transaktionalen Angebot soll sichtbar bleiben. Das ist der Kern der Entscheidung, keine Gesundheitsdaten zu verarbeiten.
  • Keine Detailseiten für AngeboteSie hätten Adressen erzeugt, über die ein abgelaufenes Angebot erreichbar bliebe.

Diese Seite ist ihr eigener Beleg

Was hier über den Verzicht auf Dritt­an­bie­ter steht, gilt auch für diese Seite. Sie lädt nichts von fremden Domains, ist per Tastatur bedienbar, setzt keine Cookies und legt nichts im lokalen Speicher des Browsers ab.

E-Mail schreibenZurück zu den Projekten

kontakt@gartway.de