OptimoCMSDocs
Guides

Restaurantseite erstellen

Erstelle eine komplette Restaurant-Website mit Menü, Buchungen, Bewertungen und Design Tokens über das OptimoCMS SDK, MCP und die REST API.

Eine komplette Restaurantseite erstellen

In diesem Tutorial baust du Schritt für Schritt eine Restaurant-Website mit:

  • Menüseite mit Kategorien und Gerichten
  • Online-Reservierungen über das Buchungssystem
  • Kundenbewertungen
  • Design Tokens für das Branding
  • Veröffentlichung in Produktion

Jeder Schritt zeigt SDK, MCP und REST Beispiele nebeneinander.


Voraussetzungen

  • Node.js 18+
  • Ein OptimoCMS API-Schlüssel (erstelle einen im Dashboard unter Einstellungen → API)
  • npm install @optimocms/sdk

Schritt 1 — Site erstellen

SDK

import { OptimoCMS } from '@optimocms/sdk';

const client = new OptimoCMS({
  apiKey: process.env.OPTIMOCMS_API_KEY!,
});

const site = await client.sites.create({
  name: 'Ristorante Bella Vista',
  subdomain: 'bellavista',
  language: 'nl',
});

console.log(`Site erstellt: ${site.id}`);

MCP (Cursor / Claude)

Erstelle eine neue Site namens "Ristorante Bella Vista" mit Subdomain "bellavista" auf Niederländisch.

Das MCP-Tool create_site wird aufgerufen mit:

{
  "name": "Ristorante Bella Vista",
  "subdomain": "bellavista",
  "language": "nl"
}

REST

curl -X POST https://api.optimocms.com/v1/sites \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ristorante Bella Vista",
    "subdomain": "bellavista",
    "language": "nl"
  }'

Schritt 2 — Template installieren

Wähle ein Restaurant-Template aus der Bibliothek und installiere es auf deiner Site.

SDK

const templates = await client.templates.list({ category: 'restaurant' });
const template = templates.data[0];

const result = await client.templates.install(site.id, {
  templateId: template.id,
  designTokens: {
    colorPrimary: '#8B0000',
    fontHeading: 'Playfair Display',
    fontBody: 'Inter',
    radiusCard: '12px',
    radiusButton: '8px',
  },
});

console.log(`Template installiert, ${result.pagesCreated.length} Seiten erstellt`);

MCP

Installiere das Restaurant-Template auf Site "bellavista" mit einer dunkelroten Primärfarbe (#8B0000) und Playfair Display als Heading-Schrift.

REST

curl -X POST https://api.optimocms.com/v1/sites/$SITE_ID/templates/install \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "tmpl_restaurant_classic",
    "designTokens": {
      "colorPrimary": "#8B0000",
      "fontHeading": "Playfair Display",
      "fontBody": "Inter",
      "radiusCard": "12px",
      "radiusButton": "8px"
    }
  }'

Schritt 3 — Menüseite befüllen

Erstelle eine Menüseite mit Kategorien und Gerichten als Content Blocks.

SDK

const menuPage = await client.pages.create(site.id, {
  title: 'Speisekarte',
  slug: 'speisekarte',
  status: 'draft',
  blocks: [
    {
      type: 'Hero',
      props: {
        title: 'Unsere Speisekarte',
        subtitle: 'Frische italienische Gerichte, täglich zubereitet',
        backgroundImage: '/images/kitchen.jpg',
      },
    },
    {
      type: 'MenuCategory',
      props: {
        title: "Antipasti",
        items: [
          { name: 'Bruschetta al Pomodoro', price: '€9,50', description: 'Geröstetes Brot mit Tomate und Basilikum' },
          { name: 'Carpaccio di Manzo', price: '€14,00', description: 'Dünn geschnittenes Rindfleisch mit Rucola und Parmesan' },
          { name: 'Burrata con Prosciutto', price: '€16,50', description: 'Cremige Burrata mit Parmaschinken' },
        ],
      },
    },
    {
      type: 'MenuCategory',
      props: {
        title: "Primi Piatti",
        items: [
          { name: 'Spaghetti Carbonara', price: '€16,00', description: 'Klassisch mit Guanciale und Pecorino' },
          { name: 'Risotto ai Funghi Porcini', price: '€18,50', description: 'Cremiges Risotto mit Steinpilzen' },
          { name: 'Tagliatelle al Ragù', price: '€17,00', description: 'Frische Pasta mit langsam gegartem Fleisch' },
        ],
      },
    },
    {
      type: 'MenuCategory',
      props: {
        title: "Dolci",
        items: [
          { name: 'Tiramisù della Casa', price: '€9,00', description: 'Hausgemacht nach Omas Rezept' },
          { name: 'Panna Cotta', price: '€8,50', description: 'Mit Saisonfrüchten und Coulis' },
        ],
      },
    },
  ],
});

console.log(`Menüseite erstellt: ${menuPage.id}`);

MCP

Erstelle eine Menüseite auf Site "bellavista" mit den Kategorien Antipasti, Primi Piatti und Dolci. Füge bei jeder Kategorie 2-3 Gerichte mit Name, Preis und kurzer Beschreibung hinzu.

REST

curl -X POST https://api.optimocms.com/v1/sites/$SITE_ID/pages \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Speisekarte",
    "slug": "speisekarte",
    "status": "draft",
    "blocks": [
      {
        "type": "Hero",
        "props": { "title": "Unsere Speisekarte", "subtitle": "Frische italienische Gerichte" }
      },
      {
        "type": "MenuCategory",
        "props": {
          "title": "Antipasti",
          "items": [
            { "name": "Bruschetta al Pomodoro", "price": "€9,50" },
            { "name": "Carpaccio di Manzo", "price": "€14,00" }
          ]
        }
      }
    ]
  }'

