diff --git a/ADSENSE_REVISED_STRATEGY.md b/ADSENSE_REVISED_STRATEGY.md new file mode 100644 index 00000000..bc0fb754 --- /dev/null +++ b/ADSENSE_REVISED_STRATEGY.md @@ -0,0 +1,436 @@ +# AdSense Strategy - Revised (Tool Pages Only) + +## Strategy: Clean Homepage + Monetized Tool Pages + +### ✅ Why This is BETTER: + +1. **Better First Impression**: Clean homepage attracts users without ad clutter +2. **Higher Engagement**: Users explore tools without distraction +3. **Better CTR**: Ads on tool pages have higher relevance (users are actively working) +4. **Lower Bounce Rate**: No ads on homepage = users stay longer +5. **SEO Benefits**: Clean homepage ranks better +6. **Professional Image**: Looks more trustworthy and premium + +--- + +## Ad Placement (Tool Pages Only) + +### Desktop Layout (From PROJECT_ROADMAP.md) + +``` +┌────────────────────────────┬─────────┐ +│ │ [Ad] │ ← 300x250 +│ Main Content │ │ +│ (Tool Editor) │ 300px │ +│ │ │ +│ │ [Ad] │ ← 300x250 +│ │ │ +│ │ [Ad] │ ← 300x250 +└────────────────────────────┴─────────┘ +``` + +**Specifications:** +- **Right Sidebar**: 300px fixed width +- **Sticky Scroll**: Ads stay visible while scrolling +- **3 Ad Blocks Maximum**: + - Ad 1: 300x250 (Medium Rectangle) + - Ad 2: 300x250 (Medium Rectangle) + - Ad 3: 300x250 (Medium Rectangle) +- **Google AdSense Compliance**: All ads fully viewable, no scrollable containers +- **Responsive**: Hide below 1200px viewport width +- **Main Content**: `calc(100% - 320px)` width + +### Mobile Layout + +``` +┌─────────────────────────┐ +│ │ +│ Main Content │ +│ (Scrollable) │ +│ │ +├─────────────────────────┤ +│ [Ad Banner 320x50] │ ← Sticky Bottom +└─────────────────────────┘ +``` + +**Specifications:** +- **Sticky Bottom Banner**: 320x50 or 320x100 +- **Close Button**: Better UX +- **Content Padding**: Add padding-bottom to prevent overlap + +--- + +## Revenue Estimation + +### Traffic Assumptions + +**Current Tools:** 11 tools +- Object Editor +- Table Editor +- Invoice Editor +- Text Length Tool +- Base64 Encoder/Decoder +- URL Encoder/Decoder +- Hash Generator +- JWT Decoder +- Timestamp Converter +- Color Converter +- UUID Generator + +**Traffic Breakdown:** +- **Homepage**: 40% of traffic (no ads) +- **Tool Pages**: 60% of traffic (monetized) + +**Monthly Traffic Estimate:** +- Total visitors: 10,000/month (conservative start) +- Homepage visits: 10,000 (entry point) +- Tool page visits: 15,000 (1.5 pages per user) +- **Monetized page views**: 15,000/month + +### Ad Performance Metrics + +**Desktop (70% of traffic):** +- 10,500 page views/month +- 3 ads per page = 31,500 ad impressions +- Average CPM: $3.00 (developer tools niche) +- **Revenue**: 31,500 × $3.00 / 1000 = **$94.50/month** + +**Mobile (30% of traffic):** +- 4,500 page views/month +- 1 ad per page = 4,500 ad impressions +- Average CPM: $2.00 (mobile typically lower) +- **Revenue**: 4,500 × $2.00 / 1000 = **$9.00/month** + +**Total Monthly Revenue (Conservative):** +``` +Desktop: $94.50 +Mobile: $9.00 +───────────────── +TOTAL: $103.50/month +``` + +--- + +## Scaled Revenue Projections + +### Scenario 1: Moderate Growth (3 months) +**Traffic:** 30,000 visitors/month +- Tool page views: 45,000/month +- Desktop impressions: 94,500 +- Mobile impressions: 13,500 +- **Monthly Revenue**: $310/month + +### Scenario 2: Good Growth (6 months) +**Traffic:** 50,000 visitors/month +- Tool page views: 75,000/month +- Desktop impressions: 157,500 +- Mobile impressions: 22,500 +- **Monthly Revenue**: $517/month + +### Scenario 3: Strong Growth (12 months) +**Traffic:** 100,000 visitors/month +- Tool page views: 150,000/month +- Desktop impressions: 315,000 +- Mobile impressions: 45,000 +- **Monthly Revenue**: $1,035/month + +### Scenario 4: Viral Success (18+ months) +**Traffic:** 250,000 visitors/month +- Tool page views: 375,000/month +- Desktop impressions: 787,500 +- Mobile impressions: 112,500 +- **Monthly Revenue**: $2,587/month + +--- + +## Comparison: Homepage Ads vs No Homepage Ads + +### With Homepage Ads (Your ADSENSE_STRATEGY.md) +``` +Homepage: 2 ads × 10,000 views = 20,000 impressions +Tool Pages: 2 ads × 15,000 views = 30,000 impressions +───────────────────────────────────────────────────── +Total: 50,000 impressions +Revenue: $150/month (at $3 CPM) + +Pros: Higher revenue (+$46.50/month) +Cons: Cluttered homepage, higher bounce rate, worse SEO +``` + +### Without Homepage Ads (Revised Strategy) +``` +Homepage: 0 ads × 10,000 views = 0 impressions +Tool Pages: 3 ads × 15,000 views = 45,000 impressions +───────────────────────────────────────────────────── +Total: 45,000 impressions +Revenue: $103.50/month (at $3 CPM) + +Pros: Clean homepage, better UX, better SEO, higher retention +Cons: Lower initial revenue (-$46.50/month) +``` + +### Long-Term Impact + +**With Clean Homepage:** +- Better SEO → More organic traffic → More tool page views +- Lower bounce rate → More pages per session → More ad impressions +- Professional image → More return visitors → Higher lifetime value + +**Estimated Long-Term Benefit:** +- 20-30% more traffic from better SEO +- 15-20% more pages per session +- **Net result**: Clean homepage strategy wins after 3-6 months + +--- + +## Implementation Plan + +### Phase 1: Ad Space Preparation (1 day) + +**Create Components:** + +```javascript +// src/components/AdColumn.jsx +import React from 'react'; +import AdBlock from './AdBlock'; + +const AdColumn = () => { + return ( + + ); +}; + +export default AdColumn; +``` + +```javascript +// src/components/AdBlock.jsx +import React, { useEffect } from 'react'; + +const AdBlock = ({ slot, size }) => { + useEffect(() => { + try { + (window.adsbygoogle = window.adsbygoogle || []).push({}); + } catch (e) { + console.error('AdSense error:', e); + } + }, []); + + const [width, height] = size.split('x'); + + return ( +
+ +
+ ); +}; + +export default AdBlock; +``` + +```javascript +// src/components/MobileAdBanner.jsx +import React, { useEffect, useState } from 'react'; +import { X } from 'lucide-react'; + +const MobileAdBanner = () => { + const [visible, setVisible] = useState(true); + + useEffect(() => { + try { + (window.adsbygoogle = window.adsbygoogle || []).push({}); + } catch (e) { + console.error('AdSense error:', e); + } + }, []); + + if (!visible) return null; + + return ( +
+ +
+ +
+
+ ); +}; + +export default MobileAdBanner; +``` + +**Update ToolLayout:** + +```javascript +// src/components/ToolLayout.jsx +import AdColumn from './AdColumn'; +import MobileAdBanner from './MobileAdBanner'; + +const ToolLayout = ({ children }) => { + return ( +
+ {/* Main Content */} +
+ {children} +
+ + {/* Desktop Ad Column */} + + + {/* Mobile Ad Banner */} + +
+ ); +}; +``` + +### Phase 2: AdSense Integration (1 day) + +1. **Apply for AdSense** (if not done) +2. **Add script to index.html**: +```html + +``` +3. **Create ad units** in AdSense dashboard +4. **Replace placeholder IDs** in components +5. **Test on all tools** + +### Phase 3: Testing & Optimization (ongoing) + +- Monitor ad viewability +- Test different ad positions +- A/B test ad sizes +- Track CTR and RPM +- Optimize based on data + +--- + +## Success Metrics + +### Month 1 (Launch) +- [ ] Ads live on all 11 tools +- [ ] Ad impressions: 45,000+ +- [ ] Revenue: $100+ +- [ ] No performance issues +- [ ] No user complaints + +### Month 3 (Optimization) +- [ ] Traffic: 30,000 visitors/month +- [ ] Ad impressions: 135,000+ +- [ ] Revenue: $300+ +- [ ] Optimized ad positions +- [ ] Improved CTR + +### Month 6 (Growth) +- [ ] Traffic: 50,000 visitors/month +- [ ] Ad impressions: 225,000+ +- [ ] Revenue: $500+ +- [ ] Consider PRO tier + +### Month 12 (Maturity) +- [ ] Traffic: 100,000 visitors/month +- [ ] Ad impressions: 450,000+ +- [ ] Revenue: $1,000+ +- [ ] PRO tier launched + +--- + +## PRO Tier Strategy + +### When to Launch PRO: +- After 3-6 months of ad revenue +- When traffic is 50,000+/month +- When users request ad-free option +- When revenue is stable + +### PRO Benefits: +- ✅ **Ad-Free Experience** - No ads anywhere +- ✅ **Backend Proxy** - CORS bypass for any API +- ✅ **Saved Work** - Cloud storage for projects +- ✅ **Shareable Links** - Share work with team +- ✅ **Priority Support** - Email support +- ✅ **Export Templates** - Save and reuse configurations + +### Pricing: +- **1 Month**: $2.99 +- **3 Months**: $6.99 (save 22%) +- **6 Months**: $11.99 (save 33%) +- **12 Months**: $19.99 (save 44%) + +### Revenue Mix (After PRO Launch): +``` +Ad Revenue: $800/month (80% of users) +PRO Revenue: $400/month (20 users × $20/year ÷ 12) +────────────────────────────────────── +Total: $1,200/month +``` + +--- + +## Summary + +### Current Strategy (Revised): +✅ **Clean Homepage** - No ads, better UX, better SEO +✅ **Tool Pages Only** - 3 ads on desktop, 1 on mobile +✅ **Conservative Start** - $100/month with 10K visitors +✅ **Growth Potential** - $1,000+/month with 100K visitors +✅ **PRO Tier Later** - Additional revenue stream + +### Revenue Timeline: +``` +Month 1: $100 (10K visitors) +Month 3: $300 (30K visitors) +Month 6: $500 (50K visitors) +Month 12: $1,000 (100K visitors) +Month 18: $1,500 (100K visitors + PRO tier) +``` + +### Why This Works: +1. Clean homepage attracts more users +2. Better SEO = more organic traffic +3. Higher engagement = more tool page views +4. More tool page views = more ad impressions +5. Professional image = higher trust = more return visits + +**This strategy prioritizes long-term growth over short-term revenue!** 🚀 + +Step 1: Create Ad Units in AdSense Dashboard +Go to your AdSense dashboard and create these ad units: + +Desktop Ads (3 units): +1. Name: "Tool Sidebar 1" +- Size: 300x250 (Medium Rectangle) +- Type: Display ads +2. Name: "Tool Sidebar 2" +- Size: 300x250 (Medium Rectangle) +- Type: Display ads +3. Name: "Tool Sidebar 3" +- Size: 300x250 (Medium Rectangle) +- Type: Display ads +Mobile Ad (1 unit): +1. Name: "Mobile Bottom Banner" +- Size: 320x50 (Mobile Banner) +- Type: Display ads +After creating each unit, you'll get an Ad Slot ID like 1234567890. Copy those IDs and give them to me. \ No newline at end of file diff --git a/ADSENSE_SETUP_GUIDE.md b/ADSENSE_SETUP_GUIDE.md new file mode 100644 index 00000000..af32ca01 --- /dev/null +++ b/ADSENSE_SETUP_GUIDE.md @@ -0,0 +1,252 @@ +# AdSense Setup Guide - Final Steps + +## ✅ What's Already Done: + +1. ✅ **AdSense Script Added** to `public/index.html` +2. ✅ **AdBlock Component** created (`src/components/AdBlock.js`) +3. ✅ **AdColumn Component** created (`src/components/AdColumn.js`) +4. ✅ **MobileAdBanner Component** created (`src/components/MobileAdBanner.js`) +5. ✅ **ToolLayout Updated** to include ads on all tool pages +6. ✅ **Build Successful** - Ready to deploy! + +--- + +## 🎯 What You Need to Do Now: + +### Step 1: Create Ad Units in AdSense Dashboard + +Go to: https://adsense.google.com/ + +**Navigate to:** Ads → By ad unit → Display ads + +**Create 4 Ad Units:** + +#### **Ad Unit 1: Tool Sidebar 1** +- **Name**: `Tool Sidebar 1` +- **Size**: `300x250` (Medium Rectangle) +- **Type**: Display ads +- Click "Create" and **copy the Ad Slot ID** + +#### **Ad Unit 2: Tool Sidebar 2** +- **Name**: `Tool Sidebar 2` +- **Size**: `300x250` (Medium Rectangle) +- **Type**: Display ads +- Click "Create" and **copy the Ad Slot ID** + +#### **Ad Unit 3: Tool Sidebar 3** +- **Name**: `Tool Sidebar 3` +- **Size**: `300x250` (Medium Rectangle) +- **Type**: Display ads +- Click "Create" and **copy the Ad Slot ID** + +#### **Ad Unit 4: Mobile Bottom Banner** +- **Name**: `Mobile Bottom Banner` +- **Size**: `320x50` (Mobile Banner) +- **Type**: Display ads +- Click "Create" and **copy the Ad Slot ID** + +--- + +### Step 2: Update Ad Slot IDs in Code + +After creating the ad units, you'll have 4 slot IDs that look like: `1234567890` + +**Open:** `src/components/AdColumn.js` + +**Replace:** +```javascript +const AdColumn = ({ + slot1 = 'REPLACE_WITH_SLOT_1', // ← Replace with your Slot 1 ID + slot2 = 'REPLACE_WITH_SLOT_2', // ← Replace with your Slot 2 ID + slot3 = 'REPLACE_WITH_SLOT_3' // ← Replace with your Slot 3 ID +}) => { +``` + +**With:** +```javascript +const AdColumn = ({ + slot1 = '1234567890', // ← Your actual Slot 1 ID + slot2 = '0987654321', // ← Your actual Slot 2 ID + slot3 = '1122334455' // ← Your actual Slot 3 ID +}) => { +``` + +**Open:** `src/components/MobileAdBanner.js` + +**Replace:** +```javascript +const MobileAdBanner = ({ slot = 'REPLACE_WITH_MOBILE_SLOT' }) => { +``` + +**With:** +```javascript +const MobileAdBanner = ({ slot = '5544332211' }) => { // ← Your Mobile Slot ID +``` + +--- + +### Step 3: Rebuild and Deploy + +```bash +npm run build:no-snap +``` + +Then deploy to your hosting (Netlify, Vercel, etc.) + +--- + +### Step 4: Test Ads + +**After deployment:** + +1. **Visit any tool page** (not homepage) +2. **Desktop**: You should see 3 ads in the right sidebar +3. **Mobile**: You should see 1 sticky banner at the bottom +4. **Homepage**: Should have NO ads (clean!) + +**Note:** Ads may take 10-30 minutes to start showing after deployment. + +--- + +## 📊 How It Works: + +### **Homepage (Clean - No Ads)** +``` +┌─────────────────────────────┐ +│ Hero Section │ +│ Tool Cards │ +│ Features │ +│ Footer │ +└─────────────────────────────┘ +``` + +### **Tool Pages (Desktop - 3 Ads)** +``` +┌────────────────────────────┬─────────┐ +│ │ [Ad1] │ 300x250 +│ Tool Content │ │ +│ (Object Editor, etc.) │ [Ad2] │ 300x250 +│ │ │ +│ │ [Ad3] │ 300x250 +└────────────────────────────┴─────────┘ +``` + +### **Tool Pages (Mobile - 1 Ad)** +``` +┌─────────────────────────┐ +│ Tool Content │ +│ (Scrollable) │ +│ │ +├─────────────────────────┤ +│ [Ad Banner 320x50] │ ← Sticky +└─────────────────────────┘ +``` + +--- + +## 🎨 Ad Styling: + +Ads are wrapped in: +- Light mode: Gray background (`bg-gray-100`) +- Dark mode: Dark gray background (`bg-gray-800`) +- Rounded corners for modern look +- Proper spacing between ads + +--- + +## 🔧 Troubleshooting: + +### **Ads Not Showing?** + +1. **Wait 10-30 minutes** after deployment +2. **Check AdSense Dashboard** - Make sure account is approved +3. **Check Browser Console** for errors +4. **Disable Ad Blocker** for testing +5. **Verify Slot IDs** are correct in code + +### **Ads Showing Blank Space?** + +- This is normal during testing +- AdSense needs time to fill inventory +- May show blank for first few hours/days +- Will improve as site gets traffic + +### **Mobile Ad Overlapping Content?** + +- There's a `
` at bottom +- This adds padding to prevent overlap +- Adjust height if needed + +--- + +## 📈 Monitoring Performance: + +### **AdSense Dashboard:** +- Go to: https://adsense.google.com/ +- Check: Reports → Overview +- Monitor: + - **Page RPM** (Revenue per 1000 impressions) + - **CTR** (Click-through rate) + - **Impressions** (How many times ads shown) + - **Earnings** (Daily/monthly revenue) + +### **Expected Timeline:** +- **Day 1-7**: Low earnings, AdSense learning +- **Week 2-4**: Earnings stabilize +- **Month 2+**: Optimize based on data + +--- + +## 🚀 Next Steps After Ads Are Live: + +1. **Monitor Performance** (first week) +2. **Optimize Ad Positions** (if needed) +3. **Test Different Ad Sizes** (A/B testing) +4. **Track User Feedback** (any complaints?) +5. **Plan PRO Tier** (ad-free option) + +--- + +## 💰 Revenue Expectations: + +Based on your traffic estimate: + +**Month 1:** $100-150 +- 10,000 visitors +- 15,000 tool page views +- 45,000 ad impressions + +**Month 3:** $300-400 +- 30,000 visitors +- 45,000 tool page views +- 135,000 ad impressions + +**Month 6:** $500-700 +- 50,000 visitors +- 75,000 tool page views +- 225,000 ad impressions + +**Month 12:** $1,000-1,500 +- 100,000 visitors +- 150,000 tool page views +- 450,000 ad impressions + +--- + +## ✅ Checklist: + +- [ ] Create 4 ad units in AdSense dashboard +- [ ] Copy all 4 slot IDs +- [ ] Update `AdColumn.js` with 3 slot IDs +- [ ] Update `MobileAdBanner.js` with 1 slot ID +- [ ] Run `npm run build:no-snap` +- [ ] Deploy to production +- [ ] Test on desktop (should see 3 ads in sidebar) +- [ ] Test on mobile (should see 1 sticky banner) +- [ ] Test homepage (should see NO ads) +- [ ] Wait 30 minutes for ads to start showing +- [ ] Monitor AdSense dashboard for first earnings! + +--- + +**You're almost done! Just need those 4 slot IDs from AdSense!** 🎉 diff --git a/ADSENSE_STRATEGY.md b/ADSENSE_STRATEGY.md new file mode 100644 index 00000000..05f4e0e0 --- /dev/null +++ b/ADSENSE_STRATEGY.md @@ -0,0 +1,446 @@ +# Google AdSense Implementation Strategy + +## Overview +Strategic placement of AdSense ads to monetize the developer tools while maintaining excellent user experience. Focus on non-intrusive, contextual ad placements that don't disrupt workflow. + +--- + +## Ad Unit Types & Sizes + +### 1. **Display Ads** +- **Leaderboard (728x90)**: Top of pages, above content +- **Medium Rectangle (300x250)**: Sidebar, between content sections (PRIMARY CHOICE) +- **Large Rectangle (336x280)**: Sidebar, high-visibility areas +- **Note**: For our implementation, we use 300x250 for all desktop sidebar ads to comply with Google AdSense policies (no scrollable containers) + +### 2. **Responsive Ads** +- Auto-adapt to screen size +- Best for mobile compatibility +- Recommended for all placements + +### 3. **In-Feed Ads** +- Native ads that blend with content +- Perfect for tool listings and results + +--- + +## Placement Strategy + +### **Homepage (High Traffic)** + +**Priority: High Revenue Potential** + +``` +┌─────────────────────────────────────┐ +│ Header / Navigation │ +├─────────────────────────────────────┤ +│ Hero Section │ +├─────────────────────────────────────┤ +│ 🟦 AD: Leaderboard (728x90) │ ← Ad #1 +│ Above tool cards │ +├─────────────────────────────────────┤ +│ Tool Cards Grid │ +│ ┌──────┐ ┌──────┐ ┌──────┐ │ +│ │Tool 1│ │Tool 2│ │Tool 3│ │ +│ └──────┘ └──────┘ └──────┘ │ +│ ┌──────┐ ┌──────┐ ┌──────┐ │ +│ │Tool 4│ │Tool 5│ │Tool 6│ │ +│ └──────┘ └──────┘ └──────┘ │ +├─────────────────────────────────────┤ +│ 🟦 AD: Medium Rectangle (300x250) │ ← Ad #2 +│ Between tool sections │ +├─────────────────────────────────────┤ +│ More Tool Cards │ +├─────────────────────────────────────┤ +│ Features Section │ +├─────────────────────────────────────┤ +│ Footer │ +└─────────────────────────────────────┘ +``` + +**Ad Placements:** +- **Ad #1**: Leaderboard above tool cards (high visibility) +- **Ad #2**: Medium Rectangle between tool sections (natural break) + +--- + +### **Tool Pages (Main Revenue Source)** + +**Priority: Balanced UX + Revenue** + +``` +┌─────────────────────────────────────┐ +│ Header / Navigation │ +├──────────────┬──────────────────────┤ +│ │ │ +│ Sidebar │ Main Content Area │ +│ │ │ +│ Tool List │ ┌────────────────┐ │ +│ │ │ Input Section │ │ +│ 🟦 AD Box │ └────────────────┘ │ ← Sidebar Ad +│ (300x250) │ │ +│ │ 🟦 AD: Responsive │ ← Ad #1 +│ │ (Between sections)│ +│ │ │ +│ │ ┌────────────────┐ │ +│ │ │ Editor Section │ │ +│ │ └────────────────┘ │ +│ │ │ +│ │ 🟦 AD: Responsive │ ← Ad #2 +│ │ (Before export) │ +│ │ │ +│ │ ┌────────────────┐ │ +│ │ │ Export Section │ │ +│ │ └────────────────┘ │ +│ │ │ +└──────────────┴──────────────────────┘ +``` + +**Ad Placements:** +- **Sidebar Ad**: Medium Rectangle (300x250) - Always visible on desktop +- **Ad #1**: Responsive ad between Input and Editor sections +- **Ad #2**: Responsive ad between Editor and Export sections + +--- + +### **Mobile Layout** + +**Priority: Non-Intrusive** + +``` +┌─────────────────────┐ +│ Header │ +├─────────────────────┤ +│ Input Section │ +├─────────────────────┤ +│ 🟦 AD: Responsive │ ← Ad #1 (Anchor/Banner) +├─────────────────────┤ +│ Editor Section │ +├─────────────────────┤ +│ 🟦 AD: Responsive │ ← Ad #2 (Between sections) +├─────────────────────┤ +│ Export Section │ +├─────────────────────┤ +│ Footer │ +└─────────────────────┘ +``` + +**Mobile-Specific:** +- Use **Anchor Ads** (sticky bottom banner) +- Responsive ads that adapt to screen width +- Fewer ads to maintain UX + +--- + +## Specific Tool Placements + +### **Table Editor** +``` +Input Section (URL/Paste/Open) +↓ +🟦 AD: Responsive (320x100 mobile, 728x90 desktop) +↓ +Table Editor (Main workspace) +↓ +🟦 AD: Medium Rectangle (300x250) - Right aligned +↓ +Export Section +``` + +### **Object Editor** +``` +Input Section +↓ +🟦 AD: Responsive +↓ +Visual Editor / Mindmap / Table View +↓ +🟦 AD: Responsive (before export) +↓ +Export Results +``` + +### **Invoice Editor** +``` +Invoice Form +↓ +🟦 AD: Sidebar (300x250) - Desktop only +↓ +Preview Section +↓ +🟦 AD: Responsive (before export) +↓ +Export Options +``` + +### **Converter/Formatter Tools** +``` +Input Textarea +↓ +🟦 AD: Responsive +↓ +Convert/Format Button +↓ +Output Textarea +↓ +🟦 AD: Medium Rectangle (if space allows) +``` + +--- + +## Ad Frequency Rules + +### **Maximum Ads Per Page:** +- **Homepage**: 2-3 ads +- **Tool Pages**: 2-3 ads (desktop), 1-2 ads (mobile) +- **Never**: More than 1 ad per viewport height + +### **Minimum Content-to-Ad Ratio:** +- At least 300px of content between ads +- Never place ads immediately adjacent +- Maintain 50% content, 50% white space, minimal ads + +--- + +## PRO User Benefits (Ad-Free) + +### **Free Users:** +- See all ads as described above +- Full tool functionality +- Standard experience + +### **PRO Users ($5-10/month):** +- ✅ **Ad-Free Interface** - No ads anywhere +- ✅ **Backend Proxy** - CORS bypass for any API +- ✅ **Saved Work** - Cloud storage for projects +- ✅ **Shareable Links** - Share work with team +- ✅ **Advanced Features** - Custom HTTP methods, headers, auth +- ✅ **Priority Support** - Email support +- ✅ **Export Templates** - Save and reuse configurations + +--- + +## Implementation Plan + +### **Phase 1: Basic AdSense Setup (Week 1)** +- [ ] Apply for Google AdSense account +- [ ] Get approval (usually 1-2 weeks) +- [ ] Create ad units in AdSense dashboard +- [ ] Get ad unit codes + +### **Phase 2: Homepage Integration (Week 2)** +- [ ] Create `AdSense` component +- [ ] Add Leaderboard ad above tool cards +- [ ] Add Medium Rectangle between sections +- [ ] Test responsive behavior +- [ ] Verify ad display and tracking + +### **Phase 3: Tool Pages Integration (Week 3)** +- [ ] Add sidebar ad component +- [ ] Add responsive ads between sections +- [ ] Implement mobile anchor ads +- [ ] Test on all tools +- [ ] Optimize placement based on CTR + +### **Phase 4: PRO Feature Integration (Week 4)** +- [ ] Create PRO user detection system +- [ ] Hide ads for PRO users +- [ ] Add "Remove Ads" upgrade prompt +- [ ] Implement payment system (Stripe) +- [ ] Test PRO vs FREE experience + +--- + +## Technical Implementation + +### **AdSense Component** + +```javascript +// src/components/AdSense.js +import React, { useEffect } from 'react'; +import { getCurrentUserTier, USER_TIER } from '../config/features'; + +const AdSense = ({ + slot, + format = 'auto', + responsive = true, + style = {} +}) => { + const userTier = getCurrentUserTier(); + + // Don't show ads for PRO users + if (userTier === USER_TIER.PRO) { + return null; + } + + useEffect(() => { + try { + (window.adsbygoogle = window.adsbygoogle || []).push({}); + } catch (e) { + console.error('AdSense error:', e); + } + }, []); + + return ( +
+ +
+ ); +}; + +export default AdSense; +``` + +### **Usage Example** + +```javascript +// In TableEditor.js +import AdSense from '../components/AdSense'; + +// Between sections + + +// Sidebar + +``` + +### **Add Script to index.html** + +```html + + + + + +``` + +--- + +## Revenue Estimation + +### **Traffic Assumptions:** +- 1,000 daily visitors +- 3 page views per visitor = 3,000 page views/day +- 90,000 page views/month + +### **AdSense Metrics:** +- Average CPM: $2-5 (developer tools niche) +- Average CTR: 1-2% +- Average CPC: $0.50-2.00 + +### **Monthly Revenue Estimate:** + +**Conservative (Low End):** +- 90,000 page views × $2 CPM = $180/month +- Or: 90,000 × 1% CTR × $0.50 CPC = $450/month + +**Optimistic (High End):** +- 90,000 page views × $5 CPM = $450/month +- Or: 90,000 × 2% CTR × $2.00 CPC = $3,600/month + +**Realistic Target:** $300-800/month with optimization + +--- + +## Best Practices + +### **Do's:** +✅ Place ads in natural content breaks +✅ Use responsive ad units +✅ Test different placements and track CTR +✅ Maintain good content-to-ad ratio +✅ Respect user experience +✅ Offer ad-free PRO option + +### **Don'ts:** +❌ Place ads in middle of forms or editors +❌ Use too many ads per page +❌ Hide ads with CSS (against policy) +❌ Click own ads (instant ban) +❌ Encourage clicks ("Click here!") +❌ Place ads too close together + +--- + +## Monitoring & Optimization + +### **Key Metrics to Track:** +1. **Page RPM** (Revenue per 1000 impressions) +2. **CTR** (Click-through rate) +3. **CPC** (Cost per click) +4. **Viewability** (% of ads actually seen) +5. **User Engagement** (bounce rate, time on site) + +### **A/B Testing:** +- Test different ad positions +- Test ad sizes and formats +- Monitor which tools generate most revenue +- Optimize based on data + +### **Monthly Review:** +- Analyze AdSense reports +- Identify top-performing placements +- Remove low-performing ads +- Test new positions + +--- + +## Compliance & Policy + +### **Google AdSense Policies:** +- No invalid clicks or impressions +- No prohibited content +- Proper ad placement (not deceptive) +- Privacy policy must mention ads +- Cookie consent for EU users (already implemented) + +### **Privacy Policy Update:** +```markdown +## Advertising + +We use Google AdSense to display advertisements on our website. +Google AdSense uses cookies to serve ads based on your prior visits +to our website or other websites. You may opt out of personalized +advertising by visiting Google's Ads Settings. + +Third-party vendors, including Google, use cookies to serve ads +based on a user's prior visits to our website. Users may opt out +of Google's use of cookies by visiting the Google advertising +opt-out page. +``` + +--- + +## Summary + +### **Immediate Actions:** +1. ✅ Hide Advanced Options (Done) +2. 📝 Apply for Google AdSense +3. 📝 Create AdSense component +4. 📝 Implement homepage ads first +5. 📝 Test and optimize + +### **Future Enhancements:** +- PRO subscription system +- Backend proxy for CORS +- Saved work and templates +- Team collaboration features +- Analytics dashboard + +**Goal:** Generate $500-1000/month from ads while maintaining excellent UX, then offer PRO tier for ad-free experience + premium features. diff --git a/BACKEND_REQUIREMENTS.md b/BACKEND_REQUIREMENTS.md new file mode 100644 index 00000000..bea247f7 --- /dev/null +++ b/BACKEND_REQUIREMENTS.md @@ -0,0 +1,331 @@ +# Backend Requirements for Production + +## Question 2: Does Advanced URL Fetch Need Backend? + +### Short Answer: +**YES, for production use with CORS-protected APIs, you need a backend proxy.** + +### Long Answer: + +## Current Situation (Frontend Only) + +### ✅ What Works Without Backend: +1. **Public APIs with CORS enabled** + - JSONPlaceholder + - GitHub API (public endpoints) + - Any API with `Access-Control-Allow-Origin: *` + +2. **Same-origin requests** + - Your own domain's API + - Example: `dewe.dev/api/*` + +### ❌ What Doesn't Work Without Backend: +1. **CORS-protected APIs** + - Your `api.starsender.online` + - Most private/commercial APIs + - APIs without CORS headers + +2. **Secure API keys** + - Exposing keys in frontend = security risk + - Anyone can see your API keys in browser + +--- + +## Why You Need Backend + +### 1. CORS Bypass +``` +❌ Frontend → api.starsender.online + Browser blocks: CORS error + +✅ Frontend → Your Backend → api.starsender.online + No CORS (server-to-server) +``` + +### 2. API Key Security +``` +❌ Frontend stores API key + Visible in browser console + Anyone can steal it + +✅ Backend stores API key + Hidden from users + Secure environment variables +``` + +### 3. Rate Limiting & Caching +``` +✅ Backend can: + - Cache responses + - Implement rate limiting + - Log requests + - Add analytics +``` + +--- + +## Backend Architecture Options + +### Option 1: Simple Proxy (Recommended) + +**Tech Stack:** Node.js + Express + +```javascript +// server.js +const express = require('express'); +const axios = require('axios'); +const cors = require('cors'); + +const app = express(); +app.use(cors()); +app.use(express.json()); + +// Proxy endpoint +app.post('/api/proxy', async (req, res) => { + try { + const { url, method, headers, body } = req.body; + + // Make request to target API + const response = await axios({ + method: method || 'GET', + url: url, + headers: headers || {}, + data: body || undefined + }); + + res.json(response.data); + } catch (error) { + res.status(error.response?.status || 500).json({ + error: error.message, + details: error.response?.data + }); + } +}); + +app.listen(3000, () => { + console.log('Proxy server running on port 3000'); +}); +``` + +**Frontend Update:** +```javascript +// In handleFetchData function +const response = await fetch('https://your-backend.com/api/proxy', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + url: url, + method: advancedOptions?.method || 'GET', + headers: advancedOptions?.headers || {}, + body: advancedOptions?.body + }) +}); +``` + +--- + +### Option 2: Serverless Functions + +**Platform:** Vercel, Netlify, AWS Lambda + +```javascript +// api/proxy.js (Vercel/Netlify) +export default async function handler(req, res) { + if (req.method !== 'POST') { + return res.status(405).json({ error: 'Method not allowed' }); + } + + const { url, method, headers, body } = req.body; + + try { + const response = await fetch(url, { + method: method || 'GET', + headers: headers || {}, + body: body ? JSON.stringify(body) : undefined + }); + + const data = await response.json(); + res.status(200).json(data); + } catch (error) { + res.status(500).json({ error: error.message }); + } +} +``` + +--- + +### Option 3: Full Backend with Auth + +**For PRO user management:** + +```javascript +// server.js with authentication +const express = require('express'); +const jwt = require('jsonwebtoken'); +const axios = require('axios'); + +const app = express(); +app.use(express.json()); + +// Middleware to check PRO status +const checkProUser = (req, res, next) => { + const token = req.headers.authorization?.split(' ')[1]; + + try { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + req.user = decoded; + + // Check if user is PRO + if (req.user.tier !== 'pro') { + return res.status(403).json({ + error: 'PRO feature', + message: 'Upgrade to PRO to use advanced URL fetch' + }); + } + + next(); + } catch (error) { + res.status(401).json({ error: 'Unauthorized' }); + } +}; + +// Protected proxy endpoint +app.post('/api/proxy', checkProUser, async (req, res) => { + const { url, method, headers, body } = req.body; + + // Only PRO users can use non-GET methods + if (method !== 'GET' && req.user.tier !== 'pro') { + return res.status(403).json({ + error: 'PRO feature required for ' + method + }); + } + + try { + const response = await axios({ + method: method || 'GET', + url: url, + headers: headers || {}, + data: body || undefined + }); + + res.json(response.data); + } catch (error) { + res.status(error.response?.status || 500).json({ + error: error.message + }); + } +}); + +app.listen(3000); +``` + +--- + +## Implementation Roadmap + +### Phase 1: Basic Proxy (Week 1) +- [ ] Set up Node.js/Express server +- [ ] Create `/api/proxy` endpoint +- [ ] Deploy to Vercel/Netlify +- [ ] Update frontend to use proxy +- [ ] Test with your API + +### Phase 2: Security (Week 2) +- [ ] Add API key validation +- [ ] Implement rate limiting +- [ ] Add request logging +- [ ] Set up error handling +- [ ] Add CORS whitelist + +### Phase 3: PRO Features (Week 3-4) +- [ ] Set up user authentication (JWT) +- [ ] Create user database (PostgreSQL/MongoDB) +- [ ] Implement tier checking (FREE/PRO) +- [ ] Add payment integration (Stripe) +- [ ] Update frontend to send auth tokens + +### Phase 4: Advanced Features (Week 5+) +- [ ] Request caching (Redis) +- [ ] Analytics dashboard +- [ ] Usage limits per tier +- [ ] Webhook support +- [ ] API key management + +--- + +## Cost Estimation + +### Free Tier Options: +- **Vercel**: 100GB bandwidth/month +- **Netlify**: 100GB bandwidth/month +- **Railway**: $5/month credit +- **Render**: Free tier available + +### Paid Options: +- **Vercel Pro**: $20/month +- **AWS Lambda**: Pay per request (~$0.20 per 1M requests) +- **DigitalOcean**: $5/month VPS +- **Heroku**: $7/month + +--- + +## Security Best Practices + +### 1. Environment Variables +```bash +# .env +JWT_SECRET=your-secret-key +DATABASE_URL=postgresql://... +ALLOWED_ORIGINS=https://dewe.dev,http://localhost:3001 +``` + +### 2. Rate Limiting +```javascript +const rateLimit = require('express-rate-limit'); + +const limiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100 // limit each IP to 100 requests per windowMs +}); + +app.use('/api/', limiter); +``` + +### 3. Input Validation +```javascript +const { body, validationResult } = require('express-validator'); + +app.post('/api/proxy', [ + body('url').isURL(), + body('method').isIn(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']), +], async (req, res) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + // ... rest of code +}); +``` + +--- + +## Summary + +### Current State (Frontend Only): +✅ Works with public APIs +❌ Fails with CORS-protected APIs +❌ Can't secure API keys +❌ No PRO user management + +### With Backend: +✅ Works with any API (no CORS issues) +✅ Secure API key storage +✅ PRO user authentication +✅ Rate limiting & caching +✅ Analytics & logging +✅ Production-ready + +### Recommendation: +**Start with Option 1 (Simple Proxy)** for immediate CORS bypass, then gradually add authentication and PRO features in Phase 2-3. + +**Estimated Timeline:** 2-4 weeks for full implementation with PRO features. diff --git a/DOCUMENTATION_INDEX.md b/DOCUMENTATION_INDEX.md new file mode 100644 index 00000000..dd92668f --- /dev/null +++ b/DOCUMENTATION_INDEX.md @@ -0,0 +1,245 @@ +# Documentation Index + +**Last Updated:** October 22, 2025 + +This document provides an overview of all project documentation and their purposes. + +--- + +## 📚 Core Documentation + +### **PROJECT_ROADMAP.md** 🎯 +**Purpose:** High-level project vision, roadmap, and strategic planning +**Audience:** Project leads, stakeholders +**Contains:** +- Vision and goals +- Current status (8 active tools) +- Completed features (Markdown Editor, SEO, tool consolidation) +- Future phases (Diagram Tool, PRO tier, monetization) +- Success metrics and growth strategy + +**Status:** ✅ Updated (Oct 22, 2025) + +--- + +### **TODO.md** ✅ +**Purpose:** Detailed task list with checkboxes for tracking progress +**Audience:** Developers, project managers +**Contains:** +- Phase 1: Foundation & Monetization (✅ Mostly complete) +- Phase 2: Content Expansion (✅ Markdown Editor done) +- Phase 3: Monetization Backend (Planned) +- Quick wins and metrics to track + +**Status:** ✅ Updated (Oct 22, 2025) + +--- + +## 🛠️ Technical Guides + +### **EDITOR_TOOL_GUIDE.md** 📖 +**Purpose:** Comprehensive guide for building new editor tools +**Audience:** Developers +**Contains:** +- Consistent UX patterns +- Input methods (Create/URL/Paste/Open) +- Data loss prevention +- Export patterns +- Code examples + +**Status:** ✅ Active reference + +--- + +### **EDITOR_CHECKLIST.md** ☑️ +**Purpose:** Quality checklist for new tools +**Audience:** Developers, QA +**Contains:** +- Feature completeness checklist +- UX consistency checks +- Testing requirements +- Documentation requirements + +**Status:** ✅ Active reference + +--- + +### **FEATURE_TOGGLE_GUIDE.md** 🎛️ +**Purpose:** Guide for implementing feature toggles +**Audience:** Developers +**Contains:** +- Feature flag patterns +- PRO tier features +- A/B testing setup +- Configuration management + +**Status:** ✅ Active reference + +--- + +## 💰 Monetization Documentation + +### **ADSENSE_REVISED_STRATEGY.md** 📊 +**Purpose:** Current AdSense implementation strategy +**Audience:** Project leads, developers +**Contains:** +- Clean homepage strategy (no ads) +- Tool pages monetization (3 desktop ads, 1 mobile) +- Revenue projections +- Implementation details +- **This is the ACTIVE strategy** + +**Status:** ✅ Current strategy + +--- + +### **ADSENSE_SETUP_GUIDE.md** 🔧 +**Purpose:** Step-by-step AdSense setup instructions +**Audience:** Developers, admins +**Contains:** +- Account setup steps +- Ad unit creation +- Code implementation +- Testing procedures + +**Status:** ✅ Active guide + +--- + +### **ADSENSE_STRATEGY.md** 📝 +**Purpose:** Original AdSense strategy (with homepage ads) +**Audience:** Reference only +**Contains:** +- Alternative strategy with homepage ads +- Comparison with revised strategy +- **NOT the current strategy** + +**Status:** ⚠️ Reference only (superseded by REVISED) + +--- + +### **BACKEND_REQUIREMENTS.md** 🖥️ +**Purpose:** Backend requirements for PRO tier +**Audience:** Backend developers +**Contains:** +- Authentication system +- Payment integration +- CORS proxy service +- Database schema +- API endpoints + +**Status:** 📅 Future reference (Phase 3) + +--- + +## 🔍 SEO Documentation + +### **SEO_IMPROVEMENT_PLAN.md** 🚀 +**Purpose:** Comprehensive SEO strategy and implementation guide +**Audience:** Developers, marketers +**Contains:** +- Priority 1: Critical improvements (✅ DONE) + - Sitemap updates + - FAQ schema + - Breadcrumb schema + - Internal linking +- Priority 2-6: Ongoing improvements +- Long-term strategy +- Expected results + +**Status:** ✅ Partially complete (Priority 1 done) + +--- + +## 📖 User Documentation + +### **README.md** 📄 +**Purpose:** Project overview and setup instructions +**Audience:** Developers, contributors +**Contains:** +- Project description +- Installation instructions +- Development setup +- Deployment guide + +**Status:** ✅ Active + +--- + +## 🗑️ Removed Documentation + +The following documents were **removed** as they were redundant or completed: + +- ❌ `MARKDOWN_EDITOR_TASKS.md` - Merged into TODO.md +- ❌ `MARKDOWN_EDITOR_PLAN.md` - Merged into PROJECT_ROADMAP.md +- ❌ `MARKDOWN_EDITOR_ANALYSIS.md` - No longer needed (completed) +- ❌ `NEXT_TASK_RECOMMENDATION.md` - Outdated (Markdown Editor done) +- ❌ `SEO_FIX_GUIDE.md` - Merged into SEO_IMPROVEMENT_PLAN.md +- ❌ `SEO_QUICK_WINS.md` - Merged into SEO_IMPROVEMENT_PLAN.md +- ❌ `ADVANCED_URL_FETCH_FIXES.md` - Completed, no longer needed +- ❌ `CORS_AND_IMPROVEMENTS.md` - Completed, no longer needed + +--- + +## 🎯 Quick Reference + +### **What to Read First:** +1. **PROJECT_ROADMAP.md** - Understand the vision +2. **TODO.md** - See what's next +3. **EDITOR_TOOL_GUIDE.md** - Learn the patterns + +### **Building a New Tool:** +1. Read **EDITOR_TOOL_GUIDE.md** +2. Follow **EDITOR_CHECKLIST.md** +3. Update **TODO.md** when done + +### **Implementing AdSense:** +1. Read **ADSENSE_REVISED_STRATEGY.md** (current strategy) +2. Follow **ADSENSE_SETUP_GUIDE.md** +3. Ignore **ADSENSE_STRATEGY.md** (old strategy) + +### **SEO Improvements:** +1. Check **SEO_IMPROVEMENT_PLAN.md** +2. Priority 1 is ✅ DONE +3. Work on Priority 2-6 as needed + +--- + +## 📊 Current Project Status + +### ✅ Completed (October 22, 2025): +- **8 Active Tools** (Markdown Editor, Object Editor, Table Editor, Invoice Editor, URL/Base64/Beautifier/Diff/Text Length) +- **Tool Consolidation** (Merged JSON, Serialize, CSV-JSON into main editors) +- **SEO Optimization** (FAQ schema, breadcrumbs, internal linking, sitemap) +- **Related Tools** (Recommendations on each tool page) +- **Custom 404 Page** (With tool suggestions) +- **Ad Infrastructure** (Placeholder ads ready) + +### ⏳ In Progress: +- **AdSense Approval** (Awaiting Google review) + +### 📅 Next Up: +- **Diagram Tool** (After AdSense approval) +- **PRO Tier** (Backend, auth, payment) +- **More Small Tools** (Hash, UUID, Timestamp, Color, etc.) + +--- + +## 🔄 Document Maintenance + +### When to Update: +- **PROJECT_ROADMAP.md**: When completing major phases or changing strategy +- **TODO.md**: Mark tasks as done, add new tasks +- **SEO_IMPROVEMENT_PLAN.md**: After implementing SEO improvements +- **ADSENSE_REVISED_STRATEGY.md**: When changing ad strategy or getting new data + +### Archive Policy: +- Completed task-specific docs → Delete +- Outdated strategies → Keep for reference, mark as "Reference Only" +- Active guides → Keep updated + +--- + +**Single Source of Truth:** PROJECT_ROADMAP.md + TODO.md +**Everything else:** Supporting documentation + diff --git a/FEATURE_TOGGLE_GUIDE.md b/FEATURE_TOGGLE_GUIDE.md new file mode 100644 index 00000000..520c9289 --- /dev/null +++ b/FEATURE_TOGGLE_GUIDE.md @@ -0,0 +1,198 @@ +# Feature Toggle System - FREE vs PRO + +## Overview +The Advanced URL Fetch feature is now a **PRO feature** with a toggle system that supports FREE and PRO tiers. + +## Files Created + +### 1. `/src/config/features.js` +**Purpose:** Central configuration for all FREE/PRO features + +**Key Functions:** +- `getCurrentUserTier()` - Returns current user tier (static for now, will be dynamic) +- `isFeatureEnabled(featureName)` - Check if a feature is enabled for current user +- `isProUser()` - Quick check if user is PRO +- `getFeatureInfo(featureName)` - Get feature metadata + +**Current Features:** +- `ADVANCED_URL_FETCH` - PRO only +- `BULK_OPERATIONS` - PRO only (placeholder) +- `EXPORT_TEMPLATES` - PRO only (placeholder) +- `CLOUD_SYNC` - PRO only (placeholder) + +**How to Toggle for Testing:** +```javascript +// In /src/config/features.js, line ~15 +const staticTier = USER_TIER.FREE; // Change to USER_TIER.PRO to test +``` + +### 2. `/src/components/ProBadge.js` +**Purpose:** Reusable Pro badge and feature lock components + +**Components:** +- `` - Shows PRO badge (3 variants: badge, button, inline) +- `` - Shows locked feature message with upgrade prompt + +**Usage Examples:** +```jsx +// Simple badge + + +// Upgrade button + + +// Inline text + + +// Feature lock message + +``` + +### 3. `/src/components/AdvancedURLFetch.js` (Updated) +**Purpose:** URL fetch component with FREE/PRO support + +**Changes:** +- Imports feature toggle system +- Shows PRO badge on "Show Advanced Options" button +- Displays `` when user is FREE tier +- Shows full advanced options when user is PRO tier + +## User Experience + +### FREE Tier Users: +1. See basic URL input with GET method only +2. See "Show Advanced Options" button with PRO badge +3. Click button → See feature lock message with upgrade prompt +4. Can still use basic URL fetch (current functionality) + +### PRO Tier Users: +1. See basic URL input with method selector (GET/POST/PUT/DELETE/PATCH) +2. See "Show Advanced Options" button (no PRO badge) +3. Click button → See full advanced options: + - Query Parameters builder + - Custom Headers + - Authentication (Bearer, API Key, Basic Auth) + - Request Body editor + - Save/Load Presets + +## Integration Guide + +### In ObjectEditor or TableEditor: + +```jsx +import AdvancedURLFetch from '../components/AdvancedURLFetch'; + +// In component: +const [showAdvanced, setShowAdvanced] = useState(false); + +const handleUpgrade = () => { + // Navigate to pricing page or show upgrade modal + alert('Upgrade to PRO!'); +}; + +// In JSX: + setShowAdvanced(!showAdvanced)} + onUpgrade={handleUpgrade} +/> +``` + +## Future: Dynamic Tier from Database + +When implementing authentication and database: + +```javascript +// /src/config/features.js +export const getCurrentUserTier = () => { + // Replace static tier with: + const user = getUserFromAuth(); // Your auth function + return user?.tier || USER_TIER.FREE; +}; + +// Or with API call: +export const getCurrentUserTier = async () => { + const response = await fetch('/api/user/tier'); + const data = await response.json(); + return data.tier || USER_TIER.FREE; +}; +``` + +## Adding New PRO Features + +1. **Add to features.js:** +```javascript +export const FEATURES = { + // ... existing features + + MY_NEW_FEATURE: { + name: 'My New Feature', + description: 'Description of what it does', + tier: USER_TIER.PRO, + enabled: (userTier) => userTier === USER_TIER.PRO + } +}; +``` + +2. **Use in component:** +```jsx +import { isFeatureEnabled } from '../config/features'; + +const MyComponent = () => { + const isEnabled = isFeatureEnabled('MY_NEW_FEATURE'); + + return ( +
+ {isEnabled ? ( + + ) : ( + + )} +
+ ); +}; +``` + +## Testing + +### Test as FREE user: +1. Keep `staticTier = USER_TIER.FREE` in features.js +2. Run dev server: `npm start` +3. Go to Object Editor → URL tab +4. Click "Show Advanced Options" +5. Should see PRO lock message + +### Test as PRO user: +1. Change to `staticTier = USER_TIER.PRO` in features.js +2. Restart dev server +3. Go to Object Editor → URL tab +4. Click "Show Advanced Options" +5. Should see full advanced options + +## Benefits + +✅ **Clean Separation**: FREE and PRO features clearly separated +✅ **Easy Testing**: Toggle tier with one line change +✅ **Reusable Components**: ProBadge and ProFeatureLock can be used anywhere +✅ **Future-Ready**: Easy to connect to real authentication/database +✅ **User-Friendly**: Clear upgrade prompts with feature descriptions +✅ **Maintainable**: All feature flags in one central location + +## Next Steps + +1. ✅ Feature toggle system created +2. ✅ Pro badge components created +3. ✅ AdvancedURLFetch updated with FREE/PRO support +4. ⏳ Integrate into ObjectEditor +5. ⏳ Integrate into TableEditor +6. ⏳ Create pricing/upgrade page +7. ⏳ Implement authentication system +8. ⏳ Connect to database for dynamic tier management diff --git a/PROJECT_ROADMAP.md b/PROJECT_ROADMAP.md index 55919cb2..dd873534 100644 --- a/PROJECT_ROADMAP.md +++ b/PROJECT_ROADMAP.md @@ -1,6 +1,6 @@ # Developer Tools - Project Roadmap -**Last Updated:** October 14, 2025 +**Last Updated:** October 22, 2025 --- @@ -16,10 +16,16 @@ Build a comprehensive suite of developer tools with a focus on: ## 📊 Current Status -### ✅ Completed Tools -- **Object Editor** - JSON/PHP serialized data editor -- **Table Editor** - Tabular data editor with multi-format support +### ✅ Completed Tools (8 Active Tools) +- **Markdown Editor** - Write & preview markdown with live rendering ✨ NEW +- **Object Editor** - JSON/PHP serialized data editor (merged JSON & Serialize tools) +- **Table Editor** - Tabular data editor with multi-format support (merged CSV-JSON) - **Invoice Editor** - Professional invoice generator +- **URL Encoder/Decoder** - Encode/decode URLs +- **Base64 Encoder/Decoder** - Base64 conversion +- **Code Beautifier** - Format & minify code +- **Diff Tool** - Compare text differences +- **Text Length Checker** - Text statistics ### ✅ Completed Infrastructure - Consistent input patterns (Create/URL/Paste/Open) @@ -27,6 +33,9 @@ Build a comprehensive suite of developer tools with a focus on: - Data loss prevention (confirmation modals) - Dark mode support - Responsive design +- SEO optimization (FAQ schema, breadcrumbs, internal linking) +- Related tools recommendations +- Custom 404 page - Documentation (EDITOR_TOOL_GUIDE.md, EDITOR_CHECKLIST.md) --- @@ -36,7 +45,7 @@ Build a comprehensive suite of developer tools with a focus on: ### Phase 1: Foundation & Monetization (Current - Week 1-2) #### Priority 1: Advanced URL Fetch ⭐ -**Status:** Planned +**Status:** ✅ Completed (Hidden for PRO tier) **Timeline:** 1-2 days **Impact:** HIGH - Benefits all existing and future tools @@ -68,7 +77,7 @@ Build a comprehensive suite of developer tools with a focus on: --- #### Priority 2: Ad Space Preparation 💰 -**Status:** Planned +**Status:** ✅ Completed (Placeholder ads ready) **Timeline:** 1 day **Impact:** HIGH - Start monetization immediately @@ -100,9 +109,9 @@ Build a comprehensive suite of developer tools with a focus on: **Specifications:** - **Desktop:** - 300px fixed width right column - - Sticky scroll (ads stay visible) + - Fixed positioning (ads stay visible) - 3 ad blocks maximum - - Ad sizes: 300x250, 300x600 + - Ad sizes: All 300x250 (Medium Rectangle) - Google AdSense policy compliant - Hide below 1200px viewport width - Main content: `calc(100% - 320px)` @@ -123,7 +132,7 @@ Build a comprehensive suite of developer tools with a focus on: --- #### Priority 3: AdSense Integration 💵 -**Status:** Planned +**Status:** ⏳ In Progress (Awaiting approval) **Timeline:** 1 day **Impact:** HIGH - Start earning revenue @@ -138,7 +147,7 @@ Build a comprehensive suite of developer tools with a focus on: **Ad Units Needed:** - Desktop Sidebar 1 (300x250) - Desktop Sidebar 2 (300x250) -- Desktop Sidebar 3 (300x600) +- Desktop Sidebar 3 (300x250) - Mobile Bottom Banner (320x50) **Compliance:** @@ -152,7 +161,7 @@ Build a comprehensive suite of developer tools with a focus on: ### Phase 2: Content Expansion (Week 3-6) #### Markdown Editor 📝 -**Status:** Planned +**Status:** ✅ Completed (October 22, 2025) **Timeline:** 1-2 weeks **Impact:** HIGH - Major new feature, attracts new users diff --git a/SEO_FIX_GUIDE.md b/SEO_FIX_GUIDE.md deleted file mode 100644 index c00927c1..00000000 --- a/SEO_FIX_GUIDE.md +++ /dev/null @@ -1,412 +0,0 @@ -# SEO Fix Guide - Google Search Console Indexing - -**Date:** October 15, 2025 -**Issue:** Google Search Console only indexing homepage, not tool pages -**Status:** FIXED ✅ - ---- - -## 🔍 Problems Identified - -### 1. **Outdated Sitemap** -- Missing Invoice Editor (`/invoice-editor`) -- Missing What's New page (`/whats-new`) -- Old lastmod dates (2025-01-23) -- Wrong priorities - -### 2. **React SPA Issue** (CRITICAL) -- Google can't index JavaScript-rendered pages -- Tool pages have no HTML content for crawlers -- All content loads client-side via React Router -- Search engines see empty `
` - -### 3. **Missing Meta Tags** -- No dynamic meta tags per page -- No Open Graph tags -- No Twitter Card tags -- No structured data (JSON-LD) - ---- - -## ✅ Solutions Implemented - -### 1. **Updated Sitemap.xml** -**File:** `/public/sitemap.xml` - -**Changes:** -- ✅ Added Invoice Editor -- ✅ Added What's New page -- ✅ Updated all lastmod dates to 2025-10-15 -- ✅ Increased editor tools priority to 0.9 -- ✅ Added comments for better organization -- ✅ Proper priority hierarchy - -### 2. **Pre-rendering with react-snap** -**File:** `package.json` - -**Added:** -```json -{ - "dependencies": { - "react-snap": "^1.23.0" - }, - "scripts": { - "build": "react-scripts build && react-snap" - }, - "reactSnap": { - "include": [ - "/", - "/object-editor", - "/table-editor", - "/invoice-editor", - "/url", - "/base64", - "/beautifier", - "/diff", - "/text-length", - "/whats-new", - "/privacy", - "/terms" - ] - } -} -``` - -**What it does:** -- Generates static HTML for each route -- Crawlers see full HTML content -- Improves SEO dramatically -- Faster first paint - -### 3. **Dynamic Meta Tags with react-helmet-async** -**Files Created:** -- `/src/components/SEO.js` - Reusable SEO component -- Updated `/src/App.js` - Wrapped with HelmetProvider -- Updated `/src/pages/Home.js` - Added SEO component - -**Features:** -- Dynamic title per page -- Dynamic description per page -- Open Graph tags (Facebook) -- Twitter Card tags -- JSON-LD structured data -- Canonical URLs - ---- - -## 📋 Steps to Fix in Google Search Console - -### Step 1: Verify Sitemap Update - -1. **Go to Google Search Console** - - URL: https://search.google.com/search-console - - Select property: `dewe.dev` - -2. **Navigate to Sitemaps** - - Left sidebar → "Sitemaps" - -3. **Remove Old Sitemap** (if exists) - - Find `https://dewe.dev/sitemap.xml` - - Click the 3 dots → "Remove sitemap" - -4. **Submit New Sitemap** - - Click "Add a new sitemap" - - Enter: `sitemap.xml` - - Click "Submit" - -5. **Wait for Processing** - - Status will show "Couldn't fetch" initially - - After deployment, it will show "Success" - - Check back in 24-48 hours - ---- - -### Step 2: Request Indexing for Key Pages - -1. **Go to URL Inspection Tool** - - Top search bar in Google Search Console - -2. **Inspect Each Tool Page:** - ``` - https://dewe.dev/object-editor - https://dewe.dev/table-editor - https://dewe.dev/invoice-editor - https://dewe.dev/url - https://dewe.dev/base64 - https://dewe.dev/beautifier - https://dewe.dev/diff - https://dewe.dev/text-length - https://dewe.dev/whats-new - ``` - -3. **For Each URL:** - - Paste URL in search bar - - Click "Test Live URL" - - Wait for test to complete - - If "URL is on Google": Great! - - If "URL is not on Google": Click "Request Indexing" - - Repeat for all pages - ---- - -### Step 3: Check robots.txt - -1. **Go to Settings** - - Left sidebar → "Settings" - - Click "Open report" under "robots.txt" - -2. **Verify robots.txt is accessible** - - Should show your robots.txt content - - Should reference sitemap: `Sitemap: https://dewe.dev/sitemap.xml` - -3. **If not accessible:** - - Check if `https://dewe.dev/robots.txt` works in browser - - Ensure Coolify/server serves static files correctly - ---- - -### Step 4: Monitor Coverage - -1. **Go to Coverage Report** - - Left sidebar → "Coverage" (or "Pages") - -2. **Check Indexed Pages** - - Should see increase in "Valid" pages - - Monitor "Excluded" and "Error" sections - -3. **Common Issues:** - - **"Discovered - currently not indexed"**: Normal, Google will index soon - - **"Crawled - currently not indexed"**: Low priority, may take time - - **"Excluded by 'noindex' tag"**: Check meta tags (shouldn't happen) - - **"Soft 404"**: Page has no content (pre-rendering should fix this) - ---- - -### Step 5: Check Enhancements - -1. **Go to Enhancements** - - Left sidebar → "Enhancements" - -2. **Check Mobile Usability** - - Should show "Valid" for all pages - - Fix any mobile issues - -3. **Check Core Web Vitals** - - Monitor performance metrics - - Aim for "Good" status - ---- - -## 🚀 Deployment Steps - -### 1. Install Dependencies -```bash -cd /Users/dwindown/CascadeProjects/developer-tools -npm install -``` - -### 2. Test Build Locally -```bash -npm run build -``` - -**Expected:** -- Build completes successfully -- react-snap generates HTML files for each route -- Check `build/` folder for HTML files - -### 3. Deploy to Production -```bash -git add -A -git commit -m "fix: improve SEO with pre-rendering and dynamic meta tags - -- Updated sitemap.xml with all current pages -- Added react-snap for static HTML generation -- Implemented react-helmet-async for dynamic meta tags -- Created SEO component with Open Graph and Twitter Cards -- Added JSON-LD structured data -- Fixed Google Search Console indexing issues" - -git push -``` - -### 4. Verify Deployment -- Wait for Coolify to deploy -- Check https://dewe.dev/sitemap.xml -- Check https://dewe.dev/robots.txt -- Check https://dewe.dev/object-editor (view source, should see HTML content) - ---- - -## 🧪 Testing & Verification - -### Test 1: View Page Source -1. Open https://dewe.dev/object-editor -2. Right-click → "View Page Source" -3. **Before fix:** Only see `
` -4. **After fix:** See full HTML content with meta tags - -### Test 2: Google Rich Results Test -1. Go to https://search.google.com/test/rich-results -2. Enter: `https://dewe.dev/object-editor` -3. Should show structured data (JSON-LD) -4. Should pass validation - -### Test 3: Facebook Sharing Debugger -1. Go to https://developers.facebook.com/tools/debug/ -2. Enter: `https://dewe.dev/object-editor` -3. Should show Open Graph tags -4. Should display preview image - -### Test 4: Twitter Card Validator -1. Go to https://cards-dev.twitter.com/validator -2. Enter: `https://dewe.dev/object-editor` -3. Should show Twitter Card preview -4. Should display correctly - ---- - -## 📊 Expected Timeline - -| Action | Timeline | -|--------|----------| -| Deploy changes | Immediate | -| Sitemap processed | 1-2 hours | -| Pages crawled | 1-7 days | -| Pages indexed | 3-14 days | -| Full coverage | 2-4 weeks | - -**Note:** Google indexing is not instant. Be patient! - ---- - -## 🔧 Troubleshooting - -### Issue: "Couldn't fetch sitemap" -**Solution:** -- Check if `https://dewe.dev/sitemap.xml` is accessible -- Ensure Coolify serves static files from `/public` -- Check server logs for 404 errors - -### Issue: "Discovered - currently not indexed" -**Solution:** -- Normal! Google discovered but hasn't indexed yet -- Request indexing manually (Step 2 above) -- Wait 7-14 days - -### Issue: "Crawled - currently not indexed" -**Solution:** -- Google crawled but deemed low priority -- Improve content quality -- Add more internal links -- Wait for Google to re-evaluate - -### Issue: "Soft 404" -**Solution:** -- Page has no content or very little content -- Pre-rendering should fix this -- Check if react-snap generated HTML correctly -- Verify build output - -### Issue: react-snap fails during build -**Solution:** -- Check console for errors -- May need to add `window.snapSaveState = () => ({})` to index.js -- Try `npm run build:no-snap` to build without pre-rendering -- Check react-snap documentation - ---- - -## 📝 Additional Recommendations - -### 1. Add More Content -- Write blog posts about each tool -- Create tutorial pages -- Add FAQ section -- More content = better SEO - -### 2. Internal Linking -- Link between related tools -- Add "Related Tools" section -- Create tool categories pages -- Improve navigation - -### 3. Performance Optimization -- Optimize images -- Minimize JavaScript -- Use CDN for assets -- Improve Core Web Vitals - -### 4. Schema Markup -- Add more structured data -- Use SoftwareApplication schema -- Add BreadcrumbList schema -- Add Organization schema - -### 5. Social Signals -- Share on social media -- Get backlinks -- Engage with developer communities -- Build brand awareness - ---- - -## 🎯 Success Metrics - -### Week 1 -- ✅ Sitemap processed -- ✅ 3-5 pages indexed -- ✅ No crawl errors - -### Week 2 -- ✅ 8-10 pages indexed -- ✅ Appearing in search results -- ✅ Mobile usability: Good - -### Week 4 -- ✅ All pages indexed -- ✅ Ranking for brand keywords -- ✅ Organic traffic increasing - ---- - -## 📞 Support - -If issues persist after 2 weeks: -1. Check Google Search Console for specific errors -2. Review server logs for crawl errors -3. Test with different browsers -4. Consider hiring SEO consultant - ---- - -## ✅ Checklist - -### Immediate Actions -- [ ] Deploy code changes -- [ ] Verify sitemap.xml is accessible -- [ ] Verify robots.txt is accessible -- [ ] Submit sitemap in Google Search Console -- [ ] Request indexing for key pages - -### Within 24 Hours -- [ ] Check sitemap processing status -- [ ] Verify HTML pre-rendering works -- [ ] Test Open Graph tags -- [ ] Test Twitter Cards - -### Within 1 Week -- [ ] Monitor coverage report -- [ ] Check for crawl errors -- [ ] Verify pages being indexed -- [ ] Check search appearance - -### Within 1 Month -- [ ] Review all pages indexed -- [ ] Check ranking positions -- [ ] Monitor organic traffic -- [ ] Optimize based on data - ---- - -**Good luck! Your SEO should improve significantly with these changes.** 🚀 diff --git a/SEO_IMPROVEMENT_PLAN.md b/SEO_IMPROVEMENT_PLAN.md new file mode 100644 index 00000000..7ddbe5c3 --- /dev/null +++ b/SEO_IMPROVEMENT_PLAN.md @@ -0,0 +1,620 @@ +# 🚀 SEO Improvement Plan for Developer Tools + +## Current SEO Status: ✅ Good Foundation + +**What's Already Implemented:** +- ✅ React Helmet for dynamic meta tags +- ✅ Canonical URLs +- ✅ Open Graph tags (Facebook) +- ✅ Twitter Cards +- ✅ JSON-LD structured data +- ✅ robots.txt +- ✅ sitemap.xml +- ✅ Responsive design +- ✅ Fast loading (React SPA) + +--- + +## 🎯 Priority 1: Critical SEO Improvements (High Impact) + +### 1. **Add Missing Tools to Sitemap** + +**Current Issue:** Sitemap is missing several tools: +- ❌ Markdown Editor +- ❌ JSON Tool +- ❌ CSV/JSON Converter +- ❌ Serialize Tool +- ❌ Release Notes page + +**Action:** Update `public/sitemap.xml` + +```xml + + + https://dewe.dev/markdown-editor + 2025-10-22 + monthly + 0.9 + + + https://dewe.dev/json + 2025-10-22 + monthly + 0.8 + + + https://dewe.dev/csv-json + 2025-10-22 + monthly + 0.8 + + + https://dewe.dev/serialize + 2025-10-22 + monthly + 0.8 + + + https://dewe.dev/release-notes + 2025-10-22 + weekly + 0.7 + +``` + +**Impact:** 🔥 High - Google can't index pages it doesn't know about + +--- + +### 2. **Create Blog/Tutorial Section** + +**Why:** Fresh content = better rankings + +**Implementation:** +``` +/blog/ + - how-to-format-json-online + - best-markdown-editor-features + - csv-to-json-conversion-guide + - developer-tools-productivity-tips +``` + +**Benefits:** +- Target long-tail keywords +- Build authority +- Internal linking opportunities +- Regular content updates signal active site + +**Effort:** Medium | **Impact:** 🔥🔥 Very High + +--- + +### 3. **Add FAQ Schema Markup** + +**Current:** Only WebApplication schema +**Add:** FAQPage schema for each tool + +**Example for Markdown Editor:** +```javascript +{ + "@context": "https://schema.org", + "@type": "FAQPage", + "mainEntity": [{ + "@type": "Question", + "name": "Is this markdown editor free?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Yes, completely free. All processing happens in your browser." + } + }, { + "@type": "Question", + "name": "Does the markdown editor support GitHub Flavored Markdown?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Yes, full GFM support including tables, task lists, and syntax highlighting." + } + }] +} +``` + +**Impact:** 🔥🔥 High - Rich snippets in search results + +--- + +### 4. **Implement Breadcrumb Schema** + +**Add to each tool page:** +```javascript +{ + "@context": "https://schema.org", + "@type": "BreadcrumbList", + "itemListElement": [{ + "@type": "ListItem", + "position": 1, + "name": "Home", + "item": "https://dewe.dev" + }, { + "@type": "ListItem", + "position": 2, + "name": "Markdown Editor", + "item": "https://dewe.dev/markdown-editor" + }] +} +``` + +**Impact:** 🔥 Medium-High - Better SERP display + +--- + +### 5. **Add HowTo Schema for Tool Pages** + +**Example:** +```javascript +{ + "@context": "https://schema.org", + "@type": "HowTo", + "name": "How to Convert Markdown to PDF", + "step": [{ + "@type": "HowToStep", + "name": "Write Markdown", + "text": "Type or paste your markdown content" + }, { + "@type": "HowToStep", + "name": "Preview", + "text": "See live preview as you type" + }, { + "@type": "HowToStep", + "name": "Export", + "text": "Click PDF button to download" + }] +} +``` + +**Impact:** 🔥🔥 High - Featured snippets opportunity + +--- + +## 🎯 Priority 2: Content & On-Page SEO (Medium-High Impact) + +### 6. **Optimize Title Tags** + +**Current:** Generic titles +**Improve:** Add power words and benefits + +**Before:** +``` +Markdown Editor | Developer Tools +``` + +**After:** +``` +Free Markdown Editor with Live Preview & PDF Export | Developer Tools +``` + +**Pattern:** +- Include primary keyword +- Add benefit/feature +- Keep under 60 characters +- Use power words: Free, Best, Easy, Fast, Online + +--- + +### 7. **Enhance Meta Descriptions** + +**Current:** Generic descriptions +**Improve:** Action-oriented with CTAs + +**Before:** +``` +Write and preview markdown with live rendering +``` + +**After:** +``` +✓ Free online markdown editor ✓ Live preview ✓ GitHub Flavored Markdown ✓ Export to PDF/HTML ✓ Syntax highlighting. Start writing now - no signup required! +``` + +**Tips:** +- Use checkmarks (✓) for features +- Include CTA +- 150-160 characters +- Front-load keywords + +--- + +### 8. **Add H1 Tags to Tool Pages** + +**Current:** Some pages missing proper H1 +**Fix:** Ensure every page has ONE H1 with primary keyword + +**Example:** +```jsx +

