Dieses Beispiel verbindet einen Node.js-Server mit einem Browser-Client – vollständig ohne externe Pakete. Der Server liefert eine HTML-Seite und einen kleinen JSON-Endpunkt; der Client ruft die Daten mit fetch ab.
Projektstruktur
node-vibe-example/
├─ package.json
├─ server.js
└─ public/
└─ index.html
Startprompt
„Erstelle einen Node.js-Server nur mit eingebauten Modulen. Er soll eine statische HTML-Datei ausliefern und unter
/api/statusJSON zurückgeben. Der Browser-Client ruft den Endpunkt per Button ab. Verwende ES-Module und behandle Serverfehler.“
package.json
{
"name": "node-vibe-example",
"private": true,
"type": "module",
"scripts": {
"start": "node server.js"
}
}
Server: server.js
import { createServer } from 'node:http';
import { readFile } from 'node:fs/promises';
const port = 3000;
const htmlFile = new URL('./public/index.html', import.meta.url);
const server = createServer(async (request, response) => {
try {
if (request.url === '/api/status') {
response.writeHead(200, { 'content-type': 'application/json' });
response.end(JSON.stringify({
ok: true,
time: new Date().toISOString()
}));
return;
}
if (request.url === '/' || request.url === '/index.html') {
const html = await readFile(htmlFile);
response.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
response.end(html);
return;
}
response.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });
response.end('Nicht gefunden');
} catch (error) {
console.error(error);
response.writeHead(500, { 'content-type': 'application/json' });
response.end(JSON.stringify({ ok: false, error: 'Serverfehler' }));
}
});
server.listen(port, () => {
console.log(`Server läuft auf http://localhost:${port}`);
});
Client: public/index.html
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Node Server & Client</title>
</head>
<body>
<main>
<h1>Node.js Server & Browser-Client</h1>
<button id="load" type="button">Status laden</button>
<pre id="output">Noch keine Daten</pre>
</main>
<script>
const button = document.querySelector('#load');
const output = document.querySelector('#output');
button.addEventListener('click', async () => {
button.disabled = true;
output.textContent = 'Lade …';
try {
const response = await fetch('/api/status');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
output.textContent = JSON.stringify(data, null, 2);
} catch (error) {
output.textContent = `Fehler: ${error.message}`;
} finally {
button.disabled = false;
}
});
</script>
</body>
</html>
Starten und testen
cd node-vibe-example
npm start
Danach http://localhost:3000 im Browser öffnen. Teste zusätzlich http://localhost:3000/api/status und eine unbekannte URL, damit auch JSON-Antwort und 404-Verhalten geprüft sind.
Sinnvolle Folgeprompts
- „Validiere die HTTP-Methode und erlaube für den API-Endpunkt nur GET.“
- „Ergänze einen automatisierten Test mit dem eingebauten Node-Test-Runner.“
- „Füge einen zweiten Endpunkt hinzu, ohne die statische Dateiauslieferung zu verändern.“