Rizo CMS
HomeFeaturesDemoDokumentationFAQ Download
Zurück

Download

Lade das vollständige Rizo CMS herunter: Editor, Login, Server-Speicherung und Zugriffsschutz.

Urheberrechtlich geschützt

Diese Software ist urheberrechtlich geschützt. Weiterverkauf, Weitergabe und Redistribution sind nicht gestattet. Durch den Download akzeptierst du die Lizenzbestimmungen.

Dateistruktur

deine-website/
├── index.html          ← Deine einzige HTML-Seite
├── rizocms.js          ← Rizo CMS Editor
├── login.php           ← Login & Session
├── save.php            ← Speichern & Backup
└── .htaccess           ← Schutzdatei
Die Download-Buttons laden immer die aktuelle Rizo CMS Version: rizocms.js, login.php, save.php und .htaccess. Kein Token und kein Hash müssen in JavaScript eingetragen werden.
rizocms.js
/**
 * ============================================================
 * Rizo CMS - PROPRIETÄRE SOFTWARE
 * ============================================================
 * Copyright (c) 2026 Rizo CMS. Alle Rechte vorbehalten.
 * 
 * LIZENZHINWEIS:
 * Diese Software ist urheberrechtlich geschützt. Die Nutzung
 * ist nur für den persönlichen/geschäftlichen Gebrauch auf
 * eigenen Webseiten gestattet.
 * 
 * VERBOTEN IST:
 * - Weiterverkauf oder kommerzielle Weitergabe
 * - Weitergabe an Dritte (kostenpflichtig)
 * - Modifikation und Redistribution
 * - Entfernen dieses Copyright-Hinweises
 * 
 * Bei Verstößen behalten wir uns rechtliche Schritte vor.
 * Kontakt: [hello@rizocms.com]
 * ============================================================
 */

/**
 * Rizo CMS v2.0.0
 * Ein leichtgewichtiges Rizo-CMS für statische HTML-Seiten
 * MIT SEO SCORE & PHP AUTHENTIFIZIERUNG & BILD-UPLOAD
 * 
 * Verwendung:
 * 1. config.php, api.php und .htaccess im selben Ordner platzieren
 * 2. Script in HTML-Seite einbinden: <script src="rizocms.js"></script>
 * 3. Elemente mit data-editable="name" markieren
 * 4. Bilder mit data-editable="name" data-editable-type="image" markieren
 * 5. STRG+E drücken zum Editieren (Mobil: Stift-Symbol)
 */

