Add sales automation stack: strategy docs, MCP scripts, PWA refinements
- SALES_STRATEGY.md: $1K/day plan (37 orders @ $27.50 AOV, 1,700 visits) - TRIPWIRE_FUNNEL.md: 7-email Mautic sequence + lead scoring - MONETIZATION.md: 9 monetization options for Nūr PWA (no ads, no registration) - EXECUTABLE_PLAN.md: MCP-executable automation plan - DAILY_OPS.md: daily KPI checklist (visits, orders, sends, recoveries) - scripts/: automation.py, mautic_setup.py, gumroad_setup.py, scout_scrape.py, analytics.py, crontab - quality_leads.json/.csv: 12 enriched Islamic-tech leads for Mautic import - content_queue.json: 10 SEO blog posts for Ghost - PWA: icons, sw.js, e2e + vitest coverage, generator scripts
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
const fs = require('fs');
|
||||
const { createCanvas } = require('canvas');
|
||||
|
||||
// Simple icon generator using canvas
|
||||
function createIcon(size) {
|
||||
const canvas = createCanvas(size, size);
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// Background gradient
|
||||
const gradient = ctx.createLinearGradient(0, 0, size, size);
|
||||
gradient.addColorStop(0, '#0f766e');
|
||||
gradient.addColorStop(1, '#0d9488');
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fillRect(0, 0, size, size);
|
||||
|
||||
// Rounded corners
|
||||
ctx.globalCompositeOperation = 'destination-in';
|
||||
ctx.beginPath();
|
||||
const radius = size * 0.2;
|
||||
ctx.roundRect(0, 0, size, size, radius);
|
||||
ctx.fill();
|
||||
|
||||
// Draw mosque silhouette
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
ctx.fillStyle = 'white';
|
||||
|
||||
const cx = size / 2;
|
||||
const scale = size / 512;
|
||||
|
||||
// Main dome
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, size * 0.45, size * 0.18, Math.PI, 0);
|
||||
ctx.lineTo(cx + size * 0.18, size * 0.65);
|
||||
ctx.lineTo(cx - size * 0.18, size * 0.65);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
// Minaret left
|
||||
ctx.fillRect(cx - size * 0.35, size * 0.35, size * 0.06, size * 0.35);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(cx - size * 0.38, size * 0.35);
|
||||
ctx.lineTo(cx - size * 0.32, size * 0.28);
|
||||
ctx.lineTo(cx - size * 0.26, size * 0.35);
|
||||
ctx.fill();
|
||||
|
||||
// Minaret right
|
||||
ctx.fillRect(cx + size * 0.29, size * 0.35, size * 0.06, size * 0.35);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(cx + size * 0.26, size * 0.35);
|
||||
ctx.lineTo(cx + size * 0.32, size * 0.28);
|
||||
ctx.lineTo(cx + size * 0.38, size * 0.35);
|
||||
ctx.fill();
|
||||
|
||||
// Crescent moon
|
||||
ctx.fillStyle = '#fef3c7';
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, size * 0.22, size * 0.06, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
ctx.globalCompositeOperation = 'destination-out';
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx + size * 0.02, size * 0.22, size * 0.055, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
|
||||
return canvas.toBuffer('image/png');
|
||||
}
|
||||
|
||||
const sizes = [192, 512];
|
||||
sizes.forEach(size => {
|
||||
const png = createIcon(size);
|
||||
fs.writeFileSync(`public/icon-${size}.png`, png);
|
||||
console.log(`Generated icon-${size}.png`);
|
||||
});
|
||||
|
||||
// Also create a favicon.ico equivalent (32x32 PNG for modern browsers)
|
||||
const favicon32 = createIcon(32);
|
||||
fs.writeFileSync('public/favicon-32.png', favicon32);
|
||||
console.log('Generated favicon-32.png');
|
||||
|
||||
// Apple touch icon
|
||||
const appleTouch = createIcon(180);
|
||||
fs.writeFileSync('public/apple-touch-icon.png', appleTouch);
|
||||
console.log('Generated apple-touch-icon.png');
|
||||
Reference in New Issue
Block a user