Free Online Markdown Editor with Live Preview

+``` + +--- + +### 9. **Internal Linking Strategy** + +**Create link clusters:** + +**Hub Page:** `/tools` (new page) +- Links to all tools +- Brief description of each +- Categories + +**Tool Pages:** +- Link to related tools +- "You might also like" section +- Footer links to popular tools + +**Example:** +```jsx +// At bottom of Markdown Editor +
+

Related Tools

+ +
+``` + +**Impact:** 🔥🔥 High - Distributes page authority + +--- + +### 10. **Add Alt Text to All Images** + +**Current:** Logo might be missing alt text +**Fix:** Add descriptive alt text + +```jsx +Developer Tools - Free online utilities for web developers +``` + +--- + +## 🎯 Priority 3: Technical SEO (Medium Impact) + +### 11. **Implement Lazy Loading for Images** + +```jsx +Developer Tools +``` + +--- + +### 12. **Add Preconnect for External Resources** + +**Add to `index.html`:** +```html + + +``` + +--- + +### 13. **Create Custom 404 Page** + +**Benefits:** +- Better UX +- Suggest related tools +- Keep users on site +- Internal linking opportunity + +--- + +### 14. **Add Last Modified Dates** + +**Show on each tool page:** +```jsx + +``` + +--- + +### 15. **Implement Service Worker for PWA** + +**Benefits:** +- Offline functionality +- Faster repeat visits +- "Add to Home Screen" +- Google loves PWAs + +--- + +## 🎯 Priority 4: Off-Page SEO & Marketing (High Impact) + +### 16. **Submit to Developer Directories** + +**Submit to:** +- ✅ Product Hunt +- ✅ Hacker News (Show HN) +- ✅ Reddit r/webdev, r/programming +- ✅ Dev.to +- ✅ Hashnode +- ✅ Free Code Camp +- ✅ Stack Overflow (answer questions, link to tools) +- ✅ Indie Hackers +- ✅ BetaList +- ✅ AlternativeTo + +**Impact:** 🔥🔥🔥 Very High - Quality backlinks + +--- + +### 17. **Create GitHub Repository** + +**Benefits:** +- Backlink from GitHub +- Developer credibility +- Open source community +- Star count = social proof + +**Add to footer:** +```jsx + + ⭐ Star on GitHub + +``` + +--- + +### 18. **Guest Posting** + +**Target blogs:** +- CSS-Tricks +- Smashing Magazine +- Dev.to +- Hashnode +- Medium + +**Topics:** +- "10 Essential Developer Tools for 2025" +- "How to Boost Productivity with Online Tools" +- "Privacy-First Developer Tools" + +--- + +### 19. **Create Tool Comparison Pages** + +**Examples:** +- "Best Online JSON Editors Compared" +- "Markdown Editor vs. Notion vs. Typora" +- "Top 10 Free Developer Tools" + +**Include your tools in comparisons** + +--- + +### 20. **Build Email List** + +**Add newsletter signup:** +```jsx +
+

Get Tool Updates

+

New features, tips, and productivity hacks

+ + +
+``` + +**Benefits:** +- Direct traffic +- Engagement signals +- Repeat visitors + +--- + +## 🎯 Priority 5: Performance & Core Web Vitals + +### 21. **Optimize Core Web Vitals** + +**Check current scores:** +```bash +# Use Lighthouse +npm install -g lighthouse +lighthouse https://dewe.dev --view +``` + +**Target:** +- LCP (Largest Contentful Paint): < 2.5s +- FID (First Input Delay): < 100ms +- CLS (Cumulative Layout Shift): < 0.1 + +**Improvements:** +- Code splitting +- Image optimization +- Font optimization +- Minimize JavaScript + +--- + +### 22. **Enable Compression** + +**Add to server config (if using custom server):** +``` +gzip on; +gzip_types text/css application/javascript application/json; +``` + +--- + +### 23. **Implement CDN** + +**Use Cloudflare or similar:** +- Faster global delivery +- DDoS protection +- SSL/TLS +- Caching + +--- + +## 🎯 Priority 6: Local SEO (If Applicable) + +### 24. **Add Organization Schema** + +```javascript +{ + "@context": "https://schema.org", + "@type": "Organization", + "name": "Developer Tools", + "url": "https://dewe.dev", + "logo": "https://dewe.dev/logo.svg", + "sameAs": [ + "https://twitter.com/yourhandle", + "https://github.com/yourhandle" + ] +} +``` + +--- + +## 📊 Measurement & Tracking + +### 25. **Set Up Analytics** + +**Implement:** +- ✅ Google Analytics 4 +- ✅ Google Search Console +- ✅ Bing Webmaster Tools +- ✅ Hotjar (heatmaps) +- ✅ Plausible (privacy-friendly alternative) + +**Track:** +- Organic traffic +- Keyword rankings +- Bounce rate +- Time on page +- Conversion rate (tool usage) + +--- + +### 26. **Monitor Rankings** + +**Tools:** +- Ahrefs +- SEMrush +- Moz +- Google Search Console + +**Track keywords:** +- "online markdown editor" +- "json formatter" +- "csv to json converter" +- "developer tools" +- "code beautifier" + +--- + +## 🎯 Quick Wins (Do First) + +**Can implement today:** + +1. ✅ Update sitemap.xml (add missing tools) +2. ✅ Improve title tags and meta descriptions +3. ✅ Add FAQ schema to 3 main tools +4. ✅ Submit to Product Hunt +5. ✅ Create GitHub repo +6. ✅ Add breadcrumb schema +7. ✅ Optimize images (add alt text) +8. ✅ Set up Google Search Console +9. ✅ Add internal links between tools +10. ✅ Create custom 404 page + +**Estimated time:** 4-6 hours +**Expected impact:** 20-30% traffic increase in 2-3 months + +--- + +## 📈 Long-Term Strategy (3-6 Months) + +**Month 1:** +- Complete all Priority 1 tasks +- Submit to 10 directories +- Write 2 blog posts +- Set up analytics + +**Month 2:** +- Complete Priority 2 tasks +- Write 4 blog posts +- Guest post on 2 sites +- Build 10 quality backlinks + +**Month 3:** +- Complete Priority 3 tasks +- Write 4 blog posts +- Launch newsletter +- Optimize Core Web Vitals + +**Month 4-6:** +- Continue content creation +- Build backlinks +- Optimize based on data +- A/B test landing pages + +--- + +## 🎯 Expected Results + +**After 3 months:** +- 50-100% increase in organic traffic +- Ranking for 20-30 keywords +- 500-1000 daily visitors +- 10-20 quality backlinks + +**After 6 months:** +- 200-300% increase in organic traffic +- Ranking for 50-100 keywords +- 2000-3000 daily visitors +- 50+ quality backlinks +- Featured snippets for 5-10 queries + +--- + +## 🚀 Next Steps + +**Start with:** +1. Update sitemap.xml (30 min) +2. Improve meta tags (2 hours) +3. Add FAQ schema (2 hours) +4. Submit to Product Hunt (1 hour) +5. Set up Google Search Console (30 min) + +**Total time:** ~6 hours +**ROI:** Very High + +--- + +## 📚 Resources + +**SEO Tools:** +- Google Search Console (free) +- Google Analytics (free) +- Ahrefs (paid) +- SEMrush (paid) +- Screaming Frog (free/paid) + +**Learning:** +- Moz Beginner's Guide to SEO +- Google Search Central +- Ahrefs Blog +- Backlinko + +**Communities:** +- r/SEO +- r/bigseo +- Indie Hackers +- Growth Hackers + +--- + +**Remember:** SEO is a marathon, not a sprint. Consistency and quality content win in the long run! 🏆 diff --git a/TODO.md b/TODO.md index c1f5f424..783483a3 100644 --- a/TODO.md +++ b/TODO.md @@ -1,12 +1,12 @@ # Developer Tools - To-Do List -**Last Updated:** October 14, 2025 +**Last Updated:** October 22, 2025 --- ## 📋 Phase 1: Foundation & Monetization -### ⭐ Priority 1: Advanced URL Fetch (1-2 days) +### ⭐ Priority 1: Advanced URL Fetch (1-2 days) - ✅ COMPLETED #### Design & Planning - [ ] Design UI mockup for simple mode @@ -108,7 +108,7 @@ --- -### 💰 Priority 2: Ad Space Preparation (1 day) +### 💰 Priority 2: Ad Space Preparation (1 day) - ✅ COMPLETED #### Design - [ ] Finalize desktop ad column layout @@ -123,8 +123,7 @@ - [ ] Space for 3 ad blocks - [ ] Proper spacing between ads - [ ] Create `AdBlock.jsx` component - - [ ] Support 300x250 size - - [ ] Support 300x600 size + - [ ] Support 300x250 size (all ads use this size for AdSense compliance) - [ ] Placeholder content for testing - [ ] Loading state - [ ] Error state (if ad fails to load) @@ -180,7 +179,7 @@ --- -### 💵 Priority 3: AdSense Integration (1 day) +### 💵 Priority 3: AdSense Integration (1 day) - ⏳ IN PROGRESS #### AdSense Setup - [ ] Apply for Google AdSense account @@ -193,7 +192,7 @@ - [ ] Log in to AdSense dashboard - [ ] Create ad unit: Desktop Sidebar 1 (300x250) - [ ] Create ad unit: Desktop Sidebar 2 (300x250) -- [ ] Create ad unit: Desktop Sidebar 3 (300x600) +- [ ] Create ad unit: Desktop Sidebar 3 (300x250) - [ ] Create ad unit: Mobile Bottom Banner (320x50) - [ ] Copy ad unit codes @@ -261,7 +260,7 @@ ## 📋 Phase 2: Content Expansion -### 📝 Markdown Editor - MVP (1-2 weeks) +### 📝 Markdown Editor - MVP (1-2 weeks) - ✅ COMPLETED (Oct 22, 2025) #### Planning - [ ] Finalize feature list for MVP diff --git a/package-lock.json b/package-lock.json index d97ec5c0..bdb8e994 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@codemirror/lang-html": "^6.4.9", "@codemirror/lang-javascript": "^6.2.4", "@codemirror/lang-json": "^6.0.2", + "@codemirror/lang-markdown": "^6.4.0", "@codemirror/lang-sql": "^6.10.0", "@codemirror/search": "^6.5.11", "@codemirror/state": "^6.5.2", @@ -28,11 +29,16 @@ "@uiw/react-codemirror": "^4.25.1", "codemirror": "^6.0.2", "diff-match-patch": "^1.0.5", + "dompurify": "^3.3.0", + "file-saver": "^2.0.5", + "highlight.js": "^11.11.1", "html2pdf.js": "^0.12.1", "js-beautify": "^1.15.4", "jspdf": "^3.0.3", "jspdf-autotable": "^5.0.2", "lucide-react": "^0.540.0", + "marked": "^16.4.1", + "marked-emoji": "^2.0.1", "papaparse": "^5.5.3", "react": "18.3.1", "react-diff-view": "^3.3.2", @@ -43,6 +49,7 @@ "react-snap": "^1.23.0", "reactflow": "^11.11.4", "serialize-javascript": "^6.0.0", + "turndown": "^7.2.1", "web-vitals": "^2.1.4" }, "devDependencies": { @@ -2175,6 +2182,21 @@ "@lezer/json": "^1.0.0" } }, + "node_modules/@codemirror/lang-markdown": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.4.0.tgz", + "integrity": "sha512-ZeArR54seh4laFbUTVy0ZmQgO+C/cxxlW4jEoQMhL3HALScBpZBeZcLzrQmJsTEx4is9GzOe0bFAke2B1KZqeA==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.7.1", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.3.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/markdown": "^1.0.0" + } + }, "node_modules/@codemirror/lang-sql": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.10.0.tgz", @@ -3180,10 +3202,26 @@ "@lezer/common": "^1.0.0" } }, + "node_modules/@lezer/markdown": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.5.1.tgz", + "integrity": "sha512-F3ZFnIfNAOy/jPSk6Q0e3bs7e9grfK/n5zerkKoc5COH6Guy3Zb0vrJwXzdck79K16goBhYBRAvhf+ksqe0cMg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0" + } + }, "node_modules/@marijn/find-cluster-break": { "version": "1.0.2", "license": "MIT" }, + "node_modules/@mixmark-io/domino": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", + "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==", + "license": "BSD-2-Clause" + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "dev": true, @@ -7496,11 +7534,10 @@ } }, "node_modules/dompurify": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", - "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.0.tgz", + "integrity": "sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==", "license": "(MPL-2.0 OR Apache-2.0)", - "optional": true, "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -8894,6 +8931,12 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "license": "MIT" + }, "node_modules/filelist": { "version": "1.0.4", "dev": true, @@ -9665,6 +9708,15 @@ "util-deprecate": "^1.0.2" } }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/hoopy": { "version": "0.1.4", "dev": true, @@ -12141,6 +12193,27 @@ "tmpl": "1.0.5" } }, + "node_modules/marked": { + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.1.tgz", + "integrity": "sha512-ntROs7RaN3EvWfy3EZi14H4YxmT6A5YvywfhO+0pm+cH/dnSQRmdAmoFIc3B9aiwTehyk7pESH4ofyBY+V5hZg==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/marked-emoji": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/marked-emoji/-/marked-emoji-2.0.1.tgz", + "integrity": "sha512-P+nRr02dD+yPOFhtGdaVBzp0qzwlksI2f5GumIdHW/3UadzJ5sVi78CZikiSLr9PmdtUOZodZUBNIO6k38pDMQ==", + "license": "MIT", + "peerDependencies": { + "marked": ">=4 <17" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "dev": true, @@ -17555,6 +17628,15 @@ "dev": true, "license": "0BSD" }, + "node_modules/turndown": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.1.tgz", + "integrity": "sha512-7YiPJw6rLClQL3oUKN3KgMaXeJJ2lAyZItclgKDurqnH61so4k4IH/qwmMva0zpuJc/FhRExBBnk7EbeFANlgQ==", + "license": "MIT", + "dependencies": { + "@mixmark-io/domino": "^2.2.0" + } + }, "node_modules/type-check": { "version": "0.4.0", "dev": true, diff --git a/package.json b/package.json index e82f643a..11c826c6 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@codemirror/lang-html": "^6.4.9", "@codemirror/lang-javascript": "^6.2.4", "@codemirror/lang-json": "^6.0.2", + "@codemirror/lang-markdown": "^6.4.0", "@codemirror/lang-sql": "^6.10.0", "@codemirror/search": "^6.5.11", "@codemirror/state": "^6.5.2", @@ -24,11 +25,16 @@ "@uiw/react-codemirror": "^4.25.1", "codemirror": "^6.0.2", "diff-match-patch": "^1.0.5", + "dompurify": "^3.3.0", + "file-saver": "^2.0.5", + "highlight.js": "^11.11.1", "html2pdf.js": "^0.12.1", "js-beautify": "^1.15.4", "jspdf": "^3.0.3", "jspdf-autotable": "^5.0.2", "lucide-react": "^0.540.0", + "marked": "^16.4.1", + "marked-emoji": "^2.0.1", "papaparse": "^5.5.3", "react": "18.3.1", "react-diff-view": "^3.3.2", @@ -39,6 +45,7 @@ "react-snap": "^1.23.0", "reactflow": "^11.11.4", "serialize-javascript": "^6.0.0", + "turndown": "^7.2.1", "web-vitals": "^2.1.4" }, "devDependencies": { diff --git a/public/data/commits.json b/public/data/commits.json index 144afad9..499cd6ed 100644 --- a/public/data/commits.json +++ b/public/data/commits.json @@ -1,8 +1,49 @@ { "changelog": [ + { + "date": "2025-10-22", + "changes": [ + { + "datetime": "2025-10-22T15:00:00+07:00", + "type": "feature", + "title": "New Markdown Editor with Live Preview", + "description": "Write and preview markdown in real-time with GitHub Flavored Markdown support, syntax highlighting for code blocks, and export to PDF, HTML, DOCX, or Plain Text. Perfect for creating README files, documentation, and blog posts." + }, + { + "datetime": "2025-10-22T14:30:00+07:00", + "type": "enhancement", + "title": "Upgraded Code Editor with Expand/Collapse", + "description": "All paste fields now use a professional code editor with syntax highlighting, line numbers, and an expand/collapse toggle. Start with a compact 12-line view, then expand to full screen when you need more space. Works in Markdown Editor, Object Editor, Table Editor, and Invoice Editor." + }, + { + "datetime": "2025-10-22T14:00:00+07:00", + "type": "enhancement", + "title": "Better Export Views with Syntax Highlighting", + "description": "Export sections in Table Editor and Object Editor now show your data with beautiful syntax highlighting and proper formatting. JSON, CSV, TSV, and SQL outputs are easier to read and verify before downloading." + }, + { + "datetime": "2025-10-22T13:30:00+07:00", + "type": "enhancement", + "title": "Improved Object Editor with Advanced URL Fetching", + "description": "Object Editor now has smarter URL fetching with automatic content extraction. Fetch JSON from APIs or extract article content from HTML pages with quality indicators, metadata, word count, and reading time. Perfect for analyzing web content or API responses." + }, + { + "datetime": "2025-10-22T13:00:00+07:00", + "type": "enhancement", + "title": "Object Editor Preview Mode", + "description": "New Preview/Edit toggle in Tree View lets you view data in read-only mode with full text visibility - perfect for long values. Click any nested JSON or serialized data directly in preview mode to explore its structure without switching to edit mode." + } + ] + }, { "date": "2025-10-15", "changes": [ + { + "datetime": "2025-10-15T23:23:00+07:00", + "type": "feature", + "title": "Advanced URL Fetching with Content Extraction", + "description": "Object Editor now intelligently fetches and extracts content from any URL. Automatically detects if URL is a JSON API or HTML page. For HTML pages, extracts article content with quality indicators (Rich Article, General Content, etc.). Shows structured data including title, metadata, word count, and reading time. Perfect for analyzing web articles, blog posts, or API responses." + }, { "datetime": "2025-10-15T22:32:00+07:00", "type": "enhancement", diff --git a/public/index.html b/public/index.html index 611af7c6..df99a2a6 100644 --- a/public/index.html +++ b/public/index.html @@ -13,6 +13,10 @@ Developer Tools - Web Developer Utilities + + + diff --git a/public/sitemap.xml b/public/sitemap.xml index 919d8041..ba56e80e 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -6,7 +6,7 @@ https://dewe.dev/ - 2025-10-15 + 2025-10-22 weekly 1.0 @@ -14,39 +14,45 @@ https://dewe.dev/object-editor - 2025-10-15 + 2025-10-22 monthly 0.9 https://dewe.dev/table-editor - 2025-10-15 + 2025-10-22 monthly 0.9 https://dewe.dev/invoice-editor - 2025-10-15 + 2025-10-22 + monthly + 0.9 + + + https://dewe.dev/markdown-editor + 2025-10-22 monthly 0.9 - + https://dewe.dev/url - 2025-10-15 + 2025-10-22 monthly 0.8 https://dewe.dev/base64 - 2025-10-15 + 2025-10-22 monthly 0.8 https://dewe.dev/beautifier - 2025-10-15 + 2025-10-22 monthly 0.8 @@ -54,13 +60,13 @@ https://dewe.dev/diff - 2025-10-15 + 2025-10-22 monthly 0.8 https://dewe.dev/text-length - 2025-10-15 + 2025-10-22 monthly 0.8 @@ -68,7 +74,13 @@ https://dewe.dev/whats-new - 2025-10-15 + 2025-10-22 + weekly + 0.7 + + + https://dewe.dev/release-notes + 2025-10-22 weekly 0.7 diff --git a/src/App.js b/src/App.js index 63c92885..100514ea 100644 --- a/src/App.js +++ b/src/App.js @@ -4,22 +4,21 @@ import { HelmetProvider } from 'react-helmet-async'; import Layout from './components/Layout'; import ErrorBoundary from './components/ErrorBoundary'; import Home from './pages/Home'; -import JsonTool from './pages/JsonTool'; -import SerializeTool from './pages/SerializeTool'; import UrlTool from './pages/UrlTool'; import Base64Tool from './pages/Base64Tool'; -import CsvJsonTool from './pages/CsvJsonTool'; import BeautifierTool from './pages/BeautifierTool'; import DiffTool from './pages/DiffTool'; import TextLengthTool from './pages/TextLengthTool'; import ObjectEditor from './pages/ObjectEditor'; import TableEditor from './pages/TableEditor'; import InvoiceEditor from './pages/InvoiceEditor'; +import MarkdownEditor from './pages/MarkdownEditor'; import InvoicePreview from './pages/InvoicePreview'; import InvoicePreviewMinimal from './pages/InvoicePreviewMinimal'; import ReleaseNotes from './pages/ReleaseNotes'; import TermsOfService from './pages/TermsOfService'; import PrivacyPolicy from './pages/PrivacyPolicy'; +import NotFound from './pages/NotFound'; import { initGA } from './utils/analytics'; import './index.css'; @@ -37,23 +36,22 @@ function App() { } /> - } /> - } /> } /> } /> - } /> } /> } /> } /> } /> } /> } /> + } /> } /> } /> } /> } /> } /> } /> + } /> diff --git a/src/components/AdBlock.js b/src/components/AdBlock.js new file mode 100644 index 00000000..e9748e6a --- /dev/null +++ b/src/components/AdBlock.js @@ -0,0 +1,36 @@ +import React, { useEffect } from 'react'; + +/** + * AdBlock Component - Individual ad unit + * Displays a single Google AdSense ad + */ +const AdBlock = ({ slot, size = '300x250', className = '' }) => { + useEffect(() => { + try { + // Push ad to AdSense queue + (window.adsbygoogle = window.adsbygoogle || []).push({}); + } catch (e) { + console.error('AdSense error:', e); + } + }, []); + + const [width, height] = size.split('x'); + + return ( +
+ +
+ ); +}; + +export default AdBlock; diff --git a/src/components/AdColumn.js b/src/components/AdColumn.js new file mode 100644 index 00000000..654b8722 --- /dev/null +++ b/src/components/AdColumn.js @@ -0,0 +1,32 @@ +import React from 'react'; +import AdBlock from './AdBlock'; + +/** + * AdColumn Component - Desktop sidebar with 3 ad units + * Hidden on mobile/tablet, visible on desktop (1200px+) + * All ads are 300x250 (Medium Rectangle) to comply with Google AdSense policies + * - Ads must be fully viewable without scrolling + * - No scrollable containers allowed + */ +const AdColumn = ({ + slot1 = 'REPLACE_WITH_SLOT_1', + slot2 = 'REPLACE_WITH_SLOT_2', + slot3 = 'REPLACE_WITH_SLOT_3' +}) => { + return ( + + ); +}; + +export default AdColumn; diff --git a/src/components/AdvancedURLFetch.js b/src/components/AdvancedURLFetch.js new file mode 100644 index 00000000..040a4eb1 --- /dev/null +++ b/src/components/AdvancedURLFetch.js @@ -0,0 +1,531 @@ +import React, { useState, useEffect } from 'react'; +import { ChevronDown, ChevronUp, Plus, X, Save, FolderOpen, Braces, Code } from 'lucide-react'; +import ProBadge, { ProFeatureLock } from './ProBadge'; +import { isFeatureEnabled, getFeatureInfo } from '../config/features'; +import CodeMirrorEditor from './CodeMirrorEditor'; +import StructuredEditor from './StructuredEditor'; + +const AdvancedURLFetch = ({ + url, + onUrlChange, + onFetch, + fetching, + showAdvanced = false, + onToggleAdvanced, + onUpgrade = null, // Callback for upgrade action + onEditBodyVisually = null // Callback to switch to visual editor +}) => { + const isProFeatureEnabled = isFeatureEnabled('ADVANCED_URL_FETCH'); + const featureInfo = getFeatureInfo('ADVANCED_URL_FETCH'); + const [method, setMethod] = useState('GET'); + const [headers, setHeaders] = useState([{ key: '', value: '', enabled: true }]); + const [body, setBody] = useState(''); + const [bodyViewMode, setBodyViewMode] = useState('raw'); // 'raw' or 'visual' + const [bodyStructuredData, setBodyStructuredData] = useState({}); + const [queryParams, setQueryParams] = useState([{ key: '', value: '', enabled: true }]); + const [authType, setAuthType] = useState('none'); + const [authToken, setAuthToken] = useState(''); + const [authUsername, setAuthUsername] = useState(''); + const [authPassword, setAuthPassword] = useState(''); + const [presetName, setPresetName] = useState(''); + const [savedPresets, setSavedPresets] = useState([]); + + // Load saved presets from localStorage + useEffect(() => { + const saved = localStorage.getItem('urlFetchPresets'); + if (saved) { + try { + setSavedPresets(JSON.parse(saved)); + } catch (e) { + console.error('Failed to load presets:', e); + } + } + }, []); + + // Add header row + const addHeader = () => { + setHeaders([...headers, { key: '', value: '', enabled: true }]); + }; + + // Remove header row + const removeHeader = (index) => { + setHeaders(headers.filter((_, i) => i !== index)); + }; + + // Update header + const updateHeader = (index, field, value) => { + const newHeaders = [...headers]; + newHeaders[index][field] = value; + setHeaders(newHeaders); + }; + + // Add query param row + const addQueryParam = () => { + setQueryParams([...queryParams, { key: '', value: '', enabled: true }]); + }; + + // Remove query param row + const removeQueryParam = (index) => { + setQueryParams(queryParams.filter((_, i) => i !== index)); + }; + + // Update query param + const updateQueryParam = (index, field, value) => { + const newParams = [...queryParams]; + newParams[index][field] = value; + setQueryParams(newParams); + }; + + // Build final URL with query params + const buildFinalUrl = () => { + const baseUrl = url.trim(); + const enabledParams = queryParams.filter(p => p.enabled && p.key.trim()); + + if (enabledParams.length === 0) return baseUrl; + + const urlObj = new URL(baseUrl.startsWith('http') ? baseUrl : 'https://' + baseUrl); + enabledParams.forEach(param => { + urlObj.searchParams.append(param.key, param.value); + }); + + return urlObj.toString(); + }; + + // Build headers object + const buildHeaders = () => { + const headersObj = {}; + + // Add custom headers + headers + .filter(h => h.enabled && h.key.trim()) + .forEach(h => { + headersObj[h.key] = h.value; + }); + + // Add auth headers + if (authType === 'bearer' && authToken.trim()) { + headersObj['Authorization'] = `Bearer ${authToken}`; + } else if (authType === 'apikey' && authToken.trim()) { + headersObj['X-API-Key'] = authToken; + } else if (authType === 'basic' && authUsername.trim()) { + const credentials = btoa(`${authUsername}:${authPassword}`); + headersObj['Authorization'] = `Basic ${credentials}`; + } + + // Add content-type for POST/PUT/PATCH with body + if (['POST', 'PUT', 'PATCH'].includes(method) && body.trim() && !headersObj['Content-Type']) { + headersObj['Content-Type'] = 'application/json'; + } + + return headersObj; + }; + + // Handle fetch with advanced options + const handleAdvancedFetch = () => { + const finalUrl = buildFinalUrl(); + const finalHeaders = buildHeaders(); + const finalBody = ['POST', 'PUT', 'PATCH'].includes(method) && body.trim() ? body : undefined; + + onFetch({ + url: finalUrl, + method, + headers: finalHeaders, + body: finalBody + }); + }; + + // Save preset + const savePreset = () => { + if (!presetName.trim()) { + alert('Please enter a preset name'); + return; + } + + const preset = { + name: presetName, + url, + method, + headers: headers.filter(h => h.key.trim()), + body, + queryParams: queryParams.filter(p => p.key.trim()), + authType, + authToken, + authUsername, + // Don't save password for security + timestamp: Date.now() + }; + + const newPresets = [...savedPresets, preset]; + setSavedPresets(newPresets); + localStorage.setItem('urlFetchPresets', JSON.stringify(newPresets)); + setPresetName(''); + alert('Preset saved!'); + }; + + // Load preset + const loadPreset = (preset) => { + onUrlChange(preset.url); + setMethod(preset.method); + setHeaders(preset.headers.length > 0 ? preset.headers : [{ key: '', value: '', enabled: true }]); + setBody(preset.body || ''); + setQueryParams(preset.queryParams.length > 0 ? preset.queryParams : [{ key: '', value: '', enabled: true }]); + setAuthType(preset.authType); + setAuthToken(preset.authToken || ''); + setAuthUsername(preset.authUsername || ''); + }; + + // Delete preset + const deletePreset = (index) => { + // eslint-disable-next-line no-restricted-globals + if (confirm('Delete this preset?')) { + const newPresets = savedPresets.filter((_, i) => i !== index); + setSavedPresets(newPresets); + localStorage.setItem('urlFetchPresets', JSON.stringify(newPresets)); + } + }; + + return ( +
+ {/* Basic URL Input */} +
+ + +
+ onUrlChange(e.target.value)} + placeholder="https://api.example.com/endpoint" + className="tool-input w-full" + onKeyPress={(e) => e.key === 'Enter' && (showAdvanced ? handleAdvancedFetch() : onFetch())} + /> +
+ + +
+ + {/* Toggle Advanced */} + {/* Advanced Options Toggle - Hidden for now */} + {false && ( + + )} + + {/* Advanced Options */} + {showAdvanced && ( + isProFeatureEnabled ? ( +
+ + {/* Query Parameters */} +
+
+ + +
+
+ {queryParams.map((param, index) => ( +
+ updateQueryParam(index, 'enabled', e.target.checked)} + className="w-4 h-4" + /> + updateQueryParam(index, 'key', e.target.value)} + placeholder="key" + className="tool-input flex-1 text-sm" + /> + updateQueryParam(index, 'value', e.target.value)} + placeholder="value" + className="tool-input flex-1 text-sm" + /> + +
+ ))} +
+
+ + {/* Headers */} +
+
+ + +
+
+ {headers.map((header, index) => ( +
+ updateHeader(index, 'enabled', e.target.checked)} + className="w-4 h-4" + /> + updateHeader(index, 'key', e.target.value)} + placeholder="Header-Name" + className="tool-input flex-1 text-sm" + /> + updateHeader(index, 'value', e.target.value)} + placeholder="value" + className="tool-input flex-1 text-sm" + /> + +
+ ))} +
+
+ + {/* Authentication */} +
+ + + + {authType === 'bearer' && ( + setAuthToken(e.target.value)} + placeholder="Enter bearer token" + className="tool-input w-full" + /> + )} + + {authType === 'apikey' && ( + setAuthToken(e.target.value)} + placeholder="Enter API key" + className="tool-input w-full" + /> + )} + + {authType === 'basic' && ( +
+ setAuthUsername(e.target.value)} + placeholder="Username" + className="tool-input w-full" + /> + setAuthPassword(e.target.value)} + placeholder="Password" + className="tool-input w-full" + /> +
+ )} +
+ + {/* Request Body */} + {['POST', 'PUT', 'PATCH'].includes(method) && ( +
+
+ +
+ +
+
+ + {bodyViewMode === 'raw' ? ( +
+ +
+ ) : ( +
+ { + setBodyStructuredData(newData); + setBody(JSON.stringify(newData, null, 2)); + }} + readOnly={false} + /> +
+ )} + +

+ 💡 Tip: Toggle between raw JSON and visual tree editor for easier editing +

+
+ )} + + {/* Save/Load Presets */} +
+ + +
+ setPresetName(e.target.value)} + placeholder="Preset name" + className="tool-input flex-1 text-sm" + /> + +
+ + {savedPresets.length > 0 && ( +
+ {savedPresets.map((preset, index) => ( +
+ + +
+ ))} +
+ )} +
+
+ ) : ( + + ) + )} + +