(function() {
    'use strict';
    
    // ===== KONFIGURATION =====
    const CONFIG = {
LOGIN_ENDPOINT: 'login.php',
  SAVE_ENDPOINT: 'save.php',
        SHORTCUT_KEY: 'KeyE',
        HIGHLIGHT_COLOR: '#3b82f6',
        SEO_ENABLED: true
    };
    
    // ===== STATE =====
    let isEditMode = false;
    let isLoggedIn = false;
    let currentElement = null;
    let csrfToken = null;
    
    // ===== STYLES =====
    const STYLES = `
        .icms-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0,0,0,0.5);
            z-index: 999998;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .icms-modal {
            background: #1a1a2e;
            border-radius: 12px;
            padding: 32px;
            max-width: 500px;
            width: 90%;
            box-shadow: 0 25px 50px rgba(0,0,0,0.5);
            max-height: 80vh;
            overflow-y: auto;
        }
        .icms-modal h2 {
            color: #fff;
            margin: 0 0 8px 0;
            font-size: 24px;
        }
        .icms-modal p {
            color: #888;
            margin: 0 0 24px 0;
            font-size: 14px;
        }
        .icms-input {
            width: 100%;
            padding: 12px 16px;
            border: 1px solid #333;
            border-radius: 8px;
            background: #0f0f1a;
            color: #fff;
            font-size: 14px;
            margin-bottom: 12px;
            box-sizing: border-box;
        }
        .icms-input:focus {
            outline: none;
            border-color: ${CONFIG.HIGHLIGHT_COLOR};
        }
        .icms-btn {
            width: 100%;
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            font-size: 14px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
        }
        .icms-btn-primary {
            background: ${CONFIG.HIGHLIGHT_COLOR};
            color: #fff;
        }
        .icms-btn-primary:hover {
            opacity: 0.9;
        }
        .icms-btn-secondary {
            background: #2a2a3e;
            color: #fff;
            margin-top: 8px;
        }
        .icms-btn-secondary:hover {
            background: #3a3a4e;
        }
        .icms-error {
            color: #ef4444;
            font-size: 12px;
            margin-top: 8px;
        }
        .icms-image-preview {
            width: 100%;
            max-height: 300px;
            object-fit: cover;
            border-radius: 8px;
            margin-bottom: 16px;
            border: 2px solid #333;
        }
        .icms-file-input-wrapper {
            position: relative;
            margin-bottom: 16px;
        }
        .icms-file-input {
            width: 100%;
            padding: 12px;
            border: 2px dashed #333;
            border-radius: 8px;
            background: #0f0f1a;
            color: #888;
            cursor: pointer;
            text-align: center;
            transition: all 0.2s;
        }
        .icms-file-input:hover {
            border-color: ${CONFIG.HIGHLIGHT_COLOR};
            color: #fff;
        }
        .icms-toolbar {
            position: fixed;
            top: 20px;
            right: 20px;
            background: #1a1a2e;
            border-radius: 12px;
            padding: 12px;
            display: flex;
            gap: 8px;
            z-index: 999999;
            box-shadow: 0 10px 40px rgba(0,0,0,0.3);
        }
        .icms-toolbar button {
            padding: 8px 16px;
            border: none;
            border-radius: 6px;
            font-size: 12px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.2s;
            background: #2a2a3e;
            color: #fff;
        }
        .icms-toolbar button:hover {
            background: #3a3a4e;
        }
        .icms-toolbar button.active {
            background: ${CONFIG.HIGHLIGHT_COLOR};
        }
        .icms-editable {
            outline: 2px dashed ${CONFIG.HIGHLIGHT_COLOR}44;
            outline-offset: 4px;
            transition: all 0.2s;
        }
        .icms-editable:hover {
            outline-color: ${CONFIG.HIGHLIGHT_COLOR};
            cursor: pointer;
        }
        .icms-editing {
            outline: 2px solid ${CONFIG.HIGHLIGHT_COLOR};
            outline-offset: 4px;
        }
        .icms-seo-panel {
            position: fixed;
            top: 80px;
            right: 20px;
            width: 320px;
            background: #1a1a2e;
            border-radius: 12px;
            padding: 20px;
            z-index: 999998;
            box-shadow: 0 10px 40px rgba(0,0,0,0.3);
            max-height: 70vh;
            overflow-y: auto;
        }
        .icms-seo-panel h3 {
            color: #fff;
            margin: 0 0 16px 0;
            font-size: 16px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .icms-seo-score {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 12px;
            background: #0f0f1a;
            border-radius: 8px;
            margin-bottom: 12px;
        }
        .icms-score-circle {
            width: 48px;
            height: 48px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: 700;
            font-size: 16px;
            color: #fff;
        }
        .icms-score-good { background: #22c55e; }
        .icms-score-medium { background: #f59e0b; }
        .icms-score-bad { background: #ef4444; }
        .icms-seo-item {
            padding: 12px;
            background: #0f0f1a;
            border-radius: 8px;
            margin-bottom: 8px;
        }
        .icms-seo-item-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 4px;
        }
        .icms-seo-item-title {
            color: #fff;
            font-size: 13px;
            font-weight: 500;
        }
        .icms-seo-item-value {
            color: #888;
            font-size: 12px;
        }
        .icms-seo-bar {
            height: 4px;
            background: #333;
            border-radius: 2px;
            overflow: hidden;
        }
        .icms-seo-bar-fill {
            height: 100%;
            border-radius: 2px;
            transition: width 0.3s;
        }
        .icms-copyright {
            font-size: 10px;
            color: #666;
            text-align: center;
            margin-top: 16px;
            padding-top: 12px;
            border-top: 1px solid #333;
        }
    `;
    
    // ===== AUTH FUNKTIONEN =====
    async function checkAuth() {
        try {
            const res = await fetch(CONFIG.AUTH_ENDPOINT, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ action: 'check' })
            });
            const data = await res.json();
            isLoggedIn = data.logged_in;
            csrfToken = data.csrf_token;
            return isLoggedIn;
        } catch (e) {
            console.warn('Auth check failed, running in standalone mode');
            isLoggedIn = true;
            return true;
        }
    }
    
    async function login(username, password) {
        try {
            const res = await fetch(CONFIG.AUTH_ENDPOINT, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ action: 'login', username, password })
            });
            const data = await res.json();
            if (data.success) {
                isLoggedIn = true;
                csrfToken = data.csrf_token;
            }
            return data;
        } catch (e) {
            return { success: false, message: 'Verbindungsfehler' };
        }
    }
    
    async function logout() {
        try {
            await fetch(CONFIG.AUTH_ENDPOINT, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ action: 'logout' })
            });
        } catch (e) {}
        isLoggedIn = false;
        csrfToken = null;
        exitEditMode();
    }
    
    // ===== UI FUNKTIONEN =====
    function injectStyles() {
        const style = document.createElement('style');
        style.textContent = STYLES;
        document.head.appendChild(style);
    }
    
    function showLoginModal() {
        const overlay = document.createElement('div');
        overlay.className = 'icms-overlay';
        overlay.innerHTML = `
            <div class="icms-modal">
                <h2>🔐 Rizo CMS</h2>
                <p>Melde dich an, um Inhalte zu bearbeiten</p>
                <input type="text" class="icms-input" id="icms-username" placeholder="Benutzername">
                <input type="password" class="icms-input" id="icms-password" placeholder="Passwort">
                <button class="icms-btn icms-btn-primary" id="icms-login-btn">Anmelden</button>
                <div class="icms-error" id="icms-error" style="display:none"></div>
                <div class="icms-copyright">© 2026 Rizo CMS - Urheberrechtlich geschützt</div>
            </div>
        `;
        document.body.appendChild(overlay);
        
        const loginBtn = document.getElementById('icms-login-btn');
        const usernameInput = document.getElementById('icms-username');
        const passwordInput = document.getElementById('icms-password');
        const errorDiv = document.getElementById('icms-error');
        
        async function doLogin() {
            const result = await login(usernameInput.value, passwordInput.value);
            if (result.success) {
                overlay.remove();
                enterEditMode();
            } else {
                errorDiv.textContent = result.message;
                errorDiv.style.display = 'block';
            }
        }
        
        loginBtn.addEventListener('click', doLogin);
        passwordInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') doLogin();
        });
        
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) overlay.remove();
        });
        
        usernameInput.focus();
    }
    
    function showImageUploadModal(element) {
        const overlay = document.createElement('div');
        overlay.className = 'icms-overlay';
        
        const currentSrc = element.src || element.style.backgroundImage.replace(/url$$['"](.+)['"]$$/, '$1');
        let newImageData = null;
        
        overlay.innerHTML = `
            <div class="icms-modal">
                <h2>🖼️ Bild ändern</h2>
                <p>Aktuelles Bild oder neues Bild hochladen</p>
                
                <div style="margin-bottom: 16px;">
                    <p style="font-size: 12px; color: #888; margin-bottom: 8px;">Aktuelles Bild:</p>
                    <img src="${currentSrc}" class="icms-image-preview" alt="Current" />
                </div>
                
                <div class="icms-file-input-wrapper">
                    <label for="icms-file-input" class="icms-file-input">
                        📁 Neues Bild auswählen
                    </label>
                    <input type="file" id="icms-file-input" accept="image/*" style="display: none;" />
                </div>
                
                <div id="icms-new-preview" style="display: none; margin-bottom: 16px;">
                    <p style="font-size: 12px; color: #888; margin-bottom: 8px;">Neues Bild:</p>
                    <img id="icms-new-image" class="icms-image-preview" alt="New" />
                </div>
                
                <button class="icms-btn icms-btn-primary" id="icms-save-image" disabled>Bild speichern</button>
                <button class="icms-btn icms-btn-secondary" id="icms-cancel-image">Abbrechen</button>
                
                <div class="icms-copyright">© 2026 Rizo CMS</div>
            </div>
        `;
        
        document.body.appendChild(overlay);
        
        const fileInput = document.getElementById('icms-file-input');
        const fileLabel = fileInput.previousElementSibling;
        const newPreview = document.getElementById('icms-new-preview');
        const newImage = document.getElementById('icms-new-image');
        const saveBtn = document.getElementById('icms-save-image');
        const cancelBtn = document.getElementById('icms-cancel-image');
        
        fileLabel.addEventListener('click', () => fileInput.click());
        
        fileInput.addEventListener('change', (e) => {
            const file = e.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = (event) => {
                    newImageData = event.target.result;
                    newImage.src = newImageData;
                    newPreview.style.display = 'block';
                    saveBtn.disabled = false;
                    fileLabel.textContent = '✓ ' + file.name;
                    fileLabel.style.borderColor = CONFIG.HIGHLIGHT_COLOR;
                    fileLabel.style.color = '#fff';
                };
                reader.readAsDataURL(file);
            }
        });
        
        saveBtn.addEventListener('click', () => {
            if (newImageData) {
                if (element.tagName === 'IMG') {
                    element.src = newImageData;
                } else {
                    element.style.backgroundImage = `url('${newImageData}')`;
                }
                
                const key = element.getAttribute('data-editable');
                const data = JSON.parse(localStorage.getItem(CONFIG.STORAGE_KEY) || '{}');
                data[key] = { type: 'image', value: newImageData };
                localStorage.setItem(CONFIG.STORAGE_KEY, JSON.stringify(data));
                
                overlay.remove();
            }
        });
        
        cancelBtn.addEventListener('click', () => overlay.remove());
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) overlay.remove();
        });
    }
    
    function createToolbar() {
        const toolbar = document.createElement('div');
        toolbar.className = 'icms-toolbar';
        toolbar.id = 'icms-toolbar';
        toolbar.innerHTML = `
            <button id="icms-btn-save">💾 Speichern</button>
            <button id="icms-btn-export">📄 Export</button>
            <button id="icms-btn-seo">📊 SEO</button>
            <button id="icms-btn-reset">🔄 Reset</button>
            <button id="icms-btn-logout">🚪 Logout</button>
            <button id="icms-btn-exit">✕</button>
        `;
        document.body.appendChild(toolbar);
        
        document.getElementById('icms-btn-save').addEventListener('click', saveChanges);
        document.getElementById('icms-btn-export').addEventListener('click', exportHTML);
        document.getElementById('icms-btn-seo').addEventListener('click', toggleSEOPanel);
        document.getElementById('icms-btn-reset').addEventListener('click', resetChanges);
        document.getElementById('icms-btn-logout').addEventListener('click', logout);
        document.getElementById('icms-btn-exit').addEventListener('click', exitEditMode);
    }
    
    // ===== SEO FUNKTIONEN =====
    function calculateReadability(text) {
        const words = text.split(/\s+/).filter(w => w.length > 0);
        const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0);
        const syllables = words.reduce((acc, word) => {
            return acc + (word.match(/[aeiouyäöü]/gi) || []).length;
        }, 0);
        
        if (words.length === 0 || sentences.length === 0) return 0;
        
        const avgWordsPerSentence = words.length / sentences.length;
        const avgSyllablesPerWord = syllables / words.length;
        
        // Flesch-Reading-Ease (German adaptation)
        const score = 180 - avgWordsPerSentence - (58.5 * avgSyllablesPerWord);
        return Math.max(0, Math.min(100, score));
    }
    
    function getKeywords(text) {
        const stopWords = ['der', 'die', 'das', 'und', 'ist', 'in', 'zu', 'den', 'mit', 'von', 'für', 'auf', 'ein', 'eine', 'einer', 'eines', 'einem', 'einen', 'dem', 'des', 'im', 'am', 'zum', 'zur', 'als', 'sich', 'bei', 'nach', 'aus', 'um', 'oder', 'auch', 'nicht', 'werden', 'wird', 'kann', 'sind', 'hat', 'haben'];
        const words = text.toLowerCase().match(/[a-zäöüß]+/gi) || [];
        const filtered = words.filter(w => w.length > 3 && !stopWords.includes(w));
        const freq = {};
        filtered.forEach(w => freq[w] = (freq[w] || 0) + 1);
        return Object.entries(freq).sort((a, b) => b[1] - a[1]).slice(0, 5).map(e => e[0]);
    }
    
    function analyzeSEO() {
        const title = document.title || '';
        const description = document.querySelector('meta[name="description"]')?.content || '';
        const h1 = document.querySelector('h1')?.textContent || '';
        const bodyText = document.body.textContent;
        
        const checks = {
            title: {
                label: 'Title',
                value: title.length,
                min: 30,
                max: 60,
                score: title.length >= 30 && title.length <= 60 ? 100 : Math.max(0, 100 - Math.abs(45 - title.length) * 2)
            },
            description: {
                label: 'Meta Description',
                value: description.length,
                min: 120,
                max: 160,
                score: description.length >= 120 && description.length <= 160 ? 100 : Math.max(0, 100 - Math.abs(140 - description.length))
            },
            h1: {
                label: 'H1 Überschrift',
                value: h1.length,
                min: 20,
                max: 70,
                score: h1.length >= 20 && h1.length <= 70 ? 100 : Math.max(0, 100 - Math.abs(45 - h1.length) * 2)
            },
            readability: {
                label: 'Lesbarkeit',
                value: Math.round(calculateReadability(bodyText)),
                min: 60,
                max: 100,
                score: calculateReadability(bodyText)
            },
            keywords: {
                label: 'Keywords',
                value: getKeywords(bodyText).join(', '),
                score: getKeywords(bodyText).length >= 3 ? 100 : getKeywords(bodyText).length * 33
            }
        };
        
        const totalScore = Math.round(
            Object.values(checks).reduce((acc, check) => acc + check.score, 0) / Object.keys(checks).length
        );
        
        return { checks, totalScore };
    }
    
    function createSEOPanel() {
        const existing = document.getElementById('icms-seo-panel');
        if (existing) {
            existing.remove();
            return;
        }
        
        const { checks, totalScore } = analyzeSEO();
        
        const panel = document.createElement('div');
        panel.className = 'icms-seo-panel';
        panel.id = 'icms-seo-panel';
        
        const scoreClass = totalScore >= 80 ? 'icms-score-good' : totalScore >= 50 ? 'icms-score-medium' : 'icms-score-bad';
        
        let html = `
            <h3>📊 SEO Score</h3>
            <div class="icms-seo-score">
                <div class="icms-score-circle ${scoreClass}">${totalScore}</div>
                <div>
                    <div style="color: #fff; font-weight: 600; margin-bottom: 4px;">
                        ${totalScore >= 80 ? 'Sehr gut!' : totalScore >= 50 ? 'OK' : 'Verbesserung nötig'}
                    </div>
                    <div style="color: #888; font-size: 12px;">Gesamt-Score</div>
                </div>
            </div>
        `;
        
        for (const [key, check] of Object.entries(checks)) {
            const percent = Math.min(100, check.score);
            const color = check.score >= 80 ? '#22c55e' : check.score >= 50 ? '#f59e0b' : '#ef4444';
            
            html += `
                <div class="icms-seo-item">
                    <div class="icms-seo-item-header">
                        <span class="icms-seo-item-title">${check.label}</span>
                        <span class="icms-seo-item-value">${check.value}${key !== 'keywords' ? '/' + check.max : ''}</span>
                    </div>
                    <div class="icms-seo-bar">
                        <div class="icms-seo-bar-fill" style="width: ${percent}%; background: ${color};"></div>
                    </div>
                </div>
            `;
        }
        
        html += `<div class="icms-copyright">© 2026 Rizo CMS</div>`;
        
        panel.innerHTML = html;
        document.body.appendChild(panel);
    }
    
    function toggleSEOPanel() {
        createSEOPanel();
    }
    
    // ===== STORAGE FUNKTIONEN =====
    function saveChanges() {
        const data = {};
        const editables = document.querySelectorAll('[data-editable]');
        
        editables.forEach(el => {
            const key = el.getAttribute('data-editable');
            const type = el.getAttribute('data-editable-type') || 'text';
            
            if (type === 'image') {
                const value = el.tagName === 'IMG' ? el.src : el.style.backgroundImage;
                data[key] = { type, value };
            } else {
                data[key] = { type, value: el.innerHTML };
            }
        });
        
        localStorage.setItem(CONFIG.STORAGE_KEY, JSON.stringify(data));
        alert('✓ Änderungen gespeichert!');
    }
    
    function loadChanges() {
        const data = JSON.parse(localStorage.getItem(CONFIG.STORAGE_KEY) || '{}');
        
        Object.entries(data).forEach(([key, item]) => {
            const el = document.querySelector(`[data-editable="${key}"]`);
            if (el) {
                if (item.type === 'image') {
                    if (el.tagName === 'IMG') {
                        el.src = item.value;
                    } else {
                        el.style.backgroundImage = item.value;
                    }
                } else {
                    el.innerHTML = item.value;
                }
            }
        });
    }
    
    function resetChanges() {
        if (confirm('Alle Änderungen zurücksetzen?')) {
            localStorage.removeItem(CONFIG.STORAGE_KEY);
            location.reload();
        }
    }
    
    // ===== EXPORT FUNKTIONEN =====
    function exportHTML() {
        const clone = document.documentElement.cloneNode(true);
        
        // Remove CMS elements
        clone.querySelectorAll('.icms-toolbar, .icms-seo-panel, .icms-overlay').forEach(el => el.remove());
        clone.querySelectorAll('[data-editable]').forEach(el => {
            el.classList.remove('icms-editable', 'icms-editing');
            el.removeAttribute('contenteditable');
        });
        
        const html = '<!DOCTYPE html>\n' + clone.outerHTML;
        const blob = new Blob([html], { type: 'text/html' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `exported-${Date.now()}.html`;
        a.click();
        URL.revokeObjectURL(url);
    }
    
    // ===== EDIT FUNKTIONEN =====
    function enterEditMode() {
        isEditMode = true;
        createToolbar();
        
        const editables = document.querySelectorAll('[data-editable]');
        editables.forEach(el => {
            el.classList.add('icms-editable');
            el.addEventListener('click', handleElementClick);
        });
        
        loadChanges();
    }
    
    function exitEditMode() {
        isEditMode = false;
        
        const toolbar = document.getElementById('icms-toolbar');
        if (toolbar) toolbar.remove();
        
        const seoPanel = document.getElementById('icms-seo-panel');
        if (seoPanel) seoPanel.remove();
        
        const editables = document.querySelectorAll('[data-editable]');
        editables.forEach(el => {
            el.classList.remove('icms-editable', 'icms-editing');
            el.contentEditable = 'false';
            el.removeEventListener('click', handleElementClick);
        });
        
        currentElement = null;
    }
    
    function handleElementClick(e) {
        e.preventDefault();
        e.stopPropagation();
        
        const element = e.currentTarget;
        const editableType = element.getAttribute('data-editable-type');
        
        // Handle image editing
        if (editableType === 'image') {
            showImageUploadModal(element);
            return;
        }
        
        // Handle text editing
        if (currentElement) {
            currentElement.classList.remove('icms-editing');
            currentElement.contentEditable = 'false';
        }
        
        currentElement = element;
        currentElement.classList.add('icms-editing');
        currentElement.contentEditable = 'true';
        currentElement.focus();
    }
    
    // ===== INITIALIZATION =====
    async function init() {
        injectStyles();
        
        // Keyboard shortcut
        document.addEventListener('keydown', async (e) => {
            if (e.altKey && e.code === CONFIG.SHORTCUT_KEY) {
                e.preventDefault();
                
                if (!isEditMode) {
                    const authed = await checkAuth();
                    if (!authed) {
                        showLoginModal();
                    } else {
                        enterEditMode();
                    }
                } else {
                    exitEditMode();
                }
            }
        });
    }
    
    // Start when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
    
})();

