Der Dreamcodes OmniChat OS ist eine hochperformante, webbasierte Chat Applikation im modernen Stil, die maximale Geschwindigkeit mit einem intuitiven Benutzererlebnis kombiniert. Entwickelt für Communitys, die Wert auf eine schlanke Infrastruktur (SQLite) und moderne Features (Google Auth) legen.
🌟 Key Features
- Modernes UI/UX: Inspiriert vom Look & Feel marktführender Messenger, optimiert für Desktop und mobile Endgeräte.
- OmniChat Login System: Flexibler Zugang über klassischen Benutzernamen, dedizierter Admin Login mit Passwortschutz oder schneller Google Account Sync.
- Echtzeit Kommunikation: Dank optimierter Sync Intervalle und SQLite Backend fließen Nachrichten ohne spürbare Verzögerung.
- Dynamisches Raum Management: Nutzer können on the fly neue Räume erstellen. Die Sidebar gibt jederzeit Überblick über aktive Räume und die Teilnehmeranzahl.
- Full Emoji Engine: Eine integrierte Bibliothek mit über 500 Unicode Emojis (kategorisiert) für maximale Ausdruckskraft.
- Admin Power: Integrierte IP Erkennung für Administratoren zur Überwachung der Sicherheit innerhalb der Chat Umgebung.
- Leichtgewichtige Installation: Kein SQL Server nötig. Ein PHP fähiger Webspace reicht aus, die Datenbank konfiguriert sich beim ersten Start von selbst.
🛠️ Technische Details
- Backend: PHP 8.x & SQLite3
- Frontend: Tailwind CSS, JavaScript (Vanilla ES6)
- Authentifizierung: Session basiert & Google OAuth 2.0 Integration
📦 Installation
- Ändere Admin Namen und Password. Lade die
index.phpauf deinen Server hoch. - Stelle sicher, dass das Verzeichnis Schreibrechte für die Erstellung der
.dbDatei besitzt. - (Optional) Trage deine Google Client ID im Header ein, um den Google Login zu aktivieren.
- Starte den Chat und logge dich ein! Die .css , .js und zugehörige Datenbank werden automatisch beim ersten Aufruf erstellt.
Dieses Premium Tutorial ist exklusiv für unsere Newsletter Abonnenten!
Dieses Tutorial ist zum sofort lesen. Gebe deine eMail Adresse zum Freischalten ein!
<?php
/**
* OmniChat OS v3.5
* Made by Dreamcodes.NET
*/
session_start();
if (!file_exists('style.css')) {
$css_content = "
:root { --wa-bg: #0b141a; --wa-header: #202c33; --wa-sidebar: #111b21; --wa-green: #00a884; --wa-bubble-out: #005c4b; --wa-bubble-in: #202c33; }
body { background: #0b141a; color: #e9edef; font-family: 'Segoe UI', sans-serif; height: 100vh; overflow: hidden; margin: 0; }
.app-wrap { display: flex; width: 100%; height: 100%; max-width: 1600px; margin: 0 auto; background: var(--wa-bg); }
.sidebar { width: 30%; min-width: 320px; border-right: 1px solid rgba(255,255,255,0.1); display: flex; flex-direction: column; background: var(--wa-sidebar); }
.chat-view { flex: 1; display: flex; flex-direction: column; background-image: url('https://user-images.githubusercontent.com/15075759/28719144-86dc0f70-73b1-11e7-911d-60d70fcded21.png'); background-color: rgba(11,20,26,0.97); background-blend-mode: darken; }
.bubble { position: relative; padding: 8px 12px 14px 12px; margin: 4px 30px; max-width: 75%; font-size: 14.5px; box-shadow: 0 1px 0.5px rgba(0,0,0,0.15); border-radius: 8px; }
.bubble-out { background: var(--wa-bubble-out); align-self: flex-end; border-top-right-radius: 0; }
.bubble-out::after { content: ''; position: absolute; top: 0; right: -8px; border: 8px solid transparent; border-top-color: var(--wa-bubble-out); }
.bubble-in { background: var(--wa-bubble-in); align-self: flex-start; border-top-left-radius: 0; }
.bubble-in::after { content: ''; position: absolute; top: 0; left: -8px; border: 8px solid transparent; border-top-color: var(--wa-bubble-in); }
.time { position: absolute; bottom: 4px; right: 8px; font-size: 10px; opacity: 0.5; }
#emoji-picker { display: none; height: 280px; background: #111b21; border-top: 1px solid #2a3942; overflow-y: auto; padding: 15px; }
#emoji-picker.active { display: block; }
.emoji-item { font-size: 26px; cursor: pointer; padding: 5px; width: 45px; display: inline-block; text-align: center; }
.dc-link { color: var(--wa-green); text-decoration: none; font-weight: bold; transition: 0.3s; }
.dc-link:hover { opacity: 0.7; }
.room-active { background: #2a3942 !important; border-left: 4px solid var(--wa-green); }
";
file_put_contents('style.css', $css_content);
}
if (!file_exists('basis.js')) {
$js_content = "
let lastId = 0;
const emojis = ["😀","😃","😄","😁","😆","😅","😂","🤣","😊","😇","🙂","🙃","😉","😌","😍","🥰","😘","😗","😙","😚","😋","😛","😝","😜","🤪","🤨","🧐","🤓","😎","🤩","🥳","😏","😒","😞","😔","😟","😕","🙁","☹️","😣","😖","😫","😩","🥺","😢","😭","😤","😠","😡","🤬","🤯","😳","🥵","🥶","😱","😨","😰","😥","😓","🤗","🤔","🤭","🤫","🤥","😶","😐","😑","😬","🙄","😯","😦","😧","😮","😲","🥱","😴","🤤","😪","😵","🤐","🥴","🤢","🤮","🤧","😷","🤒","🤕","🤑","🤠","😈","👿","👹","👺","🤡","👻","💀","☠️","👽","👾","🤖","💩","👋","🤚","🖐️","✋","🖖","👌","🤌","🤏","✌️","🤞","🤟","🤘","🤙","👈","👉","👆","🖕","👇","☝️","👍","👎","✊","👊","🤛","🤜","👏","🙌","👐","🤲","🤝","🙏","✍️","💅","🤳","💪","🦾","🦵","🦿","🦶","👂","🦻","👃","🧠","🦷","🦴","👀","👁️","👅","👄","👶","🧒","👦","👧","🧑","👱","👨","🧔","👩","🧓","👴","👵","🙍","🙎","🙅","🙆","💁","🙋","🧏","🙇","🤦","🤷","👮","🕵️","💂","👷","🤴","👸","👳","👲","🧕","🤵","👰","🤰","🤱","👼","🎅","🤶","🦸","🦹","🧙","🧚","🧛","🧜","🧝","🧞","🧟","💆","💇","🚶","🧍","🧎","🏃","💃","🕺","👯","🧖","🧗","⛷️","🏂","🏌️","🏄","🚣","🏊","⛹️","🏋️","🚴","🚵","🤸","🤼","🤽","🤾","🤹","🧘","🛀","🛌","👫","💏","💑","👪","🗣️","👤","👥","🫂","🐵","🐒","🦍","🦧","🐶","🐕","🐩","🐺","🦊","🦝","🐱","🐈","🦁","🐯","🐅","🐆","🐴","🐎","🦄","🦓","🦌","🐮","🐂","🐃","🐄","🐷","🐖","🐗","🐽","🐏","🐑","🐐","🐪","🐫","🦒","🐘","🦣","🦏","🦛","🐭","🐹","🐰","🐿️","🦔","🦇","🐻","🐨","🐼","🦦","🦨","🦘","🦡","🐾","🦃","🐔","🐓","🐣","🐤","🐥","🐦","🐧","🕊️","🦅","🦆","🦢","🦉","🦩","🦚","🦜","🐸","🐊","🐢","🦎","💃","🐲","🐉","🦖","🦕","🐳","🐋","🐬","🦭","🐟","🐠","🐡","🦈","🐙","🐚","🐌","🦋","🐛","🐜","🐝","🐞","🦗","🕷️","🕸️","🦂","🦟","💐","🌸","💮","🌹","🌺","🌻","🌼","🌷","🌱","🌲","🌳","🌴","🌵","🌾","🌿","🍀","🍁","🍂","🍃","🍇","🍈","🍉","🍊","🍋","🍌","🍍","🥭","🍎","🍏","🍐","🍑","🍒","🍓","🫐","🥝","🍅","🫒","🥥","🥑","🍆","🥔","🥕","🌽","🌶️","🫑","🥒","🥬","🥦","🧄","🧅","🍄","🥜","🍞","🥐","🥖","🫓","🥨","🥯","🥞","🧇","🧀","🍖","🍗","🥩","🥓","🍔","🍟","🍕","🌭","🥪","🌮","🌯","🥗","🍿","🧈","🧂","🥚","🍳","🥘","🍲","🥣","🥗","🍿","🍱","🍘","🍙","🍚","🍛","🍜","🍠","🍢","🍣","🍤","🍥","🥮","🍡","🥟","🥠","🥡","🦀","🦞","🦐","🦑","🦪","🍦","🍧","🍨","🍩","🍪","🎂","🍰","🧁","🥧","🍫","🍬","🍭","🍮","🍯","🍼","🥛","☕","🫖","🍵","🍶","🍾","🍷","🍸","🍹","🍺","🍻","🥂","🥃","🥤","🧃","🧉","🧊","🥢","🍽️","🍴","🥄","🔪","🏺","🌍","🌎","🌏","🌐","🗺️","🗾","🧭","🏔️","⛰️","🌋","🗻","🏕️","🏖️","🏜️","🏝️","🏞️","🏟️","🏛️","🏗️","🧱","🏘️","🏚️","🏠","🏡","🏢","🏣","🏤","🏥","🏦","🏨","🏩","🏪","🏫","🏬","🏭","🏯","🏰","💒","🗼","🗽","⛪","🕌","🛕","🕍","⛩️","🕋","⛲","⛺","🌁","🌃","🏙️","🌄","🌅","🌆","🌇","🌉","♨️","🎠","🎡","🎢","💈","🎪","🚂","🚃","🚄","🚅","🚆","🚇","🚈","🚉","🚊","🚝","🚞","🚋","🚌","🚍","🚎","🚐","🚑","🚒","🚓","🚔","🚕","🚖","🚗","🚘","🚙","🛻","🚚","🚛","🚜","🏎️","🏍️","🛵","🦽","🦼","🛺","🚲","🛴","🛹","🛼","🚏","🛣️","🛤️","🛢️","⛽","🚨","🚥","🚦","🛑","🚧","⚓","⛵","🛶","🚤","🛳️","⛴️","🛥️","🚢","✈️","🛩️","🛫","🛬","🪂","💺","🚁","🚟","🚠","🚡","🛰️","🚀","🛸","🛎️","🧳","⌛","⏳","⌚","⏰","⏱️","⏲️","🕰️","🕛","🕧","🕐","🕜","🕑","🕝","🕒","🕞","🕓","🕟","🕔","🕠","🕕","🕡","🕖","🕢","🕗","🕣","🕘","🕤","🕙","🕥","🕚","🕦","🌑","🌒","🌓","🌔","🌕","🌖","🌗","🌘","🌙","🌚","🌛","🌜","🌡️","☀️","🌝","🌞","🪐","⭐","🌟","🌠","🌌","☁️","⛅","⛈️","🌤️","🌥️","🌦️","🌧️","🌨️","🌩️","🌪️","🌫️","🌬️","🌀","🌈","🌂","☂️","☔","⛱️","⚡","❄️","☃️","⛄","☄️","🔥","💧","🌊","🎃","🎄","🎆","🎇","🧨","✨","🎈","🎉","🎊","🎀","🎁","🎗️","🎟️","🎫","🎖️","🏆","🏅","🥇","🥈","🥉","⚽","⚾","🥎","🏀","🏐","🏈","🏉","🎾","🥏","🎳","🏏","🏑","🏒","🥍","🏓","🏸","🥊","🥋","🥅","⛳","⛸️","🎣","🤿","🎽","🎿","🛷","🥌","🎯","🪀","🪁","🎱","🔮","🪄","🧿","🎮","🕹️","🎰","🎲","🧩","🧸","🪅","🪆","♠️","♥️","♦️","♣️","♟️","🃏","🀄","🎴","🎭","🖼️","🎨","🧵","🪡","🧶","🪢"];
function toggleAdmin(v) { document.getElementById('adm-p').classList.toggle('hidden', v.toLowerCase() !== 'admin'); }
async function login() {
const u = document.getElementById('u').value, p = document.getElementById('p').value, r = document.getElementById('r').value || 'Lobby';
const res = await fetch('?action=login', { method: 'POST', body: JSON.stringify({ user: u, pass: p, room: r }) });
const d = await res.json();
if(d.success) location.reload(); else alert(d.error);
}
function handleGoogleLogin(response) {
const data = JSON.parse(atob(response.credential.split('.')[1]));
fetch('?action=login', { method: 'POST', body: JSON.stringify({ user: data.name, room: 'Lobby' }) }).then(() => location.reload());
}
async function sync(cU) {
try {
const res = await fetch('?action=sync&last_id=' + lastId);
const d = await res.json();
if(d.kicked) location.href = '?logout=1';
const box = document.getElementById('chat-box'), rL = document.getElementById('room-list');
document.getElementById('header-room-name').innerText = d.curRoom;
d.messages.forEach(m => {
const div = document.createElement('div');
div.className = 'bubble ' + (m.user == cU ? 'bubble-out' : 'bubble-in');
div.innerHTML = '<span class=\"block text-[11px] font-bold mb-1\" style=\"color:'+m.color+'\">'+m.user+'</span>'+m.msg+'<span class=\"time\">'+m.time+'</span>';
box.appendChild(div); lastId = m.id; box.scrollTop = box.scrollHeight;
});
rL.innerHTML = d.rooms.map(room => `
<div onclick=\"switchRoom('\${room.room}')\" class=\"p-4 flex items-center gap-4 cursor-pointer hover:bg-[#202c33] border-b border-white/5 \${room.room == d.curRoom ? 'room-active' : ''}\">
<div class=\"w-10 h-10 bg-emerald-700/20 rounded-full flex items-center justify-center font-bold text-emerald-500\">#</div>
<div class=\"flex-1\">
<div class=\"font-bold text-sm\">\${room.room}</div>
<div class=\"text-[11px] opacity-50\">\${room.cnt} online</div>
</div>
</div>`).join('');
} catch(e) {}
}
async function send() {
const m = document.getElementById('msg'); if(!m.value) return;
await fetch('?action=send', { method: 'POST', body: JSON.stringify({ msg: m.value }) });
m.value = '';
}
function toggleEmoji() { document.getElementById('emoji-picker').classList.toggle('active'); }
function createRoom() { const r = prompt('Raum Name:'); if(r) switchRoom(r); }
async function switchRoom(r) {
await fetch('?action=switch', { method: 'POST', body: JSON.stringify({ room: r }) });
location.reload();
}
document.addEventListener('keypress', (e) => { if(e.key === 'Enter') send(); });
";
file_put_contents('basis.js', $js_content);
}
if (isset($_GET['logout'])) {
session_unset(); session_destroy();
header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); exit;
}
$db_file = 'omnichat_v35.db';
$db = new SQLite3($db_file);
$db->exec("CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, name TEXT, email TEXT, avatar TEXT, last_login DATETIME)");
$db->exec("CREATE TABLE IF NOT EXISTS messages (id INTEGER PRIMARY KEY, room TEXT, user TEXT, msg TEXT, color TEXT, type TEXT DEFAULT 'chat', created_at DATETIME)");
$db->exec("CREATE TABLE IF NOT EXISTS presence (user TEXT PRIMARY KEY, room TEXT, last_seen DATETIME, ip TEXT, is_banned INTEGER DEFAULT 0)");
$admin_config = ['name' => 'Admin', 'pass' => 'geheim123'];
$google_client_id = "DEINE_GOOGLE_CLIENT_ID.apps.googleusercontent.com";
if (isset($_GET['action'])) {
header('Content-Type: application/json');
if ($_GET['action'] == 'login' || $_GET['action'] == 'switch') {
$input = json_decode(file_get_contents('php://input'), true);
$user = htmlspecialchars($input['user'] ?? ($_SESSION['chat_user'] ?? ''));
$pass = $input['pass'] ?? '';
$room = htmlspecialchars($input['room'] ?? 'Lobby');
if (strtolower($user) === 'admin' && !isset($_SESSION['chat_user'])) {
if ($pass !== $admin_config['pass']) { echo json_encode(['success' => false, 'error' => 'Passwort falsch!']); exit; }
$_SESSION['is_admin'] = true;
}
if(!empty($user)) {
$_SESSION['chat_user'] = $user;
$_SESSION['chat_room'] = $room;
if(!isset($_SESSION['chat_color'])) $_SESSION['chat_color'] = 'hsl('.rand(0,360).', 70%, 60%)';
$db->exec("INSERT INTO presence (user, room, last_seen, ip) VALUES ('$user', '$room', DATETIME('now'), '".$_SERVER['REMOTE_ADDR']."') ON CONFLICT(user) DO UPDATE SET last_seen=DATETIME('now'), room='$room'");
echo json_encode(['success' => true]); exit;
}
}
if ($_GET['action'] == 'sync') {
$last_id = (int)$_GET['last_id'];
$u = $_SESSION['chat_user'] ?? '';
$room = $_SESSION['chat_room'] ?? 'Lobby';
if(!$u) { echo json_encode(['kicked' => true]); exit; }
$res_m = $db->query("SELECT *, strftime('%H:%M', created_at) as time FROM messages WHERE (room = '$room' OR room = 'GLOBAL') AND id > $last_id ORDER BY id ASC");
$msgs = []; while($r = $res_m->fetchArray(SQLITE3_ASSOC)) $msgs[] = $r;
$res_r = $db->query("SELECT DISTINCT room, COUNT(user) as cnt FROM presence WHERE last_seen > DATETIME('now', '-30 seconds') GROUP BY room");
$rooms = []; while($r = $res_r->fetchArray(SQLITE3_ASSOC)) $rooms[] = $r;
echo json_encode(['messages' => $msgs, 'rooms' => $rooms, 'curRoom' => $room, 'isAdmin' => ($_SESSION['is_admin'] ?? false)]); exit;
}
if ($_GET['action'] == 'send') {
$input = json_decode(file_get_contents('php://input'), true);
$stmt = $db->prepare("INSERT INTO messages (room, user, msg, color, created_at) VALUES (:r, :u, :m, :c, DATETIME('now', 'localtime'))");
$stmt->bindValue(':r', $_SESSION['chat_room']); $stmt->bindValue(':u', $_SESSION['chat_user']);
$stmt->bindValue(':m', htmlspecialchars($input['msg'])); $stmt->bindValue(':c', $_SESSION['chat_color']);
$stmt->execute(); exit;
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OmniChat OS v3.5 | Powered by Dreamcodes</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://accounts.google.com/gsi/client" async defer></script>
<link rel="stylesheet" href="style.css">
</head>
<body class="flex flex-col items-center justify-center">
<?php if(!isset($_SESSION['chat_user'])): ?>
<div class="bg-[#202c33] p-10 rounded-2xl w-full max-w-sm shadow-2xl border border-white/5 text-center">
<div class="w-20 h-20 bg-[#00a884] rounded-full flex items-center justify-center mx-auto mb-6 text-4xl shadow-lg font-bold text-white">O</div>
<h1 class="text-2xl font-bold mb-2">OmniChat OS</h1>
<p class="text-sm opacity-50 mb-8">Ein Projekt von <a href="https://www.dreamcodes.net" target="_blank" class="dc-link">Dreamcodes</a></p>
<input type="text" id="u" oninput="toggleAdmin(this.value)" placeholder="Benutzername" class="w-full p-4 rounded-lg bg-[#0b141a] mb-3 outline-none border border-transparent focus:border-[#00a884] text-white">
<div id="adm-p" class="hidden"><input type="password" id="p" placeholder="Admin Passwort" class="w-full p-4 rounded-lg bg-[#0b141a] mb-3 border border-red-500/30"></div>
<input type="text" id="r" placeholder="Raum Name (Lobby)" class="w-full p-4 rounded-lg bg-[#0b141a] mb-6 outline-none border border-transparent focus:border-[#00a884] text-[#00a884] font-bold">
<button onclick="login()" class="w-full bg-[#00a884] p-4 rounded-lg font-bold text-black uppercase mb-6 active:scale-95 transition-transform shadow-lg">Login</button>
<div id="g_id_onload" data-client_id="<?= $google_client_id ?>" data-callback="handleGoogleLogin"></div>
<div class="g_id_signin flex justify-center mb-6" data-type="standard" data-theme="filled_blue"></div>
<div class="mt-4 text-[10px] opacity-30 uppercase tracking-widest text-white">
© 2026 <a href="https://www.dreamcodes.net" target="_blank">Dreamcodes.net</a>
</div>
</div>
<?php else: ?>
<div class="app-wrap shadow-2xl">
<div class="sidebar">
<div class="p-3 bg-[#202c33] flex justify-between items-center text-white">
<div class="w-10 h-10 bg-emerald-600 rounded-full flex items-center justify-center font-bold"><?= $_SESSION['chat_user'][0] ?></div>
<div class="flex gap-5 text-xl opacity-60">
<button onclick="createRoom()" title="Neuer Raum">+</button>
<button onclick="location.href='?logout=1'" title="Abmelden">🚪</button>
</div>
</div>
<div class="flex-1 overflow-y-auto">
<div class="p-4 text-[11px] font-bold text-[#00a884] uppercase tracking-widest">Räume</div>
<div id="room-list"></div>
</div>
<div class="p-3 text-center border-t border-white/5">
<a href="https://www.dreamcodes.net" target="_blank" class="text-[10px] opacity-40 hover:opacity-100 transition-opacity dc-link">Powered by DREAMCODES.NET</a>
</div>
</div>
<div class="chat-view">
<div class="p-3 bg-[#202c33] flex items-center gap-4 z-10 shadow-md text-white">
<div class="w-10 h-10 bg-slate-700 rounded-full flex items-center justify-center text-xl">#</div>
<div class="font-bold text-[15px]" id="header-room-name">Lobby</div>
</div>
<div id="chat-box" class="flex-1 overflow-y-auto p-6 flex flex-col"></div>
<div id="emoji-picker" class="grid grid-cols-8 sm:grid-cols-10 gap-1"></div>
<div class="p-3 bg-[#202c33] flex items-center gap-3">
<button onclick="toggleEmoji()" class="text-2xl opacity-60 hover:opacity-100">😊</button>
<input type="text" id="msg" placeholder="Nachricht schreiben" class="flex-1 p-3 rounded-lg bg-[#2a3942] outline-none text-sm text-white">
<button onclick="send()" class="bg-[#00a884] w-12 h-12 rounded-full flex items-center justify-center text-black">➤</button>
</div>
</div>
</div>
<?php endif; ?>
<script src="basis.js"></script>
<script>
<?php if(isset($_SESSION['chat_user'])): ?>
const currentUserName = "<?= $_SESSION['chat_user'] ?>";
const picker = document.getElementById('emoji-picker');
if(picker) {
picker.innerHTML = emojis.map(e => `<span class="emoji-item" onclick="document.getElementById('msg').value += '${e}'">${e}</span>`).join('');
}
setInterval(() => sync(currentUserName), 1500);
sync(currentUserName);
<?php endif; ?>
</script>
</body>
</html>