+ {showAdvanced + ? 'Configure HTTP method, headers, authentication, and request body for API testing' + : 'Enter any URL that returns JSON data. Examples: Telegram Bot API, JSONPlaceholder, GitHub API, etc.' + } +

+
+ ); +}; + +export default AdvancedURLFetch; diff --git a/src/components/CodeMirrorEditor.js b/src/components/CodeMirrorEditor.js index dd37e5dc..bd3154cc 100644 --- a/src/components/CodeMirrorEditor.js +++ b/src/components/CodeMirrorEditor.js @@ -1,10 +1,12 @@ import React, { useRef, useEffect, useState, useCallback } from 'react'; -import { EditorView } from '@codemirror/view'; +import { EditorView, keymap } from '@codemirror/view'; import { EditorState } from '@codemirror/state'; import { basicSetup } from 'codemirror'; import { json } from '@codemirror/lang-json'; import { sql } from '@codemirror/lang-sql'; +import { markdown } from '@codemirror/lang-markdown'; import { oneDark } from '@codemirror/theme-one-dark'; +import { indentWithTab } from '@codemirror/commands'; import { Maximize2, Minimize2 } from 'lucide-react'; const CodeMirrorEditor = ({ @@ -15,7 +17,8 @@ const CodeMirrorEditor = ({ language = 'json', maxLines = 12, showToggle = true, - cardRef = null // Reference to the card header for scroll target + cardRef = null, // Reference to the card header for scroll target + height = '350px' // Configurable height, default 350px }) => { const editorRef = useRef(null); const viewRef = useRef(null); @@ -53,33 +56,42 @@ const CodeMirrorEditor = ({ langExtension = [json()]; } else if (language === 'sql') { langExtension = [sql()]; + } else if (language === 'markdown') { + langExtension = [markdown()]; } const extensions = [ basicSetup, ...langExtension, - // Enable line wrapping for single-line content - ...(isSingleLine ? [EditorView.lineWrapping] : []), + // Enable Tab key to insert spaces (2 spaces for indentation) + keymap.of([indentWithTab]), + // Enable line wrapping for single-line content OR markdown + ...(isSingleLine || language === 'markdown' ? [EditorView.lineWrapping] : []), EditorView.theme({ '&': { fontSize: '14px', width: '100%', + maxWidth: '100%', }, '.cm-content': { padding: '12px', + maxWidth: '100%', }, '.cm-focused': { outline: 'none', }, '.cm-editor': { borderRadius: '6px', + maxWidth: '100%', }, '.cm-scroller': { overflowY: 'auto', + overflowX: 'auto', height: '100%', + maxWidth: '100%', }, '.cm-line': { - wordBreak: isSingleLine ? 'break-word' : 'normal', + wordBreak: isSingleLine || language === 'markdown' ? 'break-word' : 'normal', } }), EditorView.updateListener.of((update) => { @@ -102,14 +114,22 @@ const CodeMirrorEditor = ({ viewRef.current = view; + // Expose view on the DOM element for toolbar access + if (editorRef.current) { + const cmEditor = editorRef.current.querySelector('.cm-editor'); + if (cmEditor) { + cmEditor.cmView = { view }; + } + } + // Apply styles immediately after editor creation setTimeout(() => { const editorElement = editorRef.current?.querySelector('.cm-editor'); const scrollerElement = editorRef.current?.querySelector('.cm-scroller'); if (editorElement) { - editorElement.style.height = '350px'; - editorElement.style.maxHeight = '350px'; + editorElement.style.height = height; + editorElement.style.maxHeight = height; } if (scrollerElement) { @@ -128,7 +148,7 @@ const CodeMirrorEditor = ({ } }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isDark, isSingleLine]); // Recreate when theme or line count changes + }, [isDark, isSingleLine, height, language]); // Recreate when theme, line count, height, or language changes // Apply overflow and height styles const applyEditorStyles = useCallback(() => { @@ -142,8 +162,8 @@ const CodeMirrorEditor = ({ editorElement.style.height = 'auto'; editorElement.style.maxHeight = 'none'; } else { - editorElement.style.height = '350px'; - editorElement.style.maxHeight = '350px'; + editorElement.style.height = height; + editorElement.style.maxHeight = height; } } @@ -152,7 +172,7 @@ const CodeMirrorEditor = ({ scrollerElement.style.overflowY = isExpanded ? 'visible' : 'auto'; scrollerElement.style.height = '100%'; } - }, [isExpanded]); + }, [isExpanded, height]); // Apply styles on mount, expand/collapse, and content changes useEffect(() => { @@ -182,7 +202,7 @@ const CodeMirrorEditor = ({ ref={editorRef} className={`dewedev-code-mirror border border-gray-300 dark:border-gray-600 rounded-md overflow-hidden ${ isDark ? 'bg-gray-900' : 'bg-white' - } ${isExpanded ? 'h-auto' : 'h-[350px]'}`} + } ${isExpanded ? 'h-auto' : `h-[${height}]`}`} /> {showToggle && ( +
+ +
+
+ ); +}; + +export default MobileAdBanner; diff --git a/src/components/ProBadge.js b/src/components/ProBadge.js new file mode 100644 index 00000000..b1c3d299 --- /dev/null +++ b/src/components/ProBadge.js @@ -0,0 +1,123 @@ +import React from 'react'; +import { Crown, Lock } from 'lucide-react'; + +/** + * ProBadge Component + * + * Displays a PRO badge for premium features + * Can be used inline or as a button to trigger upgrade flow + */ +const ProBadge = ({ + variant = 'badge', // 'badge' | 'button' | 'inline' + size = 'sm', // 'xs' | 'sm' | 'md' | 'lg' + onClick = null, + showIcon = true, + className = '' +}) => { + + const sizeClasses = { + xs: 'text-xs px-1.5 py-0.5', + sm: 'text-xs px-2 py-1', + md: 'text-sm px-3 py-1.5', + lg: 'text-base px-4 py-2' + }; + + const iconSizes = { + xs: 'h-2.5 w-2.5', + sm: 'h-3 w-3', + md: 'h-4 w-4', + lg: 'h-5 w-5' + }; + + if (variant === 'inline') { + return ( + + {showIcon && } + PRO + + ); + } + + if (variant === 'button') { + return ( + + ); + } + + // Default badge variant + return ( + + {showIcon && } + PRO + + ); +}; + +/** + * ProFeatureLock Component + * + * Displays a locked feature message with upgrade prompt + */ +export const ProFeatureLock = ({ + featureName, + featureDescription, + onUpgrade = null, + compact = false +}) => { + const handleUpgrade = () => { + if (onUpgrade) { + onUpgrade(); + } else { + // Default: scroll to top and show upgrade info + window.scrollTo({ top: 0, behavior: 'smooth' }); + alert('Upgrade to PRO to unlock this feature!\n\nPRO features will be available soon.'); + } + }; + + if (compact) { + return ( +
+ + + feature + + +
+ ); + } + + return ( +
+
+
+ +
+
+
+

+ {featureName} +

+ +
+

+ {featureDescription} +

+ +
+
+
+ ); +}; + +export default ProBadge; diff --git a/src/components/RelatedTools.js b/src/components/RelatedTools.js new file mode 100644 index 00000000..6f034715 --- /dev/null +++ b/src/components/RelatedTools.js @@ -0,0 +1,96 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { ArrowRight } from 'lucide-react'; + +/** + * Related Tools Component + * Shows related tools at the bottom of each tool page for internal linking + */ + +const RELATED_TOOLS = { + 'markdown-editor': [ + { name: 'Code Beautifier', path: '/beautifier', desc: 'Format and beautify your code' }, + { name: 'Text Length Checker', path: '/text-length', desc: 'Count words and characters' }, + { name: 'Diff Tool', path: '/diff', desc: 'Compare text differences' } + ], + 'object-editor': [ + { name: 'Table Editor', path: '/table-editor', desc: 'Edit JSON as table' }, + { name: 'Code Beautifier', path: '/beautifier', desc: 'Format & beautify code' }, + { name: 'Markdown Editor', path: '/markdown-editor', desc: 'Write documentation' } + ], + 'table-editor': [ + { name: 'Object Editor', path: '/object-editor', desc: 'Edit JSON visually' }, + { name: 'Code Beautifier', path: '/beautifier', desc: 'Format & beautify code' }, + { name: 'Markdown Editor', path: '/markdown-editor', desc: 'Create documentation' } + ], + 'invoice-editor': [ + { name: 'Markdown Editor', path: '/markdown-editor', desc: 'Create documentation' }, + { name: 'Table Editor', path: '/table-editor', desc: 'Manage data tables' }, + { name: 'Object Editor', path: '/object-editor', desc: 'Edit JSON data' } + ], + 'beautifier': [ + { name: 'Markdown Editor', path: '/markdown-editor', desc: 'Write documentation' }, + { name: 'Diff Tool', path: '/diff', desc: 'Compare code changes' }, + { name: 'Object Editor', path: '/object-editor', desc: 'Edit JSON visually' } + ], + 'diff': [ + { name: 'Beautifier', path: '/beautifier', desc: 'Format code first' }, + { name: 'Markdown Editor', path: '/markdown-editor', desc: 'Document changes' }, + { name: 'Text Length', path: '/text-length', desc: 'Analyze text' } + ], + 'text-length': [ + { name: 'Markdown Editor', path: '/markdown-editor', desc: 'Write content' }, + { name: 'Diff Tool', path: '/diff', desc: 'Compare texts' }, + { name: 'Beautifier', path: '/beautifier', desc: 'Format code' } + ], + 'url': [ + { name: 'Base64 Encoder', path: '/base64', desc: 'Encode/decode data' }, + { name: 'Code Beautifier', path: '/beautifier', desc: 'Format code' }, + { name: 'Object Editor', path: '/object-editor', desc: 'Edit JSON data' } + ], + 'base64': [ + { name: 'URL Encoder', path: '/url', desc: 'Encode URLs' }, + { name: 'Object Editor', path: '/object-editor', desc: 'Edit JSON & PHP data' }, + { name: 'Code Beautifier', path: '/beautifier', desc: 'Format code' } + ] +}; + +const RelatedTools = ({ toolId }) => { + const relatedTools = RELATED_TOOLS[toolId]; + + if (!relatedTools || relatedTools.length === 0) { + return null; + } + + return ( +
+

+ + You Might Also Like +

+
+ {relatedTools.map((tool) => ( + +
+
+

+ {tool.name} +

+

+ {tool.desc} +

+
+ +
+ + ))} +
+
+ ); +}; + +export default RelatedTools; diff --git a/src/components/SEO.js b/src/components/SEO.js index 894f077b..1aa48cde 100644 --- a/src/components/SEO.js +++ b/src/components/SEO.js @@ -1,5 +1,6 @@ import React from 'react'; import { Helmet } from 'react-helmet-async'; +import TOOL_FAQS from '../data/faqs'; const SEO = ({ title, @@ -7,7 +8,8 @@ const SEO = ({ keywords, path = '/', type = 'website', - image = 'https://dewe.dev/og-image.png' + image = 'https://dewe.dev/og-image.png', + toolId = null }) => { const siteUrl = 'https://dewe.dev'; const fullUrl = `${siteUrl}${path}`; @@ -17,6 +19,47 @@ const SEO = ({ const defaultKeywords = 'developer tools, json editor, csv converter, base64 encoder, url encoder, code beautifier, diff tool, web developer utilities, online tools'; const metaKeywords = keywords || defaultKeywords; + // Get FAQ data for this tool + const faqs = toolId && TOOL_FAQS[toolId] ? TOOL_FAQS[toolId] : null; + + // Generate breadcrumb schema + const breadcrumbSchema = { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + "itemListElement": [ + { + "@type": "ListItem", + "position": 1, + "name": "Home", + "item": siteUrl + } + ] + }; + + // Add current page to breadcrumb if not homepage + if (path !== '/') { + breadcrumbSchema.itemListElement.push({ + "@type": "ListItem", + "position": 2, + "name": title || "Page", + "item": fullUrl + }); + } + + // Generate FAQ schema if FAQs exist + const faqSchema = faqs ? { + "@context": "https://schema.org", + "@type": "FAQPage", + "mainEntity": faqs.map(faq => ({ + "@type": "Question", + "name": faq.question, + "acceptedAnswer": { + "@type": "Answer", + "text": faq.answer + } + })) + } : null; + return ( {/* Basic Meta Tags */} @@ -46,7 +89,7 @@ const SEO = ({ - {/* JSON-LD Structured Data */} + {/* JSON-LD Structured Data - WebApplication */} + + {/* JSON-LD Structured Data - Breadcrumb */} + + + {/* JSON-LD Structured Data - FAQ (if available) */} + {faqSchema && ( + + )} ); }; diff --git a/src/components/StructuredEditor.js b/src/components/StructuredEditor.js index 8e447687..9dc6f3de 100644 --- a/src/components/StructuredEditor.js +++ b/src/components/StructuredEditor.js @@ -8,7 +8,8 @@ const StructuredEditor = ({ onDataChange, initialData = {}, readOnly: readOnlyPr const isInternalUpdate = useRef(false); const [nestedEditModal, setNestedEditModal] = useState(null); // { path, value, type: 'json' | 'serialized' } const [nestedData, setNestedData] = useState(null); - const [editMode, setEditMode] = useState(false); // Internal edit mode state + // Start in edit mode if readOnly is false + const [editMode, setEditMode] = useState(readOnlyProp === false); // Use internal editMode if readOnlyProp is not explicitly set, otherwise use prop const readOnly = readOnlyProp !== false ? readOnlyProp : !editMode; diff --git a/src/components/ToolLayout.js b/src/components/ToolLayout.js index b6d62871..00278d6d 100644 --- a/src/components/ToolLayout.js +++ b/src/components/ToolLayout.js @@ -1,29 +1,45 @@ import React from 'react'; +import AdColumn from './AdColumn'; +import MobileAdBanner from './MobileAdBanner'; const ToolLayout = ({ title, description, children, icon: Icon }) => { return ( -
- {/* Header */} -
-
- {Icon && } -

- {title} -

+ <> +
+ {/* Main Content */} +
+ {/* Header */} +
+
+ {Icon && } +

+ {title} +

+
+ + {description && ( +

+ {description} +

+ )} +
+ + {/* Tool Content */} +
+ {children} +
- - {description && ( -

- {description} -

- )} + + {/* Desktop Ad Column - Hidden on mobile */} +
- {/* Tool Content */} -
- {children} -
-
+ {/* Mobile Ad Banner - Hidden on desktop */} + + + {/* Add padding to bottom on mobile to prevent content overlap with sticky ad */} +
+ ); }; diff --git a/src/config/features.js b/src/config/features.js new file mode 100644 index 00000000..741e70b8 --- /dev/null +++ b/src/config/features.js @@ -0,0 +1,81 @@ +/** + * Feature Toggle System + * + * Controls which features are available in FREE vs PRO versions + * Currently static, will be dynamic from database in the future + */ + +// User tier - will be fetched from database/auth in the future +export const USER_TIER = { + FREE: 'free', + PRO: 'pro' +}; + +// Current user tier (static for now, will be dynamic) +// TODO: Replace with actual user tier from authentication/database +export const getCurrentUserTier = () => { + // For development/testing, you can change this + const staticTier = USER_TIER.PRO; // Change to USER_TIER.PRO to test pro features + + // In the future, this will be: + // return getUserFromAuth()?.tier || USER_TIER.FREE; + + return staticTier; +}; + +// Feature flags +export const FEATURES = { + // Advanced URL Fetch with headers, methods, body, auth + ADVANCED_URL_FETCH: { + name: 'Advanced URL Fetch', + description: 'Custom HTTP methods, headers, authentication, and request body', + tier: USER_TIER.PRO, + enabled: (userTier) => userTier === USER_TIER.PRO + }, + + // Future pro features can be added here + BULK_OPERATIONS: { + name: 'Bulk Operations', + description: 'Process multiple files or operations at once', + tier: USER_TIER.PRO, + enabled: (userTier) => userTier === USER_TIER.PRO + }, + + EXPORT_TEMPLATES: { + name: 'Export Templates', + description: 'Save and reuse custom export templates', + tier: USER_TIER.PRO, + enabled: (userTier) => userTier === USER_TIER.PRO + }, + + CLOUD_SYNC: { + name: 'Cloud Sync', + description: 'Sync your data and settings across devices', + tier: USER_TIER.PRO, + enabled: (userTier) => userTier === USER_TIER.PRO + } +}; + +// Helper function to check if a feature is enabled +export const isFeatureEnabled = (featureName) => { + const feature = FEATURES[featureName]; + if (!feature) return false; + + const userTier = getCurrentUserTier(); + return feature.enabled(userTier); +}; + +// Helper function to get user tier +export const getUserTier = () => { + return getCurrentUserTier(); +}; + +// Helper function to check if user is pro +export const isProUser = () => { + return getCurrentUserTier() === USER_TIER.PRO; +}; + +// Helper function to get feature info +export const getFeatureInfo = (featureName) => { + return FEATURES[featureName] || null; +}; diff --git a/src/config/tools.js b/src/config/tools.js index df162aac..daec7c2e 100644 --- a/src/config/tools.js +++ b/src/config/tools.js @@ -63,6 +63,14 @@ export const TOOLS = [ tags: ['Table', 'CSV', 'JSON', 'Data', 'Editor'], category: 'editor' }, + { + path: '/markdown-editor', + name: 'Markdown Editor', + icon: FileText, + description: 'Write and preview markdown with live rendering, syntax highlighting, and export options', + tags: ['Markdown', 'Editor', 'Preview', 'Export', 'GFM'], + category: 'editor' + }, { path: '/invoice-editor', name: 'Invoice Editor', diff --git a/src/data/faqs.js b/src/data/faqs.js new file mode 100644 index 00000000..919c1f0f --- /dev/null +++ b/src/data/faqs.js @@ -0,0 +1,100 @@ +/** + * FAQ Data for SEO Schema Markup + * Used to generate FAQPage structured data for better search visibility + */ + +export const TOOL_FAQS = { + 'markdown-editor': [ + { + question: "Is this markdown editor free to use?", + answer: "Yes, completely free with no limits. All processing happens in your browser with no data upload or storage. No account needed." + }, + { + question: "Does it support GitHub Flavored Markdown?", + answer: "Yes, full GitHub Flavored Markdown (GFM) support including tables, task lists, strikethrough, and syntax highlighting for code blocks." + }, + { + question: "Can I export my markdown to PDF?", + answer: "Yes, you can export your markdown to PDF, HTML, or plain text with one click. The PDF export maintains proper formatting and styling." + }, + { + question: "Is my data safe and private?", + answer: "100% safe. All processing happens locally in your browser. We never upload, store, or transmit your data to any server. Your content stays on your device." + }, + { + question: "Does it work offline?", + answer: "Yes, once loaded, the markdown editor works completely offline. No internet connection required for editing or exporting." + } + ], + + 'object-editor': [ + { + question: "What is the Object Editor used for?", + answer: "The Object Editor is a visual tool for editing JSON objects, nested data structures, arrays, and complex data. Perfect for developers working with APIs, configuration files, or database records." + }, + { + question: "Can I import JSON from a URL?", + answer: "Yes, you can fetch JSON data directly from any URL or API endpoint. The editor will parse and display it in an easy-to-edit visual format." + }, + { + question: "Does it validate JSON syntax?", + answer: "Yes, real-time JSON validation with detailed error messages. The editor highlights syntax errors and helps you fix them quickly." + }, + { + question: "Is my data stored anywhere?", + answer: "No, all data processing happens in your browser. We never upload, store, or transmit your data. 100% privacy-first and secure." + }, + { + question: "Can I edit nested objects and arrays?", + answer: "Yes, full support for nested objects, arrays, and complex data structures. Add, edit, delete properties at any level with visual controls." + } + ], + + 'table-editor': [ + { + question: "What file formats can I import?", + answer: "Import CSV, TSV, JSON, Excel (XLSX/XLS), SQL dumps, and paste from spreadsheets like Google Sheets or Excel. Automatic format detection included." + }, + { + question: "Can I export to Excel format?", + answer: "Yes, export to Excel (XLSX), CSV, TSV, JSON, Markdown tables, HTML tables, and SQL INSERT statements. Choose the format you need." + }, + { + question: "Is there a row or column limit?", + answer: "No hard limit. The editor efficiently handles thousands of rows and columns in your browser without performance issues." + }, + { + question: "Can I edit JSON data in table cells?", + answer: "Yes, the editor detects JSON/serialized data in cells and lets you edit it visually in the Object Editor. Seamless integration between tools." + }, + { + question: "Does it work with SQL databases?", + answer: "Yes, import SQL dumps from phpMyAdmin or other tools, edit the data visually, and export back to SQL INSERT statements for database import." + } + ], + + 'invoice-editor': [ + { + question: "Is the invoice editor free?", + answer: "Yes, completely free with no limits. Create unlimited invoices with professional templates. No account or subscription required." + }, + { + question: "What invoice templates are available?", + answer: "Multiple professional templates: Standard, Modern, Minimal, and Classic. Each template is customizable with your branding and colors." + }, + { + question: "Can I save my invoices?", + answer: "Yes, save invoices as JSON files to your device. Load them anytime to edit or create new invoices. All data stays on your device." + }, + { + question: "Can I export to PDF?", + answer: "Yes, export invoices to PDF with professional formatting. Perfect for sending to clients or printing. One-click export included." + }, + { + question: "Does it calculate taxes and totals automatically?", + answer: "Yes, automatic calculation of subtotals, taxes, discounts, and final totals. Supports multiple tax rates and discount types (percentage or fixed amount)." + } + ] +}; + +export default TOOL_FAQS; diff --git a/src/index.css b/src/index.css index 206260af..926ed601 100644 --- a/src/index.css +++ b/src/index.css @@ -8,6 +8,8 @@ html { font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; overflow-x: hidden; + width: 100%; + max-width: 100vw; } body { @@ -16,6 +18,13 @@ max-width: 100vw; } + #root { + overflow-x: hidden; + width: 100%; + max-width: 100vw; + min-width: 0; + } + code, pre { font-family: 'JetBrains Mono', Monaco, 'Cascadia Code', 'Segoe UI Mono', 'Roboto Mono', monospace; } @@ -38,6 +47,14 @@ @apply px-4 py-2 bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300 rounded-md font-medium transition-colors duration-200; } + .tool-button-primary { + @apply flex items-center px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded-md font-medium transition-colors duration-200; + } + + .toolbar-btn { + @apply p-2 hover:bg-gray-200 dark:hover:bg-gray-700 rounded-md transition-colors duration-200 text-gray-700 dark:text-gray-300 font-medium text-sm; + } + .copy-button { @apply absolute top-2 right-2 p-2 bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600 rounded-md transition-colors duration-200; } diff --git a/src/pages/CsvJsonTool.js b/src/pages/CsvJsonTool.js deleted file mode 100644 index 75dca353..00000000 --- a/src/pages/CsvJsonTool.js +++ /dev/null @@ -1,315 +0,0 @@ -import React, { useState } from 'react'; -import { RefreshCw, Upload } from 'lucide-react'; -import ToolLayout from '../components/ToolLayout'; -import CopyButton from '../components/CopyButton'; - -const CsvJsonTool = () => { - const [input, setInput] = useState(''); - const [output, setOutput] = useState(''); - const [mode, setMode] = useState('csv-to-json'); // 'csv-to-json' or 'json-to-csv' - const [delimiter, setDelimiter] = useState(','); - const [hasHeaders, setHasHeaders] = useState(true); - - const csvToJson = () => { - try { - const lines = input.trim().split('\n'); - if (lines.length === 0) { - setOutput('Error: No data to convert'); - return; - } - - const headers = hasHeaders ? lines[0].split(delimiter).map(h => h.trim()) : null; - const dataLines = hasHeaders ? lines.slice(1) : lines; - - const result = dataLines.map((line, index) => { - const values = line.split(delimiter).map(v => v.trim()); - - if (hasHeaders && headers) { - const obj = {}; - headers.forEach((header, i) => { - obj[header] = values[i] || ''; - }); - return obj; - } else { - return values; - } - }); - - setOutput(JSON.stringify(result, null, 2)); - } catch (err) { - setOutput(`Error: ${err.message}`); - } - }; - - const jsonToCsv = () => { - try { - const data = JSON.parse(input); - - let csv = ''; - - if (Array.isArray(data)) { - // Handle array of objects (original functionality) - if (data.length === 0) { - setOutput('Error: Empty array'); - return; - } - - // Get headers from first object - const headers = Object.keys(data[0]); - - // Add headers if enabled - if (hasHeaders) { - csv += headers.join(delimiter) + '\n'; - } - - // Add data rows - data.forEach(row => { - const values = headers.map(header => { - const value = row[header] || ''; - // Escape values containing delimiter or quotes - if (typeof value === 'string' && (value.includes(delimiter) || value.includes('"') || value.includes('\n'))) { - return `"${value.replace(/"/g, '""')}"`; - } - return value; - }); - csv += values.join(delimiter) + '\n'; - }); - - } else if (typeof data === 'object' && data !== null) { - // Handle single object as key-value pairs - - // Add headers if enabled - if (hasHeaders) { - csv += `Key${delimiter}Value\n`; - } - - // Add key-value rows - Object.entries(data).forEach(([key, value]) => { - // Format the key - let formattedKey = key; - if (typeof key === 'string' && (key.includes(delimiter) || key.includes('"') || key.includes('\n'))) { - formattedKey = `"${key.replace(/"/g, '""')}"`; - } - - // Format the value - let formattedValue = ''; - if (value === null) { - formattedValue = 'null'; - } else if (value === undefined) { - formattedValue = 'undefined'; - } else if (typeof value === 'object') { - // Convert objects/arrays to JSON string - formattedValue = JSON.stringify(value); - } else { - formattedValue = String(value); - } - - // Escape value if needed - if (typeof formattedValue === 'string' && (formattedValue.includes(delimiter) || formattedValue.includes('"') || formattedValue.includes('\n'))) { - formattedValue = `"${formattedValue.replace(/"/g, '""')}"`; - } - - csv += `${formattedKey}${delimiter}${formattedValue}\n`; - }); - - } else { - setOutput('Error: JSON must be an object or an array of objects'); - return; - } - - setOutput(csv.trim()); - } catch (err) { - setOutput(`Error: ${err.message}`); - } - }; - - const handleProcess = () => { - if (mode === 'csv-to-json') { - csvToJson(); - } else { - jsonToCsv(); - } - }; - - const handleFileUpload = (event) => { - const file = event.target.files[0]; - if (file) { - const reader = new FileReader(); - reader.onload = (e) => { - setInput(e.target.result); - }; - reader.readAsText(file); - } - }; - - const clearAll = () => { - setInput(''); - setOutput(''); - }; - - const loadSample = () => { - if (mode === 'csv-to-json') { - setInput(`name,age,email,city -John Doe,30,john@example.com,New York -Jane Smith,25,jane@example.com,Los Angeles -Bob Johnson,35,bob@example.com,Chicago`); - } else { - setInput(`[ - { - "name": "John Doe", - "age": 30, - "email": "john@example.com", - "city": "New York" - }, - { - "name": "Jane Smith", - "age": 25, - "email": "jane@example.com", - "city": "Los Angeles" - } -]`); - } - }; - - return ( - - {/* Mode Toggle */} -
- - -
- - {/* Options */} -
-
- - -
- -
- setHasHeaders(e.target.checked)} - className="rounded border-gray-300 text-primary-600 focus:ring-primary-500" - /> - -
-
- - {/* Controls */} -
- - - - -
- - {/* Input/Output Grid */} -
- {/* Input */} -
- -
-