Schnellstart

  1. Lade rizocms.js, login.php, save.php und .htaccess herunter
  2. Platziere alle vier Dateien im selben Ordner wie deine HTML-Seiten
  3. Ein separates config.php ist nicht erforderlich. Beim ersten Login legst du dein Passwort fest; danach bleibt es serverseitig gespeichert.
  4. RizoCMS erkennt editierbare Elemente automatisch; manuelle Marker sind optional
  5. Bilder werden im Edit-Modus automatisch erkannt und können direkt ersetzt werden
  6. Binde das Script ein: <script src="rizocms.js"></script>
  7. Drücke STRG + E zum Editieren. Mobil nutzt du das Stift-Symbol.

Konfigurierbare Features

SEO Analyzer

Live SEO-Score beim Bearbeiten

Bild-Upload

Bilder direkt hochladen

HTML Export

Bereinigte HTML-Datei exportieren

Server-Speicherung

Sicheres Speichern mit Backup über save.php

Keyboard Shortcuts

STRG+E am Desktop, Stift-Symbol auf Mobilgeräten

CSRF Schutz

Sicherheit gegen Angriffe

Rizo CMS

Ein kostenloses Hobbyprojekt für Webseitenbetreiber. Verwandle statische HTML-Seiten in editierbare Webseiten – ohne komplizierte Installation.

Lizenzbedingungen anzeigen

Produkt

  • Live Demo
  • Dokumentation
  • Download
  • FAQ

Rechtliches

  • Impressum
  • Datenschutz
  • Lizenz
© 2026 Rizo CMS. Alle Rechte vorbehalten.