feat: implement WiFi QR code generator and strategy docs
This commit is contained in:
parent
95e062eab6
commit
e539aaf9a1
|
|
@ -0,0 +1,268 @@
|
||||||
|
# 🚀 Side Project Marketing Strategy
|
||||||
|
|
||||||
|
> **"Engineering as Marketing"** – Kostenlose Micro-Tools bauen, um SEO-Traffic abzufangen und in zahlende Kunden zu konvertieren.
|
||||||
|
|
||||||
|
**Status:** Planung abgeschlossen, bereit für Implementierung
|
||||||
|
**Autor:** QR Master Team
|
||||||
|
**Letzte Aktualisierung:** 2026-01-08
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Executive Summary
|
||||||
|
|
||||||
|
Wir nutzen die bewiesene "Engineering as Marketing" Strategie (bekannt von HubSpot's Website Grader, Ahrefs' Free Tools, Shopify's Business Tools), um organischen Traffic über spezialisierte, kostenlose QR-Generatoren zu gewinnen.
|
||||||
|
|
||||||
|
### Das Konzept in einem Satz
|
||||||
|
|
||||||
|
> Anstatt gegen "QR Code Generator" (DA 90+ Konkurrenz) zu kämpfen, bauen wir 10 spezialisierte Tools für Long-Tail-Keywords wie "WiFi QR Code erstellen" oder "VCard QR Generator".
|
||||||
|
|
||||||
|
### Warum das funktioniert
|
||||||
|
|
||||||
|
1. **Weniger Konkurrenz:** "WiFi QR Code Generator" hat 1/10 der Konkurrenz von "QR Code Generator"
|
||||||
|
2. **Höhere Kaufabsicht:** Wer "Restaurant Menu QR Code" sucht, ist bereit für ein Premium-Tool
|
||||||
|
3. **Natürliche Backlinks:** Leute teilen nützliche Tools ("Hier, dieser Generator ist kostenlos")
|
||||||
|
4. **Zero Marginal Cost:** Client-Side Generierung = 0€ Serverkosten pro User
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ROI Projektion (Konservativ)
|
||||||
|
|
||||||
|
| Metrik | Monat 3 | Monat 6 | Monat 12 |
|
||||||
|
|--------|---------|---------|----------|
|
||||||
|
| Organischer Traffic (alle Tools) | 2.000 | 10.000 | 25.000 |
|
||||||
|
| Free Signups (20% Conv.) | 400 | 2.000 | 5.000 |
|
||||||
|
| Paid Customers (3% der Signups) | 12 | 60 | 150 |
|
||||||
|
| **Zusätzlicher MRR** | **108€** | **540€** | **1.350€** |
|
||||||
|
|
||||||
|
> **Benchmarks verwendet:** 2-3% Free-to-Paid Conversion (Industry Standard), 20% Tool-to-Signup (optimistisch, aber erreichbar mit gutem UX).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Die Tools-Roadmap
|
||||||
|
|
||||||
|
### Phase 1: Quick Wins (Woche 1-2)
|
||||||
|
|
||||||
|
Fokus auf **hohes Suchvolumen + geringe Komplexität**.
|
||||||
|
|
||||||
|
| Tool | URL | Geschätztes SV | Implementierungs-Aufwand |
|
||||||
|
|------|-----|----------------|-------------------------|
|
||||||
|
| **WiFi QR Generator** | `/tools/wifi-qr-code` | 40.000/Monat | 4h |
|
||||||
|
| **VCard QR Generator** | `/tools/vcard-qr-code` | 15.000/Monat | 4h |
|
||||||
|
| **WhatsApp QR Generator** | `/tools/whatsapp-qr-code` | 20.000/Monat | 3h |
|
||||||
|
|
||||||
|
### Phase 2: Monetization Focus (Woche 3-4)
|
||||||
|
|
||||||
|
Fokus auf **hohe Conversion-Wahrscheinlichkeit** (B2B Use Cases).
|
||||||
|
|
||||||
|
| Tool | URL | Geschätztes SV | Upsell-Hook |
|
||||||
|
|------|-----|----------------|-------------|
|
||||||
|
| **App Store Link QR** | `/tools/app-store-qr-code` | 5.000/Monat | Smart Routing (iOS/Android) |
|
||||||
|
| **PDF to QR** | `/tools/pdf-qr-code` | 15.000/Monat | PDF Hosting (benötigt Account) |
|
||||||
|
| **Menu QR Generator** | `/tools/menu-qr-code` | 8.000/Monat | Multi-Sprache, Analytics |
|
||||||
|
|
||||||
|
### Phase 3: Differenzierung (Monat 2+)
|
||||||
|
|
||||||
|
Fokus auf **Unique Features** die Konkurrenten nicht haben.
|
||||||
|
|
||||||
|
| Tool | URL | Differenzierung |
|
||||||
|
|------|-----|-----------------|
|
||||||
|
| **Barcode Generator** | `/tools/barcode-generator` | EAN/UPC/ISBN Unterstützung |
|
||||||
|
| **Bitcoin/Crypto QR** | `/tools/bitcoin-qr-code` | Multi-Wallet Format |
|
||||||
|
| **Calendar Event QR** | `/tools/calendar-qr-code` | iCal + Google Cal Support |
|
||||||
|
| **AI Art QR (Viral)** | `/tools/ai-qr-code` | Stable Diffusion Integration |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technische Architektur
|
||||||
|
|
||||||
|
### Warum Client-Side Generierung?
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ USER BROWSER │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────┐ │
|
||||||
|
│ │ Form Input │ -> │ qrcode.js │ -> │ Canvas/SVG │ │
|
||||||
|
│ │ (SSID, PW) │ │ (generation) │ │ (download) │ │
|
||||||
|
│ └─────────────┘ └──────────────┘ └────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ KEINE Server-Calls! │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Vorteile:**
|
||||||
|
- **Privatsphäre:** Passwörter verlassen nie den Browser
|
||||||
|
- **Speed:** Instant Generation (kein Network Latency)
|
||||||
|
- **Kosten:** 0€ pro generiertem Code
|
||||||
|
- **Scale:** Kein Backend-Limit
|
||||||
|
|
||||||
|
### Datei-Struktur (Next.js)
|
||||||
|
|
||||||
|
```
|
||||||
|
src/app/(marketing)/tools/
|
||||||
|
├── wifi-qr-code/
|
||||||
|
│ ├── page.tsx # Server Component (SEO)
|
||||||
|
│ └── WiFiGenerator.tsx # Client Component (Interaktion)
|
||||||
|
├── vcard-qr-code/
|
||||||
|
│ ├── page.tsx
|
||||||
|
│ └── VCardGenerator.tsx
|
||||||
|
└── [weitere tools]/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shared Components
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/components/tools/QRDownloadButtons.tsx
|
||||||
|
// Wiederverwendbare Download-Buttons für alle Tools
|
||||||
|
|
||||||
|
// src/components/tools/UpgradePrompt.tsx
|
||||||
|
// "Willst du Scans tracken?" CTA Box
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SEO-Strategie pro Tool-Page
|
||||||
|
|
||||||
|
Jede Seite folgt dem gleichen bewährten Muster:
|
||||||
|
|
||||||
|
### 1. Above the Fold: Sofort nutzbar
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────┐
|
||||||
|
│ H1: Free WiFi QR Code Generator │
|
||||||
|
│ Subline: Teile dein WLAN in Sekunden │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────────────────────┐ │
|
||||||
|
│ │ [SSID] [Password] [WPA▼] │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ [ Generate QR Code ] │ │
|
||||||
|
│ └─────────────────────────────────┘ │
|
||||||
|
└────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Regel:** Der User muss SOFORT interagieren können. Kein langer Intro-Text.
|
||||||
|
|
||||||
|
### 2. Schema Markup (Pflicht!)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "SoftwareApplication",
|
||||||
|
"name": "WiFi QR Code Generator",
|
||||||
|
"applicationCategory": "UtilitiesApplication",
|
||||||
|
"operatingSystem": "Web Browser",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "0",
|
||||||
|
"priceCurrency": "EUR"
|
||||||
|
},
|
||||||
|
"aggregateRating": {
|
||||||
|
"@type": "AggregateRating",
|
||||||
|
"ratingValue": "4.8",
|
||||||
|
"ratingCount": "1247"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. FAQ Section (Long-Tail Keywords)
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Häufig gestellte Fragen
|
||||||
|
|
||||||
|
### Wie funktioniert ein WiFi QR Code?
|
||||||
|
Der QR Code enthält deine WLAN-Daten im Format...
|
||||||
|
|
||||||
|
### Ist es sicher, mein WiFi Passwort in einem QR Code zu speichern?
|
||||||
|
Ja, der QR Code wird nur lokal in deinem Browser generiert...
|
||||||
|
|
||||||
|
### Kann ich den QR Code später bearbeiten?
|
||||||
|
Dieser Generator erstellt statische Codes. Für editierbare...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Conversion Prompt (Der Hook)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ ✅ QR Code erfolgreich erstellt! │
|
||||||
|
│ │
|
||||||
|
│ ⚠️ Hinweis: Dies ist ein statischer Code. │
|
||||||
|
│ Wenn du dein Passwort änderst, musst du neu drucken. │
|
||||||
|
│ │
|
||||||
|
│ → Erstelle einen dynamischen Code (jederzeit änderbar) │
|
||||||
|
│ │
|
||||||
|
│ Bonus: Sieh wer deinen Code scannt (Datum, Standort) │
|
||||||
|
│ │
|
||||||
|
│ [ Kostenlos registrieren ] │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conversion Optimierung
|
||||||
|
|
||||||
|
### Die "Limitation Awareness" Methode
|
||||||
|
|
||||||
|
Jedes Tool zeigt nach der Generierung **sanft** die Limitierungen auf:
|
||||||
|
|
||||||
|
| Tool | Statische Limitation | Upsell-Feature |
|
||||||
|
|------|---------------------|----------------|
|
||||||
|
| WiFi | Passwort-Änderung = Neudruck | Dynamischer Code (editierbar) |
|
||||||
|
| VCard | Kontakt-Update = Neudruck | Immer aktuelle Visitenkarte |
|
||||||
|
| Menu | Neue Speisekarte = Neudruck | PDF-Hosting + Analytics |
|
||||||
|
| App Store | Nur ein Store-Link | Smart Device Detection |
|
||||||
|
|
||||||
|
### Email Capture vor Download
|
||||||
|
|
||||||
|
**Optional (A/B testen):**
|
||||||
|
```
|
||||||
|
"Gib deine Email ein, um den QR als hochauflösende PNG zu erhalten"
|
||||||
|
```
|
||||||
|
→ Baut Email-Liste, auch wenn User nicht sofort konvertiert.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Erfolgsmetriken (KPIs)
|
||||||
|
|
||||||
|
| KPI | Tool | Ziel (Monat 3) |
|
||||||
|
|-----|------|----------------|
|
||||||
|
| **Organic Sessions** | Google Analytics | 2.000/Monat |
|
||||||
|
| **QR Generations** | PostHog Event | 500/Monat |
|
||||||
|
| **Signup Clicks** | PostHog Event | 100/Monat |
|
||||||
|
| **Actual Signups** | DB Query | 50/Monat |
|
||||||
|
| **Paid Conversion** | Stripe | 5/Monat |
|
||||||
|
|
||||||
|
### Tracking Events implementieren
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Auf jeder Tool-Page
|
||||||
|
posthog.capture('tool_qr_generated', {
|
||||||
|
tool: 'wifi',
|
||||||
|
format: 'png'
|
||||||
|
});
|
||||||
|
|
||||||
|
posthog.capture('tool_signup_cta_clicked', {
|
||||||
|
tool: 'wifi'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nächste Schritte
|
||||||
|
|
||||||
|
1. [ ] **Heute:** WiFi QR Generator implementieren (`/tools/wifi-qr-code`)
|
||||||
|
2. [ ] **Diese Woche:** VCard + WhatsApp Generator
|
||||||
|
3. [ ] **Nächste Woche:** Google Search Console monitoren für erste Impressions
|
||||||
|
4. [ ] **Monat 2:** A/B Test Email-Capture vs. Direct Download
|
||||||
|
5. [ ] **Monat 3:** Phase 2 Tools (App Store, PDF, Menu)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Referenzen & Inspiration
|
||||||
|
|
||||||
|
- [HubSpot Website Grader](https://website.grader.com/) – Das Original "Engineering as Marketing"
|
||||||
|
- [Ahrefs Free Tools](https://ahrefs.com/free-seo-tools) – 12+ Free Tools als Lead Magnets
|
||||||
|
- [Shopify Business Tools](https://www.shopify.com/tools) – Logo Maker, Invoice Generator, etc.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Dieses Dokument wird regelmäßig aktualisiert basierend auf Traffic-Daten und Conversion-Rates.*
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
# 🚀 Kostenlose Wachstums- & Backlink-Strategien (High DA)
|
||||||
|
|
||||||
|
Hier ist ein Plan, um schnell Domain Authority (DA) aufzubauen und kostenlose Reichweite zu generieren, basierend auf deinem aktuellen Status.
|
||||||
|
|
||||||
|
## 1. "Parasite SEO" & High DA Content Platforms
|
||||||
|
Nutze die extrem hohe Domain Authority dieser Plattformen, um für Keywords zu ranken und starke Backlinks zu erhalten. "Cloud Parasites" ist ein guter Start, hier sind weitere:
|
||||||
|
|
||||||
|
* **LinkedIn Pulse (Artikel)**:
|
||||||
|
* Schreibe Artikel wie *"Warum 90% der QR Codes falsch genutzt werden"* oder *"QR Code Tracking Guide 2026"*.
|
||||||
|
* Nutze LinkedIn's eigene SEO-Power. Am Ende immer auf dein Tool verlinken.
|
||||||
|
* *DA: 99*
|
||||||
|
* **Medium**:
|
||||||
|
* Importiere deine Blogposts (nutze den "Import" Button für Canonical Tags, damit du dich nicht selbst kannibalisierst, oder schreibe Zusammenfassungen).
|
||||||
|
* Publiziere in "Publications" (z.B. Marketing-fokussierte Pubs).
|
||||||
|
* *DA: 95*
|
||||||
|
* **Dev.to & Hashnode**:
|
||||||
|
* Da du schon auf `web.dev` (vermutlich Dev Community) bist: Veröffentliche technische "How-To" Artikel.
|
||||||
|
* Thema: "How to build a QR Code Generator with Next.js" (und verlinke auf QR Master als die "Pro-Lösung").
|
||||||
|
* *DA: 91 / 88*
|
||||||
|
* **GitHub Repository**:
|
||||||
|
* Erstelle ein Repository mit einer kuratierten Liste ("Awesome QR Code Tools") oder einem kleinen Open-Source-Skript.
|
||||||
|
* Die `README.md` ist ein sehr starker Backlink.
|
||||||
|
* *DA: 96*
|
||||||
|
* **NPM Package**:
|
||||||
|
* Veröffentliche ein kleines Wrapper-Package. In der Beschreibung auf deine Seite verlinken.
|
||||||
|
* *DA: 96*
|
||||||
|
|
||||||
|
## 2. Nischen-Communities & "Problem Solving"
|
||||||
|
Gehe weg von reinen "SaaS-Gründer" Communities hin zu den **Endnutzern**.
|
||||||
|
|
||||||
|
* **Reddit (Laser-Fokus)**:
|
||||||
|
* Suche nicht nur in r/SaaS. Suche in:
|
||||||
|
* `r/WeddingPlanning`: "Wie mache ich einen QR Code für Einladungen?"
|
||||||
|
* `r/Restaurateur`: "Digitale Speisekarten Lösungen?"
|
||||||
|
* `r/RealEstate`: "QR Codes auf Flyern?"
|
||||||
|
* Sei hilfreich, erwähne dein Tool nur organisch ("Ich habe dafür ein Tool gebaut...").
|
||||||
|
* **Quora**:
|
||||||
|
* Beantworte Fragen wie *"Best free dynamic QR code generator?"*.
|
||||||
|
* Schreibe ausführliche Antworten, nicht nur Links.
|
||||||
|
* **Pinterest (Visuelle Suche)**:
|
||||||
|
* QR Codes sind visuell. Erstelle Pins mit "Creative QR Code Ideas", "Wedding QR Codes", "Restaurant Menu QR Styles".
|
||||||
|
* Verlinke jeden Pin auf deine Landing Page. Pinterest ist eine starke Traffic-Maschine für visuelle Themen.
|
||||||
|
|
||||||
|
## 3. Side Project Marketing (Engineering as Marketing)
|
||||||
|
Erstelle kleine, kostenlose Tools, die als "Lead Magnet" dienen.
|
||||||
|
|
||||||
|
* **Spezialisierte Generatoren**:
|
||||||
|
* Erstelle Landingpages für spezifische Use-Cases: *"Kostenloser WiFi QR Code Generator"*, *"VCard QR Erstellen"*.
|
||||||
|
* Diese Keywords sind einfacher zu ranken als "QR Code Generator".
|
||||||
|
* **Kostenlose Tools Verzeichnisse**:
|
||||||
|
* Es gibt Verzeichnisse nur für kostenlose Tools (z.B. "Tiny Tools", "Free for Dev").
|
||||||
|
|
||||||
|
## 4. Design & CSS Galleries (Für "Premium" Look)
|
||||||
|
Da dein Design "Premium" und hochwertig ist, reiche deine Seite bei Design-Gallerien ein. Das sind oft Do-Follow Backlinks von Design-Seiten.
|
||||||
|
|
||||||
|
* **One Page Love** (Sehr hochwertig)
|
||||||
|
* **SiteInspire**
|
||||||
|
* **Lapa Ninja**
|
||||||
|
* **Godly Website**
|
||||||
|
* *Hinweis: Manche kosten eine kleine Gebühr für schnelle Prüfung, aber oft gibt es Free Submissions.*
|
||||||
|
|
||||||
|
## 5. Cold Outreach (Backlink Sniping)
|
||||||
|
* **"Best of" Listen**:
|
||||||
|
* Suche bei Google nach *"Best QR Code Generators 2025"*.
|
||||||
|
* Schreibe die Autoren der Top 10 Artikel an.
|
||||||
|
* Pitch: *"Hey, cooler Artikel. Mein Tool QR Master ist neu und hat Feature X (z.B. bessere Analytics), das den anderen fehlt. Würde gut in deine Liste passen."*
|
||||||
|
* **Broken Link Building**:
|
||||||
|
* Suche nach Artikeln, die auf tote QR-Code-Tools verlinken (es gibt viele alte Tools, die offline gegangen sind).
|
||||||
|
* Schreibe den Webmaster an: *"Hey, der Link zu Tool X geht nicht mehr. Mein Tool ist eine super Alternative."*
|
||||||
|
|
||||||
|
## 6. Social Media "Content Repurposing"
|
||||||
|
Mach aus einem Content-Stück 10.
|
||||||
|
|
||||||
|
* **Twitter/X Threads**: "Wie QR Codes dein Marketing ruinieren können (und wie man es richtig macht)".
|
||||||
|
* **LinkedIn Carousels**: PDF-Slider mit "5 Fehler bei QR Codes".
|
||||||
|
* **Shorts/Reels**: Zeige den Screen, wie schnell man einen QR Code erstellt. Visuell & schnell.
|
||||||
|
|
||||||
|
## 7. Verzeichnisse (Checkliste)
|
||||||
|
Falls noch nicht erledigt (neben Product Hunt):
|
||||||
|
|
||||||
|
* [ ] **Indie Hackers** (Product Page)
|
||||||
|
* [ ] **Hacker News** ("Show HN")
|
||||||
|
* [ ] **Betalist**
|
||||||
|
* [ ] **10words**
|
||||||
|
* [ ] **Microlaunch**
|
||||||
|
* [ ] **Peerlist**
|
||||||
|
* [ ] **AlternativeTo** (Als Alternative zu "QR Code Monkey" vorschlagen)
|
||||||
|
|
||||||
|
## 8. Technical SEO & Lighthouse
|
||||||
|
Du erwähntest, Lighthouse soll 100 sein.
|
||||||
|
* **Performance**: Bilder optimieren (WebP/AVIF), Lazy Loading.
|
||||||
|
* **Accessiblity**: `aria-labels` für alle Buttons, Kontraste prüfen.
|
||||||
|
* **SEO**: `meta description`, `title` tags, `canonical` URLs, `sitemap.xml`.
|
||||||
|
* **Schema Markup**: Füge `SoftwareApplication` JSON-LD Schema auf deiner Homepage hinzu. Das hilft Google, dich als Software-Tool zu verstehen.
|
||||||
|
|
||||||
|
---
|
||||||
|
**Sofort-Maßnahme**: Erstelle heute einen **LinkedIn Pulse Artikel** und einen **GitHub Account/Repo** für dein Projekt. Das sind 2 High-DA Backlinks garantiert.
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"framer-motion": "^12.24.10",
|
"framer-motion": "^12.24.10",
|
||||||
|
"html-to-image": "^1.11.13",
|
||||||
"i18next": "^23.7.6",
|
"i18next": "^23.7.6",
|
||||||
"ioredis": "^5.3.2",
|
"ioredis": "^5.3.2",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
|
|
@ -5576,6 +5577,12 @@
|
||||||
"void-elements": "3.1.0"
|
"void-elements": "3.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/html-to-image": {
|
||||||
|
"version": "1.11.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz",
|
||||||
|
"integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/i18next": {
|
"node_modules/i18next": {
|
||||||
"version": "23.16.8",
|
"version": "23.16.8",
|
||||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz",
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz",
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"framer-motion": "^12.24.10",
|
"framer-motion": "^12.24.10",
|
||||||
|
"html-to-image": "^1.11.13",
|
||||||
"i18next": "^23.7.6",
|
"i18next": "^23.7.6",
|
||||||
"ioredis": "^5.3.2",
|
"ioredis": "^5.3.2",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,245 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { useState, useRef } from "react";
|
||||||
|
import { QRCodeSVG } from "qrcode.react";
|
||||||
|
import { Wifi, Lock, Eye, EyeOff, Check, AlertTriangle, Download, Printer } from "lucide-react";
|
||||||
|
import * as htmlToImage from "html-to-image";
|
||||||
|
|
||||||
|
export default function WiFiGenerator() {
|
||||||
|
const [ssid, setSsid] = useState("");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const [encryption, setEncryption] = useState("WPA");
|
||||||
|
const [hidden, setHidden] = useState(false);
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
|
// For QR generation string
|
||||||
|
const qrValue = `WIFI:S:${ssid};T:${encryption};P:${password};H:${hidden};;`;
|
||||||
|
|
||||||
|
const qrRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleDownload = (format: "png" | "svg") => {
|
||||||
|
if (!qrRef.current) return;
|
||||||
|
|
||||||
|
if (format === "svg") {
|
||||||
|
const svg = qrRef.current.querySelector("svg");
|
||||||
|
if (svg) {
|
||||||
|
const svgData = new XMLSerializer().serializeToString(svg);
|
||||||
|
const blob = new Blob([svgData], { type: "image/svg+xml" });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = url;
|
||||||
|
link.download = `wifi-qr-${ssid || "network"}.svg`;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
htmlToImage
|
||||||
|
.toPng(qrRef.current)
|
||||||
|
.then(function (dataUrl) {
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.download = `wifi-qr-${ssid || "network"}.png`;
|
||||||
|
link.href = dataUrl;
|
||||||
|
link.click();
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.error("oops, something went wrong!", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 -mt-20 relative z-10">
|
||||||
|
<div className="bg-white rounded-3xl shadow-2xl shadow-indigo-500/10 overflow-hidden border border-slate-100/50 backdrop-blur-xl">
|
||||||
|
<div className="grid lg:grid-cols-12 gap-0">
|
||||||
|
|
||||||
|
{/* LEFT COLUMN - FORM */}
|
||||||
|
<div className="lg:col-span-7 p-8 sm:p-10 lg:p-12 space-y-8 bg-white">
|
||||||
|
<div>
|
||||||
|
<h2 className="text-2xl font-semibold text-slate-800 flex items-center gap-2">
|
||||||
|
Network Details
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-500 mt-1">
|
||||||
|
Enter your WiFi credentials to create a QR code.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-5">
|
||||||
|
|
||||||
|
{/* SSID Input */}
|
||||||
|
<div className="space-y-1.5">
|
||||||
|
<label className="text-sm font-medium text-slate-700 ml-1">
|
||||||
|
Network Name (SSID)
|
||||||
|
</label>
|
||||||
|
<div className="relative group">
|
||||||
|
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||||
|
<Wifi className="h-5 w-5 text-slate-400 group-focus-within:text-indigo-500 transition-colors" />
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={ssid}
|
||||||
|
onChange={(e) => setSsid(e.target.value)}
|
||||||
|
placeholder="e.g. Office_Guest_5G"
|
||||||
|
className="block w-full pl-10 pr-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 transition-all shadow-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Password Input */}
|
||||||
|
<div className="space-y-1.5">
|
||||||
|
<label className="text-sm font-medium text-slate-700 ml-1">
|
||||||
|
Password
|
||||||
|
</label>
|
||||||
|
<div className="relative group">
|
||||||
|
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||||
|
<Lock className="h-5 w-5 text-slate-400 group-focus-within:text-indigo-500 transition-colors" />
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type={showPassword ? "text" : "password"}
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
placeholder="Your WiFi Password"
|
||||||
|
className="block w-full pl-10 pr-12 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 transition-all shadow-sm font-mono"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowPassword(!showPassword)}
|
||||||
|
className="absolute inset-y-0 right-0 pr-3 flex items-center"
|
||||||
|
>
|
||||||
|
{showPassword ? (
|
||||||
|
<EyeOff className="h-5 w-5 text-slate-400 hover:text-slate-600 cursor-pointer transition-colors" />
|
||||||
|
) : (
|
||||||
|
<Eye className="h-5 w-5 text-slate-400 hover:text-slate-600 cursor-pointer transition-colors" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Encryption & Hidden */}
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
|
||||||
|
<div className="space-y-1.5">
|
||||||
|
<label className="text-sm font-medium text-slate-700 ml-1">
|
||||||
|
Encryption
|
||||||
|
</label>
|
||||||
|
<div className="relative">
|
||||||
|
<select
|
||||||
|
value={encryption}
|
||||||
|
onChange={(e) => setEncryption(e.target.value)}
|
||||||
|
className="block w-full pl-4 pr-10 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 transition-all shadow-sm appearance-none"
|
||||||
|
>
|
||||||
|
<option value="WPA">WPA / WPA2 / WPA3</option>
|
||||||
|
<option value="WEP">WEP</option>
|
||||||
|
<option value="nopass">None (Open Network)</option>
|
||||||
|
</select>
|
||||||
|
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-4 text-slate-500">
|
||||||
|
<svg className="h-4 w-4 fill-current" viewBox="0 0 20 20"><path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" /></svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center space-x-3 pt-6 sm:pt-0 sm:mt-8">
|
||||||
|
<div className="flex items-center h-5">
|
||||||
|
<input
|
||||||
|
id="hidden-network"
|
||||||
|
type="checkbox"
|
||||||
|
checked={hidden}
|
||||||
|
onChange={(e) => setHidden(e.target.checked)}
|
||||||
|
className="h-5 w-5 text-indigo-600 border-slate-300 rounded focus:ring-indigo-500 cursor-pointer"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<label htmlFor="hidden-network" className="text-sm font-medium text-slate-700 cursor-pointer select-none">
|
||||||
|
Hidden Network
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="pt-2">
|
||||||
|
<button
|
||||||
|
onClick={() => window.scrollTo({ top: 400, behavior: 'smooth' })}
|
||||||
|
id="generate-btn"
|
||||||
|
className="w-full group relative flex justify-center py-4 px-4 border border-transparent text-lg font-semibold rounded-xl text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-all shadow-lg shadow-indigo-600/30 hover:shadow-indigo-600/50"
|
||||||
|
>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
<svg className="w-5 h-5 animate-pulse" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
|
||||||
|
</svg>
|
||||||
|
Generate QR Code
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<p className="text-xs text-center text-slate-400 mt-3 flex items-center justify-center gap-1">
|
||||||
|
<Lock className="w-3 h-3" /> All data stays on your device
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* RIGHT COLUMN - PREVIEW */}
|
||||||
|
<div className="lg:col-span-5 bg-slate-50 border-l border-slate-100 p-8 sm:p-10 flex flex-col items-center justify-center relative overflow-hidden">
|
||||||
|
{/* Background Pattern */}
|
||||||
|
<div className="absolute inset-0 opacity-40" style={{
|
||||||
|
backgroundImage: 'radial-gradient(#cbd5e1 1px, transparent 1px)',
|
||||||
|
backgroundSize: '24px 24px'
|
||||||
|
}}></div>
|
||||||
|
|
||||||
|
<div className="relative z-10 w-full max-w-sm mx-auto text-center space-y-6">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xs font-bold text-slate-400 uppercase tracking-widest mb-4">Live Preview</h3>
|
||||||
|
|
||||||
|
{/* QR Card */}
|
||||||
|
<div className="bg-white p-6 rounded-2xl shadow-xl shadow-slate-200/50 border border-slate-100 inline-block mb-2 transform transition-transform hover:scale-105 duration-300" ref={qrRef}>
|
||||||
|
<div className="bg-white p-2 rounded-lg">
|
||||||
|
<QRCodeSVG
|
||||||
|
value={qrValue}
|
||||||
|
size={200}
|
||||||
|
level="H"
|
||||||
|
includeMargin={false}
|
||||||
|
className="w-full h-auto"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Download Actions */}
|
||||||
|
<div className="grid grid-cols-3 gap-3 w-full">
|
||||||
|
<button onClick={() => handleDownload("png")} className="flex items-center justify-center px-4 py-2 border border-slate-200 shadow-sm text-sm font-medium rounded-lg text-slate-700 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
|
||||||
|
PNG
|
||||||
|
</button>
|
||||||
|
<button onClick={() => handleDownload("svg")} className="flex items-center justify-center px-4 py-2 border border-slate-200 shadow-sm text-sm font-medium rounded-lg text-slate-700 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
|
||||||
|
SVG
|
||||||
|
</button>
|
||||||
|
<button onClick={() => window.print()} className="flex items-center justify-center px-4 py-2 border border-slate-200 shadow-sm text-sm font-medium rounded-lg text-slate-700 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
|
||||||
|
Print
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button onClick={() => window.print()} className="w-full flex items-center justify-center px-4 py-3 border border-indigo-100 text-sm font-semibold rounded-xl text-indigo-700 bg-indigo-50 hover:bg-indigo-100 transition-colors gap-2">
|
||||||
|
<Printer className="w-4 h-4" />
|
||||||
|
Print WiFi Card Template
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* UPSELL BOX */}
|
||||||
|
<div className="mt-8 bg-amber-50 rounded-2xl p-6 border border-amber-100 flex flex-col sm:flex-row items-center justify-between gap-4 max-w-4xl mx-auto shadow-sm">
|
||||||
|
<div className="flex items-start gap-4">
|
||||||
|
<div className="p-3 bg-amber-100 rounded-full shrink-0 text-amber-600">
|
||||||
|
<AlertTriangle className="w-6 h-6" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-lg font-bold text-slate-800">Change passwords often?</h4>
|
||||||
|
<p className="text-slate-600 text-sm mt-1 max-w-md">
|
||||||
|
Note: This is a static QR Code. If you update your WiFi password, you'll need to reprint this code.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="/dashboard" className="w-full sm:w-auto px-6 py-3 bg-amber-500 hover:bg-amber-600 text-white font-semibold rounded-xl transition-colors shadow-lg shadow-amber-500/20 whitespace-nowrap text-center">
|
||||||
|
Try Dynamic Codes
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
import React from 'react';
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import WiFiGenerator from './WiFiGenerator';
|
||||||
|
import { Wifi, Shield, Zap } from 'lucide-react';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Free WiFi QR Code Generator | Connect Instantly & Securely',
|
||||||
|
description: 'Create a free QR code for your WiFi network. Instant connection for guests, 100% client-side security (your password never leaves your browser). No app needed.',
|
||||||
|
alternates: {
|
||||||
|
canonical: 'https://qrmaster.com/tools/wifi-qr-code',
|
||||||
|
},
|
||||||
|
openGraph: {
|
||||||
|
title: 'Free WiFi QR Code Generator | Connect Instantly',
|
||||||
|
description: 'Share your WiFi without sharing your password. Generate a secure QR code in seconds.',
|
||||||
|
type: 'website',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function WiFiQRCodePage() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-slate-50 font-sans">
|
||||||
|
|
||||||
|
{/* HERO SECTION */}
|
||||||
|
<section className="relative bg-gradient-to-br from-indigo-600 to-blue-500 pt-32 pb-48 px-4 sm:px-6 lg:px-8 overflow-hidden">
|
||||||
|
{/* Background Decorative Elements */}
|
||||||
|
<div className="absolute top-0 left-0 w-full h-full overflow-hidden z-0">
|
||||||
|
<div className="absolute top-0 left-1/4 w-96 h-96 bg-white/10 rounded-full blur-3xl -translate-y-1/2"></div>
|
||||||
|
<div className="absolute bottom-0 right-1/4 w-96 h-96 bg-indigo-900/20 rounded-full blur-3xl translate-y-1/2"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative z-10 max-w-4xl mx-auto text-center">
|
||||||
|
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10">
|
||||||
|
<span className="flex h-2 w-2 relative">
|
||||||
|
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
|
||||||
|
<span className="relative inline-flex rounded-full h-2 w-2 bg-emerald-500"></span>
|
||||||
|
</span>
|
||||||
|
Free Tool
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6 drop-shadow-sm">
|
||||||
|
Secure WiFi QR Code <br className="hidden sm:block" /> Generator
|
||||||
|
</h1>
|
||||||
|
<p className="text-lg md:text-xl text-indigo-100 max-w-2xl mx-auto mb-10 leading-relaxed">
|
||||||
|
Connect guests instantly without typing passwords. <br />
|
||||||
|
<span className="font-semibold text-white">100% Client-side & Private.</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap justify-center gap-4 text-sm font-medium text-white/80">
|
||||||
|
<div className="flex items-center gap-2 bg-white/5 px-4 py-2 rounded-lg backdrop-blur-sm border border-white/5">
|
||||||
|
<Shield className="w-4 h-4 text-emerald-400" />
|
||||||
|
100% Private
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 bg-white/5 px-4 py-2 rounded-lg backdrop-blur-sm border border-white/5">
|
||||||
|
<Zap className="w-4 h-4 text-amber-400" />
|
||||||
|
Instant Generation
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 bg-white/5 px-4 py-2 rounded-lg backdrop-blur-sm border border-white/5">
|
||||||
|
<Wifi className="w-4 h-4 text-blue-400" />
|
||||||
|
Always Free
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* GENERATOR APP SECTION */}
|
||||||
|
<WiFiGenerator />
|
||||||
|
|
||||||
|
{/* FAQ SECTION */}
|
||||||
|
<section className="max-w-3xl mx-auto px-4 sm:px-6 py-24">
|
||||||
|
<div className="text-center mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-slate-800">Frequently Asked Questions</h2>
|
||||||
|
<p className="text-slate-500 mt-2">Everything you need to know about WiFi QR codes.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<FaqItem
|
||||||
|
question="Is it safe to type my password here?"
|
||||||
|
answer="Yes, absolutely. This tool uses 'Client-Side Encryption', meaning your WiFi credentials never leave your browser. They are processed locally on your device to generate the QR code image. We never see, store, or transmit your password."
|
||||||
|
/>
|
||||||
|
<FaqItem
|
||||||
|
question="Does this work on both iPhone and Android?"
|
||||||
|
answer="Yes! Most modern smartphones (iOS and Android) have a built-in QR code scanner in their camera app. Guests just need to point their camera at the code and tap the notification to join your network."
|
||||||
|
/>
|
||||||
|
<FaqItem
|
||||||
|
question="Do WiFi QR codes expire?"
|
||||||
|
answer="No, static WiFi QR codes never expire. However, if you change your WiFi password or network name (SSID), the old QR code will stop working and you will need to generate a new one."
|
||||||
|
/>
|
||||||
|
<FaqItem
|
||||||
|
question="Can I hide my WiFi network?"
|
||||||
|
answer="Yes, key in your hidden network credentials and check the 'Hidden Network' box. The generated QR code will contain the necessary instructions for devices to find and connect to your hidden network."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FaqItem({ question, answer }: { question: string, answer: string }) {
|
||||||
|
return (
|
||||||
|
<details className="group bg-white rounded-2xl shadow-sm border border-slate-200 overflow-hidden">
|
||||||
|
<summary className="flex items-center justify-between p-6 cursor-pointer list-none text-slate-800 font-semibold hover:bg-slate-50 transition-colors">
|
||||||
|
{question}
|
||||||
|
<span className="transition group-open:rotate-180">
|
||||||
|
<svg fill="none" height="24" shapeRendering="geometricPrecision" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1.5" viewBox="0 0 24 24" width="24"><path d="M6 9l6 6 6-6"></path></svg>
|
||||||
|
</span>
|
||||||
|
</summary>
|
||||||
|
<div className="text-slate-600 px-6 pb-6 pt-0 leading-relaxed">
|
||||||
|
{answer}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue