1
0

Add logos and README

This commit is contained in:
2025-07-18 11:15:19 +02:00
parent 9fc5e7c078
commit 88d47dc4e0
4 changed files with 608 additions and 2 deletions

293
README.md
View File

@@ -1,3 +1,292 @@
# OpenWall # 🏠 OpenWall
Smart home dashboard for calendar syncing, notes, and shopping lists with seamless mobile and tablet integration. <div align="center">
![OpenWall Logo](assets/logo.svg)
**Ein Smart Home Dashboard für modernes Wohnen**
*Kalender-Synchronisation, Notizen und Einkaufslisten mit nahtloser Handy- und Tablet-Integration*
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Node.js](https://img.shields.io/badge/Node.js-18%2B-green.svg)](https://nodejs.org/)
[![React](https://img.shields.io/badge/React-19.1.0-blue.svg)](https://reactjs.org/)
[![Electron](https://img.shields.io/badge/Electron-35.1.5-purple.svg)](https://electronjs.org/)
[Funktionen](#-funktionen) • [Architektur](#-architektur) • [Schnellstart](#-schnellstart) • [Installation](#-installation) • [Entwicklung](#-entwicklung)
</div>
---
## 🌟 Funktionen
### 📅 **Kalender-Integration**
- Synchronisation mit Ihren bevorzugten Kalender-Diensten
- Saubere, intuitive Benutzeroberfläche optimiert für Touch-Displays
- Perfekt für wandmontierte Tablets und Smart Displays
### 📝 **Notizen-Verwaltung**
- Schnelle Notizerstellung und -organisation
- Nahtlose Synchronisation zwischen Geräten
- Touch-freundliche Benutzeroberfläche für einfache Bedienung
### 🛒 **Intelligente Einkaufslisten**
- Gemeinsame Einkaufslisten für Familien
- Echtzeit-Synchronisation zwischen Geräten
- Mobile-optimierte Begleit-App
- Automatische Bereinigung erledigter Einträge
### 🎨 **Schönes Design**
- Moderne, responsive Benutzeroberfläche
- Optimiert für Hochformat-Displays (9:16 Verhältnis)
- Atemberaubende Hintergrundbilder
- Touch-First Interaktionsdesign
### 📱 **Multi-Platform Unterstützung**
- **Desktop**: Vollständiges Electron Dashboard
- **Mobile**: Progressive Web App für Einkaufslisten
- **Embedded**: Benutzerdefinierte Linux OS Installation für dedizierte Displays
## 🏗️ Architektur
OpenWall ist als modernes, skalierbares System mit mehreren Komponenten aufgebaut:
```
📦 OpenWall
├── 🖥️ dashboard/ # Electron Desktop-Anwendung
├── 📱 mobile-shopping/ # Mobile PWA für Einkaufslisten
├── 🔧 server/ # Express.js Backend API
└── 🐧 os/ # Linux OS Installer & Konfiguration
```
### Technologie-Stack
| Komponente | Technologie | Zweck |
|------------|-------------|-------|
| **Frontend** | React 19 + Vite | Moderne, schnelle UI-Entwicklung |
| **Desktop** | Electron 35 | Plattformübergreifende Desktop-App |
| **Mobile** | PWA + React | Native-ähnliche mobile Erfahrung |
| **Backend** | Express.js + SQLite | RESTful API & Datenpersistierung |
| **Styling** | Sass | Schöne, wartbare Stylesheets |
| **Package Manager** | pnpm | Schnelles, effizientes Dependency Management |
## 🚀 Schnellstart
### Voraussetzungen
- **Node.js** 18 oder höher
- **pnpm** (empfohlen) oder npm
- **Git**
### 1. Repository klonen
```bash
git clone https://github.com/yourusername/OpenWall.git
cd OpenWall
```
### 2. Backend-Server starten
```bash
cd server
pnpm install
pnpm start
```
Der Server startet auf `http://localhost:3001`
### 3. Dashboard starten
```bash
cd ../dashboard
pnpm install
pnpm dev
```
Das Dashboard öffnet sich automatisch im Entwicklungsmodus.
### 4. Mobile App ausprobieren (Optional)
```bash
cd ../mobile-shopping
pnpm install
pnpm dev
```
Zugriff auf die mobile App unter `http://localhost:5173`
## 🔧 Installation
### Option 1: Entwicklungsumgebung
Perfekt für Entwicklung und Tests:
```bash
# Alle Abhängigkeiten installieren
pnpm install
# Alle Services im Entwicklungsmodus starten
pnpm dev
```
### Option 2: Produktions-Deployment
Für dedizierte Wanddisplays und Smart Home Setups:
#### Manuelle Installation
```bash
# Dashboard bauen
cd dashboard
pnpm install
pnpm build
# Mobile App bauen
cd ../mobile-shopping
pnpm install
pnpm build
# Produktionsserver starten
cd ../server
pnpm install
NODE_ENV=production pnpm start
```
#### Automatisierte Linux Installation
Für Debian-basierte Systeme mit automatischem Kiosk-Modus Setup:
```bash
# Als root ausführen
sudo ./os/install.sh
```
Dieser Installer wird:
- ✅ Einen dedizierten Benutzeraccount erstellen
- ✅ Alle Abhängigkeiten installieren
- ✅ Wayland/Sway für Touch-Displays konfigurieren
- ✅ Auto-Start beim Booten einrichten
- ✅ Für 9:16 Hochformat-Displays optimieren
- ✅ Touch-Input-Kalibrierung aktivieren
## 💻 Entwicklung
### Projektstruktur
```
dashboard/ # Haupt-Electron-Anwendung
├── src/
│ ├── main/ # Electron Hauptprozess
│ ├── preload/ # Preload-Skripte
│ └── renderer/ # React Frontend
│ ├── src/
│ │ ├── pages/ # Anwendungsseiten
│ │ ├── common/ # Geteilte Komponenten
│ │ ├── services/ # API Services
│ │ └── utils/ # Hilfsfunktionen
│ └── index.html
├── build/ # Build-Assets (Icons, etc.)
└── package.json
mobile-shopping/ # Mobile PWA
├── src/
│ ├── services/ # API Integration
│ └── utils/ # Geteilte Hilfsmittel
└── public/ # PWA Assets
server/ # Backend API
├── models/ # Datenbank-Modelle
├── routes/ # API Routen
├── database.sqlite # SQLite Datenbank
└── index.js # Haupt-Server-Datei
os/ # System-Installation
├── install.sh # Automatisierter Installer
└── build-iso.sh # Custom ISO Builder
```
### Verfügbare Skripte
#### Dashboard (Electron)
```bash
pnpm dev # Entwicklungsmodus mit Hot Reload
pnpm build # Für Produktion bauen
pnpm start # Gebaute Anwendung starten
pnpm build:mac # macOS App bauen
pnpm build:win # Windows App bauen
pnpm build:linux # Linux App bauen
```
#### Mobile Shopping (PWA)
```bash
pnpm dev # Entwicklungsserver
pnpm build # Für Produktion bauen
pnpm preview # Gebaute App anzeigen
```
#### Server (Express.js)
```bash
pnpm start # Produktionsserver starten
pnpm dev # Entwicklung mit nodemon
```
### API Endpunkte
| Methode | Endpunkt | Beschreibung |
|---------|----------|--------------|
| `GET` | `/api/health` | Server-Gesundheitscheck |
| `GET` | `/api/shopping` | Alle Einkaufsartikel abrufen |
| `POST` | `/api/shopping` | Neuen Einkaufsartikel erstellen |
| `PUT` | `/api/shopping/:id` | Einkaufsartikel aktualisieren |
| `DELETE` | `/api/shopping/:id` | Einkaufsartikel löschen |
### Umgebungsvariablen
Erstellen Sie `.env` Dateien im Server-Verzeichnis:
```env
PORT=3001
NODE_ENV=development
DATABASE_URL=sqlite:./database.sqlite
```
## 🎯 Anwendungsfälle
### 🏠 **Smart Home Display**
Perfekt für wandmontierte Tablets in Küchen, Fluren oder Familienzimmern. Die Hochformat-Ausrichtung und touch-optimierte Benutzeroberfläche machen es ideal für schnelle Interaktionen.
### 👨‍👩‍👧‍👦 **Familienorganisation**
Halten Sie alle mit geteilten Kalendern, Familiennotizen und gemeinsamen Einkaufslisten synchron, die nahtlos auf allen Geräten funktionieren.
### 🏢 **Büro & Co-Working**
Verwenden Sie es in Büroumgebungen für Teamkalender, geteilte Notizen und Büromaterial-Verwaltung.
### 🎛️ **Digitaler Kiosk**
Einsatz als eigenständiges Kiosk-System mit der enthaltenen Linux-Installation für dedizierte Displays.
## 📄 Lizenz
Dieses Projekt ist unter der MIT-Lizenz lizenziert - siehe die [LICENSE](LICENSE) Datei für Details.
## 🙏 Danksagungen
- **Electron** Team für das exzellente Desktop-Framework
- **React** Community für das großartige Ökosystem
- **Pixabay** für die schönen Hintergrundbilder
## 📞 Support
- 🐛 **Issues**: [GitHub Issues](https://github.com/yourusername/OpenWall/issues)
- 💬 **Diskussionen**: [GitHub Discussions](https://github.com/yourusername/OpenWall/discussions)
- 📧 **E-Mail**: [your-email@example.com](mailto:your-email@example.com)
---
<div align="center">
**Erstellt mit ❤️ von [Mathias Wagner](https://git.gnm.dev/Mathias/OpenWall)**
*Verwandeln Sie Ihren Raum mit OpenWall in eine intelligente, vernetzte Umgebung*
</div>

31
assets/logo-small.svg Normal file
View File

@@ -0,0 +1,31 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#2563eb"/>
<stop offset="100%" style="stop-color:#1d4ed8"/>
</linearGradient>
<linearGradient id="screenGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#f8fafc"/>
<stop offset="100%" style="stop-color:#e2e8f0"/>
</linearGradient>
</defs>
<!-- Background -->
<circle cx="32" cy="32" r="30" fill="url(#bgGradient)"/>
<!-- Screen -->
<rect x="18" y="12" width="28" height="40" rx="3" fill="url(#screenGrad)" stroke="#cbd5e1"/>
<rect x="20" y="14" width="24" height="36" rx="2" fill="#1e293b"/>
<rect x="22" y="16" width="20" height="32" rx="1" fill="#f1f5f9"/>
<!-- UI Elements -->
<rect x="24" y="18" width="6" height="4" rx="0.5" fill="#3b82f6"/>
<rect x="32" y="18" width="6" height="4" fill="#10b981"/>
<rect x="24" y="24" width="8" height="6" fill="#e5e7eb" stroke="#cbd5e1" stroke-width="0.5"/>
<rect x="34" y="24" width="6" height="6" fill="#e5e7eb" stroke="#cbd5e1" stroke-width="0.5"/>
<!-- Status indicator -->
<circle cx="32" cy="54" r="2" fill="#10b981">
<animate attributeName="opacity" values="0.5;1;0.5" dur="2s" repeatCount="indefinite"/>
</circle>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

143
assets/logo.svg Normal file
View File

@@ -0,0 +1,143 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
<defs>
<!-- Gradient for the wall background -->
<linearGradient id="wallGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#2563eb;stop-opacity:1" />
<stop offset="50%" style="stop-color:#3b82f6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1d4ed8;stop-opacity:1" />
</linearGradient>
<!-- Gradient for the screen glow -->
<radialGradient id="screenGlow" cx="50%" cy="50%" r="60%">
<stop offset="0%" style="stop-color:#60a5fa;stop-opacity:0.8" />
<stop offset="70%" style="stop-color:#3b82f6;stop-opacity:0.4" />
<stop offset="100%" style="stop-color:#1e40af;stop-opacity:0" />
</radialGradient>
<!-- Gradient for the screen -->
<linearGradient id="screenGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#f8fafc;stop-opacity:1" />
<stop offset="100%" style="stop-color:#e2e8f0;stop-opacity:1" />
</linearGradient>
<!-- Drop shadow filter -->
<filter id="dropShadow" x="-50%" y="-50%" width="200%" height="200%">
<feDropShadow dx="2" dy="4" stdDeviation="3" flood-color="#1e293b" flood-opacity="0.3"/>
</filter>
<!-- Inner shadow for depth -->
<filter id="innerShadow" x="-50%" y="-50%" width="200%" height="200%">
<feOffset dx="0" dy="2"/>
<feGaussianBlur stdDeviation="2" result="offset-blur"/>
<feFlood flood-color="#334155" flood-opacity="0.2"/>
<feComposite in2="offset-blur" operator="in"/>
<feMerge>
<feMergeNode in="SourceGraphic"/>
<feMergeNode/>
</feMerge>
</filter>
</defs>
<!-- Background circle -->
<circle cx="100" cy="100" r="95" fill="url(#wallGradient)" filter="url(#dropShadow)"/>
<!-- Wall texture lines -->
<g opacity="0.1">
<line x1="20" y1="40" x2="180" y2="40" stroke="#fff" stroke-width="1"/>
<line x1="20" y1="80" x2="180" y2="80" stroke="#fff" stroke-width="1"/>
<line x1="20" y1="120" x2="180" y2="120" stroke="#fff" stroke-width="1"/>
<line x1="20" y1="160" x2="180" y2="160" stroke="#fff" stroke-width="1"/>
<line x1="40" y1="20" x2="40" y2="180" stroke="#fff" stroke-width="1"/>
<line x1="80" y1="20" x2="80" y2="180" stroke="#fff" stroke-width="1"/>
<line x1="120" y1="20" x2="120" y2="180" stroke="#fff" stroke-width="1"/>
<line x1="160" y1="20" x2="160" y2="180" stroke="#fff" stroke-width="1"/>
</g>
<!-- Screen glow effect -->
<ellipse cx="100" cy="85" rx="45" ry="55" fill="url(#screenGlow)" opacity="0.6"/>
<!-- Main screen/tablet -->
<rect x="65" y="35" width="70" height="100" rx="8" ry="8"
fill="url(#screenGradient)"
stroke="#cbd5e1"
stroke-width="2"
filter="url(#innerShadow)"/>
<!-- Screen bezel -->
<rect x="68" y="38" width="64" height="94" rx="4" ry="4"
fill="#1e293b"
opacity="0.9"/>
<!-- Active screen content area -->
<rect x="72" y="45" width="56" height="80" rx="2" ry="2"
fill="#f1f5f9"/>
<!-- Calendar icon representation -->
<g transform="translate(75, 48)">
<!-- Calendar header -->
<rect x="0" y="0" width="20" height="4" rx="1" fill="#3b82f6"/>
<!-- Calendar body -->
<rect x="0" y="4" width="20" height="16" fill="#e2e8f0" stroke="#cbd5e1" stroke-width="0.5"/>
<!-- Calendar grid lines -->
<line x1="5" y1="4" x2="5" y2="20" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="10" y1="4" x2="10" y2="20" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="15" y1="4" x2="15" y2="20" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="0" y1="8" x2="20" y2="8" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="0" y1="12" x2="20" y2="12" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="0" y1="16" x2="20" y2="16" stroke="#94a3b8" stroke-width="0.3"/>
<!-- Today highlight -->
<rect x="5" y="8" width="5" height="4" fill="#3b82f6" opacity="0.7"/>
</g>
<!-- Notes icon -->
<g transform="translate(100, 48)">
<rect x="0" y="0" width="16" height="20" rx="1" fill="#f8fafc" stroke="#cbd5e1" stroke-width="0.5"/>
<!-- Note lines -->
<line x1="2" y1="4" x2="14" y2="4" stroke="#94a3b8" stroke-width="0.4"/>
<line x1="2" y1="7" x2="12" y2="7" stroke="#94a3b8" stroke-width="0.4"/>
<line x1="2" y1="10" x2="14" y2="10" stroke="#94a3b8" stroke-width="0.4"/>
<line x1="2" y1="13" x2="10" y2="13" stroke="#94a3b8" stroke-width="0.4"/>
</g>
<!-- Shopping list icon -->
<g transform="translate(75, 75)">
<rect x="0" y="0" width="20" height="24" rx="1" fill="#f8fafc" stroke="#cbd5e1" stroke-width="0.5"/>
<!-- Shopping list items -->
<circle cx="3" cy="4" r="1" fill="#10b981"/>
<line x1="6" y1="4" x2="16" y2="4" stroke="#64748b" stroke-width="0.4"/>
<circle cx="3" cy="8" r="1" fill="#10b981"/>
<line x1="6" y1="8" x2="14" y2="8" stroke="#64748b" stroke-width="0.4"/>
<circle cx="3" cy="12" r="1" fill="#e5e7eb" stroke="#9ca3af" stroke-width="0.4"/>
<line x1="6" y1="12" x2="15" y2="12" stroke="#9ca3af" stroke-width="0.4"/>
<circle cx="3" cy="16" r="1" fill="#e5e7eb" stroke="#9ca3af" stroke-width="0.4"/>
<line x1="6" y1="16" x2="12" y2="16" stroke="#9ca3af" stroke-width="0.4"/>
</g>
<!-- Smart home connectivity dots -->
<g transform="translate(100, 75)">
<!-- WiFi/connectivity symbol -->
<circle cx="8" cy="12" r="1.5" fill="#10b981" opacity="0.8"/>
<circle cx="14" cy="8" r="1" fill="#3b82f6" opacity="0.6"/>
<circle cx="12" cy="16" r="0.8" fill="#8b5cf6" opacity="0.7"/>
<circle cx="18" cy="12" r="1.2" fill="#f59e0b" opacity="0.6"/>
<!-- Connection lines -->
<line x1="8" y1="12" x2="14" y2="8" stroke="#10b981" stroke-width="0.5" opacity="0.4"/>
<line x1="8" y1="12" x2="12" y2="16" stroke="#10b981" stroke-width="0.5" opacity="0.4"/>
<line x1="14" y1="8" x2="18" y2="12" stroke="#3b82f6" stroke-width="0.5" opacity="0.4"/>
</g>
<!-- Home base indicator -->
<g transform="translate(100, 145)">
<!-- Simple house shape -->
<polygon points="0,8 8,0 16,8 16,16 0,16" fill="#64748b" opacity="0.7"/>
<rect x="6" y="10" width="4" height="6" fill="#475569"/>
<rect x="2" y="8" width="3" height="3" fill="#1e293b" opacity="0.6"/>
<rect x="11" y="8" width="3" height="3" fill="#1e293b" opacity="0.6"/>
</g>
<!-- Power/status indicator -->
<circle cx="100" cy="170" r="3" fill="#10b981" opacity="0.8">
<animate attributeName="opacity" values="0.4;0.8;0.4" dur="2s" repeatCount="indefinite"/>
</circle>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -0,0 +1,143 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
<defs>
<!-- Gradient for the wall background -->
<linearGradient id="wallGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#2563eb;stop-opacity:1" />
<stop offset="50%" style="stop-color:#3b82f6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1d4ed8;stop-opacity:1" />
</linearGradient>
<!-- Gradient for the screen glow -->
<radialGradient id="screenGlow" cx="50%" cy="50%" r="60%">
<stop offset="0%" style="stop-color:#60a5fa;stop-opacity:0.8" />
<stop offset="70%" style="stop-color:#3b82f6;stop-opacity:0.4" />
<stop offset="100%" style="stop-color:#1e40af;stop-opacity:0" />
</radialGradient>
<!-- Gradient for the screen -->
<linearGradient id="screenGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#f8fafc;stop-opacity:1" />
<stop offset="100%" style="stop-color:#e2e8f0;stop-opacity:1" />
</linearGradient>
<!-- Drop shadow filter -->
<filter id="dropShadow" x="-50%" y="-50%" width="200%" height="200%">
<feDropShadow dx="2" dy="4" stdDeviation="3" flood-color="#1e293b" flood-opacity="0.3"/>
</filter>
<!-- Inner shadow for depth -->
<filter id="innerShadow" x="-50%" y="-50%" width="200%" height="200%">
<feOffset dx="0" dy="2"/>
<feGaussianBlur stdDeviation="2" result="offset-blur"/>
<feFlood flood-color="#334155" flood-opacity="0.2"/>
<feComposite in2="offset-blur" operator="in"/>
<feMerge>
<feMergeNode in="SourceGraphic"/>
<feMergeNode/>
</feMerge>
</filter>
</defs>
<!-- Background circle -->
<circle cx="100" cy="100" r="95" fill="url(#wallGradient)" filter="url(#dropShadow)"/>
<!-- Wall texture lines -->
<g opacity="0.1">
<line x1="20" y1="40" x2="180" y2="40" stroke="#fff" stroke-width="1"/>
<line x1="20" y1="80" x2="180" y2="80" stroke="#fff" stroke-width="1"/>
<line x1="20" y1="120" x2="180" y2="120" stroke="#fff" stroke-width="1"/>
<line x1="20" y1="160" x2="180" y2="160" stroke="#fff" stroke-width="1"/>
<line x1="40" y1="20" x2="40" y2="180" stroke="#fff" stroke-width="1"/>
<line x1="80" y1="20" x2="80" y2="180" stroke="#fff" stroke-width="1"/>
<line x1="120" y1="20" x2="120" y2="180" stroke="#fff" stroke-width="1"/>
<line x1="160" y1="20" x2="160" y2="180" stroke="#fff" stroke-width="1"/>
</g>
<!-- Screen glow effect -->
<ellipse cx="100" cy="85" rx="45" ry="55" fill="url(#screenGlow)" opacity="0.6"/>
<!-- Main screen/tablet -->
<rect x="65" y="35" width="70" height="100" rx="8" ry="8"
fill="url(#screenGradient)"
stroke="#cbd5e1"
stroke-width="2"
filter="url(#innerShadow)"/>
<!-- Screen bezel -->
<rect x="68" y="38" width="64" height="94" rx="4" ry="4"
fill="#1e293b"
opacity="0.9"/>
<!-- Active screen content area -->
<rect x="72" y="45" width="56" height="80" rx="2" ry="2"
fill="#f1f5f9"/>
<!-- Calendar icon representation -->
<g transform="translate(75, 48)">
<!-- Calendar header -->
<rect x="0" y="0" width="20" height="4" rx="1" fill="#3b82f6"/>
<!-- Calendar body -->
<rect x="0" y="4" width="20" height="16" fill="#e2e8f0" stroke="#cbd5e1" stroke-width="0.5"/>
<!-- Calendar grid lines -->
<line x1="5" y1="4" x2="5" y2="20" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="10" y1="4" x2="10" y2="20" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="15" y1="4" x2="15" y2="20" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="0" y1="8" x2="20" y2="8" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="0" y1="12" x2="20" y2="12" stroke="#94a3b8" stroke-width="0.3"/>
<line x1="0" y1="16" x2="20" y2="16" stroke="#94a3b8" stroke-width="0.3"/>
<!-- Today highlight -->
<rect x="5" y="8" width="5" height="4" fill="#3b82f6" opacity="0.7"/>
</g>
<!-- Notes icon -->
<g transform="translate(100, 48)">
<rect x="0" y="0" width="16" height="20" rx="1" fill="#f8fafc" stroke="#cbd5e1" stroke-width="0.5"/>
<!-- Note lines -->
<line x1="2" y1="4" x2="14" y2="4" stroke="#94a3b8" stroke-width="0.4"/>
<line x1="2" y1="7" x2="12" y2="7" stroke="#94a3b8" stroke-width="0.4"/>
<line x1="2" y1="10" x2="14" y2="10" stroke="#94a3b8" stroke-width="0.4"/>
<line x1="2" y1="13" x2="10" y2="13" stroke="#94a3b8" stroke-width="0.4"/>
</g>
<!-- Shopping list icon -->
<g transform="translate(75, 75)">
<rect x="0" y="0" width="20" height="24" rx="1" fill="#f8fafc" stroke="#cbd5e1" stroke-width="0.5"/>
<!-- Shopping list items -->
<circle cx="3" cy="4" r="1" fill="#10b981"/>
<line x1="6" y1="4" x2="16" y2="4" stroke="#64748b" stroke-width="0.4"/>
<circle cx="3" cy="8" r="1" fill="#10b981"/>
<line x1="6" y1="8" x2="14" y2="8" stroke="#64748b" stroke-width="0.4"/>
<circle cx="3" cy="12" r="1" fill="#e5e7eb" stroke="#9ca3af" stroke-width="0.4"/>
<line x1="6" y1="12" x2="15" y2="12" stroke="#9ca3af" stroke-width="0.4"/>
<circle cx="3" cy="16" r="1" fill="#e5e7eb" stroke="#9ca3af" stroke-width="0.4"/>
<line x1="6" y1="16" x2="12" y2="16" stroke="#9ca3af" stroke-width="0.4"/>
</g>
<!-- Smart home connectivity dots -->
<g transform="translate(100, 75)">
<!-- WiFi/connectivity symbol -->
<circle cx="8" cy="12" r="1.5" fill="#10b981" opacity="0.8"/>
<circle cx="14" cy="8" r="1" fill="#3b82f6" opacity="0.6"/>
<circle cx="12" cy="16" r="0.8" fill="#8b5cf6" opacity="0.7"/>
<circle cx="18" cy="12" r="1.2" fill="#f59e0b" opacity="0.6"/>
<!-- Connection lines -->
<line x1="8" y1="12" x2="14" y2="8" stroke="#10b981" stroke-width="0.5" opacity="0.4"/>
<line x1="8" y1="12" x2="12" y2="16" stroke="#10b981" stroke-width="0.5" opacity="0.4"/>
<line x1="14" y1="8" x2="18" y2="12" stroke="#3b82f6" stroke-width="0.5" opacity="0.4"/>
</g>
<!-- Home base indicator -->
<g transform="translate(100, 145)">
<!-- Simple house shape -->
<polygon points="0,8 8,0 16,8 16,16 0,16" fill="#64748b" opacity="0.7"/>
<rect x="6" y="10" width="4" height="6" fill="#475569"/>
<rect x="2" y="8" width="3" height="3" fill="#1e293b" opacity="0.6"/>
<rect x="11" y="8" width="3" height="3" fill="#1e293b" opacity="0.6"/>
</g>
<!-- Power/status indicator -->
<circle cx="100" cy="170" r="3" fill="#10b981" opacity="0.8">
<animate attributeName="opacity" values="0.4;0.8;0.4" dur="2s" repeatCount="indefinite"/>
</circle>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB