No description
  • JavaScript 66%
  • CSS 14.2%
  • Python 11.4%
  • HTML 7.6%
  • Nix 0.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-28 13:48:03 +01:00
__pycache__ init project 2025-08-21 09:40:22 +02:00
assets Redesign question cards and add short answers 2026-10-26 12:22:58 +01:00
council Use HTTPS for OpenGraph URLs 2026-10-28 13:48:03 +01:00
fragdenrat Use HTTPS for OpenGraph URLs 2026-10-28 13:48:03 +01:00
media/wappen Add moderation notifications and portal polish 2026-10-24 14:10:57 +02:00
staticfiles Add member portal and polish UI, mail and module 2026-10-24 13:37:12 +02:00
templates Use HTTPS for OpenGraph URLs 2026-10-28 13:48:03 +01:00
.gitignore Limit question submissions per IP 2026-10-23 14:06:17 +02:00
__init__.py update package and module 2026-08-20 12:46:08 +02:00
db.sqlite3 Redesign question cards and add short answers 2026-10-26 12:22:58 +01:00
favicon.svg Add member portal and polish UI, mail and module 2026-10-24 13:37:12 +02:00
flake.lock Update Nix dev app and module 2026-10-23 10:46:13 +02:00
flake.nix Redesign question cards and add short answers 2026-10-26 12:22:58 +01:00
gulpfile.js update module 2025-08-19 10:23:17 +02:00
Makefile add SEO 2025-08-19 10:09:31 +02:00
manage.py init project 2025-08-21 09:40:22 +02:00
module.nix Redesign question cards and add short answers 2026-10-26 12:22:58 +01:00
package-lock.json add deps 2025-08-19 09:46:26 +02:00
package.json Queue outgoing mail and configure SMTP via env 2026-10-23 12:07:45 +02:00
README.md Redesign question cards and add short answers 2026-10-26 12:22:58 +01:00
result update package and module 2026-08-20 12:46:08 +02:00
run_nixos_shell.sh Update Nix dev app and module 2026-10-23 10:46:13 +02:00

FragDenRat

FragDenRat ist eine Django‑Webanwendung, inspiriert von abgeordnetenwatch.de, mit der öffentlich Fragen an Stadträt:innen in Gemeinderäten gestellt und veröffentlicht werden können.

Datenmodell

  • Gemeinde (PublicBody): Verwaltungseinheit (z. B. Stadt/Gemeinde)
  • Partei (Party): Politische Partei
  • Stadträt:in (Member): Mitglied eines Gemeinderats; kann einer Gemeinde und optional einer Partei zugeordnet sein
  • Frage (Question): Frage an eine:n Stadträt:in
  • Antwort (Answer): Kurz- und Langantwort auf eine Frage

Entwicklung (lokal)

Am einfachsten im Projektverzeichnis starten – Django läuft dann mit Autoreload (Hot Reload) und liest den lokalen Quellcode:

nix run

Standardmäßig lauscht der Server auf http://127.0.0.1:8000. Adresse und Port können als Argument übergeben werden:

nix run . -- 0.0.0.0:8000

Alternativ mit einer Development-Shell:

nix develop
export DJANGO_SETTINGS_MODULE=fragdenrat.settings
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver 0.0.0.0:8000

Dann im Browser öffnen: http://localhost:8000

nix run funktioniert auch aus einem Unterverzeichnis des Checkouts. Wird es außerhalb des Checkouts ausgeführt, startet es den Code aus dem Flake-Store – dort gibt es naturgemäß kein Hot Reload.

E-Mail und Mail-Warteschlange

Der Mailversand wird über Umgebungsvariablen konfiguriert:

  • MAIL_HOST (Standard: localhost)
  • MAIL_USER (Standard: info@fragdenrat.de)
  • MAIL_PASSWORD (Standard: leer)
  • MAIL_MODERATOR (Standard: onny@project-insanity.org) für Benachrichtigungen zu neuen Fragen und Antworten
  • MAIL_PORT (Standard: 587, bei MAIL_USE_SSL=1: 465)
  • MAIL_USE_TLS (Standard: 1, außer bei SSL)
  • MAIL_USE_SSL (Standard: 0)
  • DEFAULT_FROM_EMAIL (Standard: MAIL_USER oder noreply@fragdenrat.local)

