diff --git a/public/js/windowManager.js b/public/js/windowManager.js
new file mode 100644
index 0000000..face46b
--- /dev/null
+++ b/public/js/windowManager.js
@@ -0,0 +1,322 @@
+/* ============================================================
+ AURA OS — Pencere Yöneticisi (Window Manager)
+ createWindow / focus / minimize / restore / close / drag / z-sırası
+ ============================================================ */
+
+// Global uygulama kayıt defteri
+const AuraApps = {};
+
+// Pencere yöneticisi durumu
+const Wm = {
+ windows: [], // tüm pencere kayıtları
+ zCounter: 10, // z-index sayaç (her focus artar)
+ activeWin: null, // şu an üstte olan pencere
+ nextId: 1,
+};
+
+function registerApp(appId, config) {
+ AuraApps[appId] = config;
+ // console.log('[AuraApps] kayıtlı:', appId);
+}
+
+/**
+ * Yeni bir pencere oluşturup ekran katmanına ekler.
+ * @param {object} opts
+ * appId: string — uygulama kimliği (AuraApps kaydı)
+ * title: string — başlık
+ * icon: string — emoji ikon
+ * width,height: pencere boyut
+ * x, y: başlangıç konumu (opsiyonel)
+ * content: html string (body içeriği)
+ * onReady: function(winBody) — içeriğin DOM'a bağlanmasından sonra çağrılır
+ */
+function createWindow(opts) {
+ const app = AuraApps[opts.appId];
+ if (!app) {
+ console.error('[WM] Bilinmeyen uygulama:', opts.appId);
+ return null;
+ }
+
+ // Varsayılanlar
+ const width = opts.width || app.defaultWidth || 560;
+ const height = opts.height || app.defaultHeight || 400;
+
+ // Konum: verilmediyse kademeli merkez açılım
+ const vw = window.innerWidth;
+ const vh = window.innerHeight - 50; // taskbar payı
+ const baseX = typeof opts.x === 'number' ? opts.x : Math.max(30, Math.round((vw - width) / 2));
+ const baseY = typeof opts.y === 'number' ? opts.y : Math.max(20, Math.round((vh - height) / 3));
+ const offset = (Wm.windows.length % 8) * 22;
+ const x = Math.min(baseX + offset, vw - width - 20);
+ const y = Math.min(baseY + offset, vh - height - 20);
+
+ const id = 'win-' + (Wm.nextId++);
+ const zIndex = ++Wm.zCounter;
+
+ // Pencere kök elemanı
+ const win = document.createElement('div');
+ win.className = 'aura-window active';
+ win.id = id;
+ win.dataset.appId = opts.appId;
+ win.style.left = Math.max(6, x) + 'px';
+ win.style.top = Math.max(6, y) + 'px';
+ win.style.width = width + 'px';
+ win.style.height = height + 'px';
+ win.style.zIndex = zIndex;
+
+ // Baslık çubuğu
+ const titlebar = document.createElement('div');
+ titlebar.className = 'window-titlebar';
+ titlebar.innerHTML =
+ '' + (opts.icon || app.icon || '🪟') + '' +
+ '' + escapeHtml(opts.title || app.name || opts.appId) + '' +
+ '
' +
+ '' +
+ '' +
+ '
';
+
+ // Gövde
+ const body = document.createElement('div');
+ body.className = 'window-body';
+
+ win.appendChild(titlebar);
+ win.appendChild(body);
+
+ // Kayıt nesnesi
+ const record = {
+ id,
+ appId: opts.appId,
+ title: opts.title || app.name,
+ icon: opts.icon || app.icon,
+ el: win,
+ titlebar,
+ body,
+ minimized: false,
+ metadata: opts.metadata || null,
+ };
+
+ Wm.windows.push(record);
+
+ // Pencereyi katmana ekle
+ const layer = document.getElementById('window-layer');
+ layer.appendChild(win);
+ record.launchTime = Date.now();
+
+ // ---- Başlık çubuğundan sürükleme ----
+ setupDrag(record);
+
+ // ---- Odaklama olayı: pencereye tıklandığında en öne ----
+ win.addEventListener('mousedown', (e) => {
+ if (record.minimized) return;
+ focusWindow(record.id);
+ });
+ // Başlık çubuğu drag başlarken de öne alınmalı
+ titlebar.addEventListener('mousedown', (e) => {
+ if (record.minimized) return;
+ focusWindow(record.id);
+ });
+
+ // ---- Buton davranışları ----
+ const minBtn = titlebar.querySelector('.btn-min');
+ const closeBtn = titlebar.querySelector('.btn-close');
+ minBtn.addEventListener('click', (e) => {
+ e.stopPropagation();
+ minimizeWindow(record.id);
+ });
+ closeBtn.addEventListener('click', (e) => {
+ e.stopPropagation();
+ closeWindow(record.id);
+ });
+
+ // ---- İçeriği doldur ----
+ if (typeof opts.content === 'string') {
+ body.innerHTML = opts.content;
+ }
+
+ // ---- Görev çubuğu butonunu oluştur ----
+ window.Taskbar && window.Taskbar.addTaskButton(record);
+ record.taskBtn = window.Taskbar && window.Taskbar.getTaskBtn(record.id);
+
+ // ---- Uygulamanın kurulum çağrısı ----
+ if (app.onLaunch) {
+ try {
+ app.onLaunch(record, body);
+ } catch (err) {
+ console.error('[WM] onLaunch hatası:', err);
+ body.innerHTML = 'Hata: ' + escapeHtml(err.message) + '
';
+ }
+ }
+
+ // ---- onReady çağrısı ----
+ if (typeof opts.onReady === 'function') {
+ opts.onReady(record, body);
+ }
+
+ window.Taskbar && window.Taskbar.render();
+ focusWindow(record.id);
+
+ return { record, bodyEl: body, win };
+}
+
+/* ------------ Saydam yardımcı: DOM'a sağlam pencere dış IP arayüzü ------------
+ createWindow genel (global) fonksiyon olarak dönecek, alt-scriptler kullanır.
+ Diğer modüller window.createWindow ≠ çalışmasın diye: */
+window.createWindow = createWindow;
+
+/* ---- Odak (z-sırası) Yönetimi ---- */
+function focusWindow(id) {
+ const rec = getWindow(id);
+ if (!rec) return;
+
+ // Zaten aktifse ama minimize ise restore olur
+ if (rec.minimized) return; // taskbar üzerinden restore edilir
+
+ // Aktif pencere sınıfını temizle
+ Wm.windows.forEach(w => {
+ w.el.classList.remove('active');
+ w.taskBtn && w.taskBtn.classList.remove('active');
+ });
+
+ rec.el.classList.add('active');
+ rec.el.style.zIndex = ++Wm.zCounter;
+ Wm.activeWin = rec;
+
+ if (recordBtnById(id)) recordBtnById(id).classList.add('active');
+ rec.taskBtn && rec.taskBtn.classList.add('active');
+
+ window.Taskbar && window.Taskbar.render();
+ // Pencereyi minimum boyutun üzerinde tutmaz, minimize restore
+ if (rec.minimized && rec.__doRestore) topLevelRestore(rec);
+}
+
+function topLevelRestore(rec) {
+ rec.el.classList.remove('minimized');
+ rec.minimized = false;
+ rec.el.style.display = 'flex';
+}
+
+/* ------------ Küçült ------------ */
+function minimizeWindow(id) {
+ const rec = getWindow(id);
+ if (!rec) return;
+ rec.el.classList.add('minimized');
+ rec.minimized = true;
+ rec.el.classList.remove('active');
+ rec.taskBtn && rec.taskBtn.classList.remove('active');
+
+ // Aktifliği bırak
+ if (Wm.activeWin && Wm.activeWin.id === id) {
+ Wm.activeWin = null;
+ // Aktifliği diğer pencereye aktar
+ const others = Wm.windows.filter(w => !w.minimized);
+ if (others.length) focusWindow(others[others.length - 1].id);
+ }
+ window.Taskbar && window.Taskbar.render();
+}
+
+/* ------------ Geri getir (restore) ------------ */
+function restoreWindow(id) {
+ const rec = getWindow(id);
+ if (!rec) return;
+ rec.el.classList.remove('minimized');
+ rec.minimized = false;
+ rec.el.classList.add('active');
+ rec.el.style.zIndex = ++Wm.zCounter;
+ Wm.activeWin = rec;
+ focusWindow(id);
+ window.Taskbar && window.Taskbar.render();
+}
+
+/* ------------ Kapat ------------ */
+function closeWindow(id) {
+ const rec = getWindow(id);
+ if (!rec) return;
+
+ const idx = Wm.windows.indexOf(rec);
+ if (idx >= 0) Wm.windows.splice(idx, 1);
+
+ // Görev çubuğu butonunu kaldır
+ if (window.Taskbar) {
+ window.Taskbar.removeTaskButton(id);
+ }
+
+ if (rec.el.parentNode) rec.el.parentNode.removeChild(rec.el);
+
+ if (Wm.activeWin && Wm.activeWin.id === id) {
+ Wm.activeWin = null;
+ const others = Wm.windows.filter(w => !w.minimized);
+ if (others.length) focusWindow(others[others.length - 1].id);
+ }
+ window.Taskbar && window.Taskbar.render();
+}
+
+/* ------------ Yardımcı fonksiyonlar ------------ */
+function getWindow(id) {
+ return Wm.windows.find(w => w.id === id) || null;
+}
+
+function recordBtnById(id) {
+ const rec = getWindow(id);
+ return rec && rec.taskBtn;
+}
+
+function escapeHtml(str) {
+ if (!str) return '';
+ return String(str)
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"');
+}
+
+/* ------------ Fareyle sürükleme (drag) ------------ */
+function setupDrag(rec) {
+ const titlebar = rec.titlebar;
+ let isDragging = false;
+ let startX, startY, origX, origY, origPointerX, origPointerY;
+
+ titlebar.addEventListener('mousedown', (e) => {
+ // Sol tuş; başlık butonlarına tıklanmışsa sürükleme başlatma
+ if (e.button !== 0) return;
+ if (e.target.closest('.win-btns')) return;
+
+ isDragging = true;
+ const rect = rec.el.getBoundingClientRect();
+ startX = rect.left;
+ startY = rect.top;
+ origPointerX = e.clientX;
+ origPointerY = e.clientY;
+
+ rec.el.style.transition = 'none';
+ e.preventDefault();
+ });
+
+ document.addEventListener('mousemove', (e) => {
+ if (!isDragging) return;
+ const dx = e.clientX - origPointerX;
+ const dy = e.clientY - origPointerY;
+ let nx = startX + dx;
+ let ny = startY + dy;
+
+ // Ekran sınırları içinde tut (kısmen taşmasın)
+ const vw = window.innerWidth;
+ const vh = window.innerHeight - 50;
+ nx = Math.min(nx, vw - 60);
+ ny = Math.min(ny, vh - 30);
+ nx = Math.max(nx, -rec.el.offsetWidth + 80);
+ ny = Math.max(ny, 0);
+
+ rec.el.style.left = nx + 'px';
+ rec.el.style.top = ny + 'px';
+ });
+
+ document.addEventListener('mouseup', () => {
+ if (isDragging) {
+ isDragging = false;
+ rec.el.style.transition = '';
+ }
+ });
+}
+
+/* ----- Pencere sırasını gösteren API (debug/taskbar) ----- */
+window.Wm = Wm;