Schritt 4 — Reservierungen aktivieren

Konfiguriere das Buchungssystem, damit Gäste online reservieren können.

SDK

const bookingPage = await client.pages.create(site.id, {
  title: 'Reservieren',
  slug: 'reservieren',
  status: 'published',
  blocks: [
    {
      type: 'Hero',
      props: { title: 'Tisch reservieren', subtitle: 'Wählen Sie Ihr gewünschtes Datum und Ihre Uhrzeit' },
    },
    {
      type: 'BookingWidget',
      props: { serviceId: 'dinner', showStaff: false, showBranch: false },
    },
  ],
});

const slots = await client.booking.getSlots(site.id, {
  serviceId: 'dinner',
  date: '2026-06-15',
});

console.log(`${slots.slots.filter(s => s.available).length} verfügbare Zeitfenster`);

const booking = await client.booking.create(site.id, {
  serviceId: 'dinner',
  date: '2026-06-15',
  startTime: '19:00',
  customer: {
    name: 'Jan de Vries',
    email: 'jan@beispiel.de',
    phone: '+31612345678',
  },
});

console.log(`Reservierung bestätigt: ${booking.id} (${booking.status})`);

MCP

Aktiviere Reservierungen auf Site "bellavista". Erstelle eine Reservierungsseite mit einem Buchungs-Widget für den Dinner-Service.

REST

curl https://api.optimocms.com/v1/sites/$SITE_ID/booking/slots?serviceId=dinner&date=2026-06-15 \
  -H "Authorization: Bearer $API_KEY"

curl -X POST https://api.optimocms.com/v1/sites/$SITE_ID/booking \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "dinner",
    "date": "2026-06-15",
    "startTime": "19:00",
    "customer": {
      "name": "Jan de Vries",
      "email": "jan@beispiel.de"
    }
  }'

Schritt 5 — Design Tokens einstellen

Passe das Branding mit Design Tokens an — diese wirken auf allen Seiten.

SDK

const tokens = await client.designTokens.update(site.id, {
  colorPrimary: '#8B0000',
  colorBackground: '#FFF8F0',
  colorSurface: '#FFFFFF',
  colorText: '#1A1A1A',
  colorTextMuted: '#6B7280',
  fontHeading: 'Playfair Display',
  fontBody: 'Inter',
  radiusCard: '12px',
  radiusButton: '8px',
  radiusInput: '6px',
});

console.log(`Design Tokens aktualisiert: ${tokens.updatedAt}`);

MCP

Aktualisiere die Design Tokens von Site "bellavista": Primärfarbe dunkelrot #8B0000, Hintergrund warmweiß #FFF8F0, Heading-Schrift Playfair Display, Body-Schrift Inter.

REST

curl -X PUT https://api.optimocms.com/v1/sites/$SITE_ID/design-tokens \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "colorPrimary": "#8B0000",
    "colorBackground": "#FFF8F0",
    "colorSurface": "#FFFFFF",
    "colorText": "#1A1A1A",
    "fontHeading": "Playfair Display",
    "fontBody": "Inter",
    "radiusCard": "12px",
    "radiusButton": "8px"
  }'

Schritt 6 — Veröffentlichen

Veröffentliche die Site in Produktion, damit Besucher sie erreichen können.

SDK

const publishResult = await client.sites.publish(site.id);

if (publishResult.status === 'queued' || publishResult.status === 'deploying') {
  console.log(`Site wird veröffentlicht! Deploy ID: ${publishResult.deployId}`);
  console.log(`Live auf: https://bellavista.optimocms.com`);
}

MCP

Veröffentliche Site "bellavista" in Produktion.

REST

curl -X POST https://api.optimocms.com/v1/sites/$SITE_ID/publish \
  -H "Authorization: Bearer $API_KEY"

Antwort:

{
  "siteId": "site_abc123",
  "status": "deploying",
  "deployId": "dpl_xyz789"
}

Komplettes Skript

Hier das vollständige Skript, das alle Schritte kombiniert:

import { OptimoCMS } from '@optimocms/sdk';

const client = new OptimoCMS({
  apiKey: process.env.OPTIMOCMS_API_KEY!,
});

async function buildRestaurantSite() {
  const site = await client.sites.create({
    name: 'Ristorante Bella Vista',
    subdomain: 'bellavista',
    language: 'nl',
  });

  const templates = await client.templates.list({ category: 'restaurant' });
  await client.templates.install(site.id, {
    templateId: templates.data[0].id,
  });

  await client.designTokens.update(site.id, {
    colorPrimary: '#8B0000',
    colorBackground: '#FFF8F0',
    fontHeading: 'Playfair Display',
    fontBody: 'Inter',
    radiusCard: '12px',
    radiusButton: '8px',
  });

  await client.pages.create(site.id, {
    title: 'Speisekarte',
    slug: 'speisekarte',
    status: 'published',
    blocks: [
      { type: 'Hero', props: { title: 'Unsere Speisekarte' } },
      { type: 'MenuCategory', props: { title: 'Antipasti', items: [
        { name: 'Bruschetta', price: '€9,50' },
        { name: 'Carpaccio', price: '€14,00' },
      ]}},
    ],
  });

  await client.pages.create(site.id, {
    title: 'Reservieren',
    slug: 'reservieren',
    status: 'published',
    blocks: [
      { type: 'BookingWidget', props: { serviceId: 'dinner' } },
    ],
  });

  const result = await client.sites.publish(site.id);
  console.log(`✓ Site live auf https://bellavista.optimocms.com (${result.status})`);
}

buildRestaurantSite().catch(console.error);

Nächste Schritte

On this page