Browser selber machen

Warum?

Weil alle Browser entweder zu langsam, zu tracking-lastig oder zu vollgestopft sind. Und weil’s Spaß macht.

Was bauen wir?

Einen minimalistischen, extrem schnellen Desktop-Browser auf Chromium-Basis, der standardmäßig Werbung und Tracker blockiert. Mit Electron, TypeScript und dem @cliqz/adblocker-electron.


Schritt 1: Projekt aufsetzen

mkdir my-browser
cd my-browser
npm init -y
npm install electron typescript @cliqz/adblocker-electron @cliqz/adblocker-types cross-fetch

Schritt 2: TypeScript-Konfiguration

Erstelle tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "sourceMap": true
  },
  "include": ["src/**/*"]
}

Schritt 3: Main-Prozess

Erstelle src/main.ts:

import { app, BrowserWindow, session } from 'electron';
import { createElectronBlocker } from '@cliqz/adblocker-electron';
import fetch from 'cross-fetch';
import * as path from 'path';

let mainWindow: BrowserWindow | null = null;

async function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    frame: true,
    webPreferences: {
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
      preload: path.join(__dirname, 'preload.js'),
    },
  });

  mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'));
}

async function setupAdBlocker() {
  const blocker = await createElectronBlocker({
    loadLists: true,
    fetchLists: true,
    lists: [
      'https://easylist.to/easylist/easylist.txt',
      'https://easylist.to/easylist/easyprivacy.txt',
    ],
  });

  blocker.enableBlockingInSession(session.defaultSession);
}

function setupPrivacy() {
  const ses = session.defaultSession;
  
  // Drittanbieter-Cookies blockieren
  ses.webRequest.onHeadersReceived((details, callback) => {
    callback({
      responseHeaders: {
        ...details.responseHeaders,
        'Set-Cookie': undefined,
      },
    });
  });

  // Tracker blockieren
  ses.webRequest.onBeforeRequest((details, callback) => {
    const blockPatterns = [
      'google-analytics.com',
      'doubleclick.net',
      'facebook.com/tr',
      'adsystem.com',
      'adservice.google.com',
    ];
    
    const shouldBlock = blockPatterns.some(pattern => 
      details.url.includes(pattern)
    );

    callback(shouldBlock ? { cancel: true } : {});
  });
}

app.whenReady().then(async () => {
  await setupAdBlocker();
  setupPrivacy();
  await createWindow();
});

app.on('window-all-closed', () => {
  app.quit();
});

Schritt 4: UI

Erstelle renderer/index.html:

<!DOCTYPE html>
<html>
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #1a1a2e; color: #e0e0e0; }
    
    #toolbar {
      display: flex; align-items: center; gap: 8px;
      padding: 8px 12px; background: #16213e; border-bottom: 1px solid #0f3460;
    }
    
    .nav-btn {
      background: none; border: none; color: #e0e0e0; cursor: pointer;
      padding: 6px 10px; border-radius: 4px; font-size: 16px;
    }
    .nav-btn:hover { background: #0f3460; }
    .nav-btn:disabled { opacity: 0.3; cursor: default; }
    
    #url-bar {
      flex: 1; padding: 8px 12px; border: 1px solid #0f3460; border-radius: 6px;
      background: #1a1a2e; color: #e0e0e0; font-size: 14px; outline: none;
    }
    #url-bar:focus { border-color: #e94560; }
    
    #content {
      width: 100%; height: calc(100vh - 50px); border: none;
    }
  </style>
</head>
<body>
  <div id="toolbar">
    <button id="back" class="nav-btn">←</button>
    <button id="forward" class="nav-btn">→</button>
    <button id="reload" class="nav-btn">↻</button>
    <input type="text" id="url-bar" placeholder="URL eingeben..." value="https://duckduckgo.com" />
  </div>
  <webview id="content" src="https://duckduckgo.com"></webview>
  
  <script>
    const webview = document.getElementById('content');
    const urlBar = document.getElementById('url-bar');
    const back = document.getElementById('back');
    const forward = document.getElementById('forward');
    const reload = document.getElementById('reload');
    
    webview.addEventListener('did-navigate', (e) => { urlBar.value = e.url; });
    webview.addEventListener('did-navigate-in-page', (e) => { urlBar.value = e.url; });
    webview.addEventListener('page-title-updated', (e) => { document.title = e.title + ' — MyBrowser'; });
    
    urlBar.addEventListener('keydown', (e) => {
      if (e.key === 'Enter') {
        let url = urlBar.value.trim();
        if (!url.startsWith('http://') && !url.startsWith('https://')) {
          url = 'https://' + url;
        }
        webview.loadURL(url);
      }
    });
    
    back.addEventListener('click', () => webview.canGoBack() && webview.goBack());
    forward.addEventListener('click', () => webview.canGoForward() && webview.goForward());
    reload.addEventListener('click', () => webview.reload());
    
    webview.addEventListener('did-start-loading', () => { reload.textContent = '✕'; });
    webview.addEventListener('did-stop-loading', () => { reload.textContent = '↻'; });
  </script>
</body>
</html>

Schritt 5: Build & Start

In package.json die Scripts anpassen:

{
  "scripts": {
    "build": "tsc",
    "start": "npm run build && electron dist/main.js",
    "dev": "tsc && electron dist/main.js"
  }
}

Dann:

npm run build
npm start

Ergebnis

Du hast jetzt einen eigenen Browser der:

  • ✅ Werbung blockiert (EasyList + EasyPrivacy)
  • ✅ Tracker blockiert (Google Analytics, Facebook, Doubleclick)
  • ✅ Drittanbieter-Cookies blockiert
  • ✅ Sandbox + Context Isolation aktiviert
  • ✅ Minimalistisches UI
  • ✅ Superschnell

Morvel-Status

Gebaut in: ~30 Minuten Komplexität: Mittel Lernfaktor: Hoch — du verstehst danach wie Browser wirklich funktionieren Nützlichkeit: Sehr hoch — dein eigener Privacy-Browser, komplett unter deiner Kontrolle