Diese Woche am beliebtesten

Vertiefendes Material

Node.js Formular

Mit unserem Leserbrief Formular kannst du ganz einfach Feedback, Anregungen oder Fragen von deiner Community sammeln und strukturiert verwalten. Die Lösung basiert auf Node.js und speichert die eingehenden Nachrichten sicher auf deinem Server, ohne externe Dienste einzubinden.

Das Script bietet:

  • Ein übersichtliches Formular mit Feldern für Name, E-Mail-Adresse, Betreff und Nachricht
  • Eine sichere Speicherung der Einträge in einer JSON-Datei, direkt auf deinem Server
  • Optionale Anonymisierung von Einsendungen
  • Eine klare Bestätigung für Nutzer:innen nach dem Absenden
  • Einen Endpunkt zum Auslesen aller Leserbriefe für interne Auswertungen

So kannst du Feedback direkt einholen, organisieren und für die Weiterentwicklung deiner Inhalte nutzen. Perfekt geeignet für Blogs, Online-Magazine oder Communities, die Wert auf den Dialog mit ihren Leser:innen legen.

const express = require('express');
const fs = require('fs').promises;
const path = require('path');
const app = express();
app.use(express.json()); // erwartet application/json
app.use(express.urlencoded({ extended: true })); // form-urlencoded
const DATA_DIR = path.join(__dirname, 'data');
const DATA_FILE = path.join(DATA_DIR, 'leserbriefe.json');
function validateInput({ name, email, subject, message }) {
  if (!message || typeof message !== 'string' || message.trim().length < 5) {
    return 'Die Nachricht muss mindestens 5 Zeichen enthalten.';
  }
  if (!email || typeof email !== 'string' || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    return 'Bitte gib eine gültige E-Mail-Adresse an.';
  }
  if (!subject || subject.trim().length === 0) {
    return 'Bitte gib einen Betreff an.';
  }
  return null;
}
async function ensureDataFile() {
  try {
    await fs.mkdir(DATA_DIR, { recursive: true });
    try {
      await fs.access(DATA_FILE);
    } catch {
      await fs.writeFile(DATA_FILE, '[]', 'utf8');
    }
  } catch (err) {
    console.error('Fehler beim Anlegen des Datenverzeichnisses:', err);
    throw err;
  }
}
app.post('/leserbrief', async (req, res) => {
  try {
    const { name = '', email = '', subject = '', message = '', anonymous = false } = req.body;
    const err = validateInput({ name, email, subject, message });
    if (err) return res.status(400).json({ ok: false, error: err });
    const safe = {
      name: String(name).trim(),
      email: String(email).trim(),
      subject: String(subject).trim(),
      message: String(message).trim(),
      anonymous: Boolean(anonymous),
      receivedAt: new Date().toISOString()
    };
    if (safe.anonymous) safe.name = 'Anonym';
    await ensureDataFile();
    const raw = await fs.readFile(DATA_FILE, 'utf8');
    const entries = JSON.parse(raw || '[]');
    entries.push(safe);
    await fs.writeFile(DATA_FILE, JSON.stringify(entries, null, 2), 'utf8');
    return res.json({ ok: true, message: 'Danke! Dein Leserbrief wurde empfangen.' });
  } catch (e) {
    console.error('Serverfehler:', e);
    return res.status(500).json({ ok: false, error: 'Serverfehler' });
  }
});
app.get('/leserbriefe', async (req, res) => {
  try {
    await ensureDataFile();
    const raw = await fs.readFile(DATA_FILE, 'utf8');
    return res.type('application/json').send(raw);
  } catch (e) {
    console.error(e);
    res.status(500).json({ ok: false });
  }
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server läuft auf http://localhost:${PORT}`));
Dreamcodes Redaktion
Dreamcodes Redaktion
Jeder Inhalt auf Dreamcodes entsteht mit einem klaren Anspruch: geprüfte Praxis statt schneller Theorie. Was hier veröffentlicht wird, basiert auf Best Practices, echten Projekterfahrungen und technischem Verständnis, das über das Offensichtliche hinausgeht. Unser Ziel ist ein Fundament, auf dem du aufbauen kannst, nicht eines, das beim ersten produktiven Einsatz bricht. Wie du die Inhalte integrierst, absicherst und in deinen Kontext überträgst, liegt bei dir. Die fachliche Grundlage liefern wir, die Verantwortung für den Einsatz bleibt deine.

Mehr entdecken? Lass dich von weiteren ähnlichen Inhalten inspirieren!