nix run und nix develop setzen standardmäßig:

MAIL_HOST=mx1.project-insanity.org
MAIL_USER=info@fragdenrat.de
MAIL_MODERATOR=onny@project-insanity.org

Ohne MAIL_PASSWORD wird die Console als E-Mail-Backend verwendet, damit lokale Tests keine echten Mails versenden. Sobald ein Passwort gesetzt ist, wird automatisch SMTP verwendet. Mit EMAIL_BACKEND kann das Backend explizit überschrieben werden.

Neue Fragen werden zunächst nicht öffentlich gespeichert. Die Empfangsbestätigung an den/die Fragesteller:in sowie Benachrichtigungen bei Antworten landen in der Datenbank-Warteschlange und werden vom Systemd-Timer regelmäßig versendet:

python manage.py list_mail_queue
python manage.py process_mail_queue
python manage.py process_mail_queue --dry-run

Spam-Schutz

Neue Fragen sind pro IP-Adresse auf 10 pro Stunde begrenzt. Die Grenze lässt sich über eine Umgebungsvariable anpassen:

QUESTION_RATE_LIMIT_PER_HOUR=10

0 deaktiviert die Begrenzung. Die Zähler liegen im File-Cache unter $FRAGDENRAT_DATA_DIR/cache und werden nach einer Stunde zurückgesetzt.

SEO & OpenGraph

Jede Seite liefert dynamische Meta-Tags für Suchmaschinen und soziale Netzwerke, inklusive Canonical-URL, Twitter Cards und JSON-LD. Die OpenGraph-Bilder werden unter /og/<seitenpfad>.png erzeugt und für 24 Stunden gecacht. Zusätzlich stehen /sitemap.xml und /robots.txt bereit.

NixOS

Binde das Modul in deine flake.nix ein und aktiviere den Service:

{
  inputs.fragdenrat.url = "git+https://git.project-insanity.org/onny/fragify.git"; # Repo-URL anpassen
  # ...
  outputs = { self, nixpkgs, ... }@inputs: {
    nixosConfigurations.host = inputs.nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        inputs.fragdenrat.nixosModule
        ({ pkgs, ... }:{
          nixpkgs.overlays = [ inputs.fragdenrat.overlay ];
        })
        ./configuration.nix
      ];
    };
  };
}

In configuration.nix:

services.fragdenrat.enable = true;
services.fragdenrat.settings = {
  MAIL_HOST = "mx1.project-insanity.org";
  MAIL_USER = "info@fragdenrat.de";
  MAIL_MODERATOR = "onny@project-insanity.org";
  DEFAULT_FROM_EMAIL = "noreply@fragdenrat.de";
  QUESTION_RATE_LIMIT_PER_HOUR = "10";
};
# Optional für Geheimnisse, z. B. eine Datei mit MAIL_PASSWORD=...
services.fragdenrat.environmentFile = "/run/secrets/fragdenrat-mail";

Der Dienst stellt einen Uvicorn-Socket unter /run/fragdenrat/fragdenrat.socket bereit und liefert statische Assets unter /static/ aus. Ein Systemd-Timer verarbeitet die Mail-Warteschlange alle fünf Minuten, sobald MAIL_PASSWORD bzw. EMAIL_BACKEND gesetzt oder ein environmentFile konfiguriert ist. Geheimnisse sollten über environmentFile und nicht über settings in den Nix-Store gelangen.

Technisches

  • Framework: Django
  • UI: Bootstrap 5, Swiper 11 (MIT)
  • OpenGraph-Bilder: Pillow
  • ASGI: Uvicorn (über NixOS-Modul)
  • Datenbank: SQLite standardmäßig (anpassbar über Django-Settings)

Lizenz & Beiträge

Lizenz wie im ursprünglichen Projekt. Beiträge sind willkommen – gerne Issues und Pull Requests eröffnen.