anhedral 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/CONTRIBUTING.md +4 -0
  3. package/README.md +76 -57
  4. package/SKILL.md +107 -12
  5. package/assets/anhedral-cli-init.svg +238 -0
  6. package/assets/images/svg/ably-symbol-color.svg +8 -0
  7. package/assets/images/svg/logo-white-subtract.svg +4 -0
  8. package/dist/architecture/index.d.ts +2 -2
  9. package/dist/architecture/index.js +1 -1
  10. package/dist/architecture/modules.d.ts +5 -1
  11. package/dist/architecture/modules.js +4 -1
  12. package/dist/bin.js +113 -84
  13. package/dist/cli.d.ts +7 -7
  14. package/dist/cli.js +62 -16
  15. package/dist/dependencies.d.ts +1 -0
  16. package/dist/dependencies.js +11 -8
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.js +1 -1
  19. package/dist/project.d.ts +30 -0
  20. package/dist/project.js +1 -0
  21. package/dist/prompts.d.ts +4 -3
  22. package/dist/prompts.js +29 -7
  23. package/dist/scaffold.d.ts +12 -24
  24. package/dist/scaffold.js +345 -124
  25. package/dist/templates/api.d.ts +1 -1
  26. package/dist/templates/api.js +67 -2
  27. package/dist/templates/assets-private-proxy.d.ts +1 -1
  28. package/dist/templates/desktop.d.ts +1 -1
  29. package/dist/templates/desktop.js +189 -36
  30. package/dist/templates/electron-updater.d.ts +1 -1
  31. package/dist/templates/electron-updater.js +1 -1
  32. package/dist/templates/extension.d.ts +1 -1
  33. package/dist/templates/extension.js +138 -14
  34. package/dist/templates/first-run.d.ts +2 -0
  35. package/dist/templates/first-run.js +167 -0
  36. package/dist/templates/mobile.d.ts +1 -1
  37. package/dist/templates/mobile.js +158 -17
  38. package/dist/templates/shared.d.ts +1 -1
  39. package/dist/templates/shared.js +64 -7
  40. package/dist/templates/web.d.ts +1 -1
  41. package/dist/templates/web.js +185 -28
  42. package/dist/version.d.ts +1 -1
  43. package/dist/version.js +1 -1
  44. package/docs/NORTHSTAR.md +114 -0
  45. package/docs/conventions.md +6 -4
  46. package/docs/engineering-principles.md +88 -0
  47. package/docs/master-stack-map.md +7 -0
  48. package/docs/output-tree-contract.md +16 -5
  49. package/docs/references/manual-scaffolding.md +22 -4
  50. package/docs/references/provisioning.md +434 -77
  51. package/package.json +10 -2
  52. package/scripts/render-master-stack-map.mjs +510 -0
@@ -0,0 +1,238 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1180" viewBox="0 0 1920 1180" role="img" aria-labelledby="title description">
2
+ <title id="title">Anhedral Init Stack</title>
3
+ <desc id="description">A simplified architecture diagram showing DX tools, deployment destinations, four generated client surfaces, their shared Fastify API, RevenueCat and Stripe billing, Ably realtime, backend services, and a dedicated private R2 updater Worker.</desc>
4
+ <defs>
5
+ <linearGradient id="card-fill" x1="0" y1="0" x2="1" y2="1">
6
+ <stop offset="0" stop-color="#0d1b29"/>
7
+ <stop offset="1" stop-color="#07121d"/>
8
+ </linearGradient>
9
+ <linearGradient id="app-store-fill" x1="0" y1="0" x2="0" y2="1">
10
+ <stop offset="0" stop-color="#24c7fa"/>
11
+ <stop offset="1" stop-color="#0878f9"/>
12
+ </linearGradient>
13
+ <filter id="endpoint-glow" x="-100%" y="-100%" width="300%" height="300%">
14
+ <feGaussianBlur in="SourceGraphic" stdDeviation="1.7"/>
15
+ </filter>
16
+ <marker id="arrow-white" markerWidth="9" markerHeight="9" refX="8" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#f7f5f0"/></marker>
17
+ <marker id="arrow-yellow" markerWidth="9" markerHeight="9" refX="8" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 Z" fill="#e9f600"/></marker>
18
+ </defs>
19
+ <rect width="1920" height="1180" fill="#0c1117"/>
20
+ <g transform="translate(28 34) scale(0.0263756252842201)">
21
+ <path d="M1604.59 26.7414C1694.33 -39.6752 1821.31 25.3379 1819.89 136.971L1809.28 971.026C1774.28 969.39 1738.87 969.434 1703.15 971.237C1334.16 989.855 1017.8 1191.61 837.641 1484.06L122.496 1416.65C-0.793297 1405.03 -44.6847 1247.41 54.8543 1173.73L1604.59 26.7414Z" fill="#f7f5f0"/>
22
+ <path d="M1795.36 2064.84C1793.79 2188.66 1640.25 2245.21 1558.74 2151.98L1083.84 1608.79C1214.01 1305.09 1479.98 1071.11 1809.07 987.262L1795.36 2064.84Z" fill="#f7f5f0"/>
23
+ </g>
24
+ <path d="M 93.00363801728058 26 L 93.00363801728058 104" fill="none" stroke="#73777b" stroke-width="1.5" stroke-linecap="round"/>
25
+ <text x="115.00363801728058" y="80" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="27" font-weight="500" text-anchor="start" letter-spacing="1.3">ANHEDRAL</text>
26
+ <text x="32" y="176" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="78" font-weight="700" text-anchor="start" letter-spacing="0">Anhedral</text>
27
+ <path d="M 33 195 L 366 195" fill="none" stroke="#e9f600" stroke-width="6" stroke-linecap="round"/>
28
+ <text x="392" y="176" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="78" font-weight="700" text-anchor="start" letter-spacing="0">Init</text>
29
+ <path d="M 393 195 L 506 195" fill="none" stroke="#e9f600" stroke-width="6" stroke-linecap="round"/>
30
+ <text x="532" y="176" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="78" font-weight="700" text-anchor="start" letter-spacing="0">Stack</text>
31
+ <path d="M 533 195 L 747 195" fill="none" stroke="#e9f600" stroke-width="6" stroke-linecap="round"/>
32
+ <text x="34" y="240" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="24" font-weight="400" text-anchor="start" letter-spacing="0">One init flow for web, native apps, extensions, backend,</text>
33
+ <text x="34" y="274" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="24" font-weight="400" text-anchor="start" letter-spacing="0">storage, auth, subscriptions, and seamless desktop updates.</text>
34
+ <text x="1525" y="52" fill="#e9f600" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="17" font-weight="600" text-anchor="middle" letter-spacing="3.2">DX TOOLS</text>
35
+ <rect x="1187" y="76" width="88" height="92" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
36
+ <g transform="translate(1214 90) scale(1.4166666666666667)"><path d="M12.001,4.8c-3.2,0-5.2,1.6-6,4.8c1.2-1.6,2.6-2.2,4.2-1.8c0.913,0.228,1.565,0.89,2.288,1.624 C13.666,10.618,15.027,12,18.001,12c3.2,0,5.2-1.6,6-4.8c-1.2,1.6-2.6,2.2-4.2,1.8c-0.913-0.228-1.565-0.89-2.288-1.624 C16.337,6.182,14.976,4.8,12.001,4.8z M6.001,12c-3.2,0-5.2,1.6-6,4.8c1.2-1.6,2.6-2.2,4.2-1.8c0.913,0.228,1.565,0.89,2.288,1.624 c1.177,1.194,2.538,2.576,5.512,2.576c3.2,0,5.2-1.6,6-4.8c-1.2,1.6-2.6,2.2-4.2,1.8c-0.913-0.228-1.565-0.89-2.288-1.624 C10.337,13.382,8.976,12,6.001,12z" fill="#06b6d4"/></g>
37
+ <text x="1231" y="148" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="11" font-weight="500" text-anchor="middle" letter-spacing="0">Tailwind</text>
38
+ <rect x="1285" y="76" width="88" height="92" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
39
+ <g transform="translate(1312 90) scale(1.4166666666666667)"><path d="M22.219 11.784 11.784 22.219c-.407.407-.407 1.068 0 1.476.407.407 1.068.407 1.476 0L23.695 13.26c.407-.408.407-1.069 0-1.476-.408-.407-1.069-.407-1.476 0ZM20.132.305.305 20.132c-.407.407-.407 1.068 0 1.476.408.407 1.069.407 1.476 0L21.608 1.781c.407-.407.407-1.068 0-1.476-.408-.407-1.069-.407-1.476 0Z" fill="#f7f5f0"/></g>
40
+ <text x="1329" y="148" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="11" font-weight="500" text-anchor="middle" letter-spacing="0">shadcn/ui</text>
41
+ <rect x="1383" y="76" width="88" height="92" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
42
+ <g transform="translate(1410 90) scale(1.4166666666666667)"><path d="M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z" fill="#61dafb"/></g>
43
+ <text x="1427" y="148" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="11" font-weight="500" text-anchor="middle" letter-spacing="0">RN Reusables</text>
44
+ <rect x="1481" y="76" width="88" height="92" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
45
+ <g transform="translate(1508 90) scale(1.4166666666666667)"><path d="M1.125 0C.502 0 0 .502 0 1.125v21.75C0 23.498.502 24 1.125 24h21.75c.623 0 1.125-.502 1.125-1.125V1.125C24 .502 23.498 0 22.875 0zm17.363 9.75c.612 0 1.154.037 1.627.111a6.38 6.38 0 0 1 1.306.34v2.458a3.95 3.95 0 0 0-.643-.361 5.093 5.093 0 0 0-.717-.26 5.453 5.453 0 0 0-1.426-.2c-.3 0-.573.028-.819.086a2.1 2.1 0 0 0-.623.242c-.17.104-.3.229-.393.374a.888.888 0 0 0-.14.49c0 .196.053.373.156.529.104.156.252.304.443.444s.423.276.696.41c.273.135.582.274.926.416.47.197.892.407 1.266.628.374.222.695.473.963.753.268.279.472.598.614.957.142.359.214.776.214 1.253 0 .657-.125 1.21-.373 1.656a3.033 3.033 0 0 1-1.012 1.085 4.38 4.38 0 0 1-1.487.596c-.566.12-1.163.18-1.79.18a9.916 9.916 0 0 1-1.84-.164 5.544 5.544 0 0 1-1.512-.493v-2.63a5.033 5.033 0 0 0 3.237 1.2c.333 0 .624-.03.872-.09.249-.06.456-.144.623-.25.166-.108.29-.234.373-.38a1.023 1.023 0 0 0-.074-1.089 2.12 2.12 0 0 0-.537-.5 5.597 5.597 0 0 0-.807-.444 27.72 27.72 0 0 0-1.007-.436c-.918-.383-1.602-.852-2.053-1.405-.45-.553-.676-1.222-.676-2.005 0-.614.123-1.141.369-1.582.246-.441.58-.804 1.004-1.089a4.494 4.494 0 0 1 1.47-.629 7.536 7.536 0 0 1 1.77-.201zm-15.113.188h9.563v2.166H9.506v9.646H6.789v-9.646H3.375z" fill="#3178c6"/></g>
46
+ <text x="1525" y="148" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="11" font-weight="500" text-anchor="middle" letter-spacing="0">TypeScript</text>
47
+ <rect x="1579" y="76" width="88" height="92" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
48
+ <g transform="translate(1606 90) scale(1.4166666666666667)"><path d="M2.584 3.582a2.247 2.247 0 0 1 2.112-1.479h14.617c.948 0 1.794.595 2.115 1.487l2.44 6.777a2.248 2.248 0 0 1-.624 2.443l-9.61 8.52a2.247 2.247 0 0 1-2.963.018L.776 12.773a2.248 2.248 0 0 1-.64-2.467Zm12.038 4.887-9.11 5.537 5.74 5.007c.456.399 1.139.396 1.593-.006l5.643-5.001H14.4l6.239-3.957c.488-.328.69-.947.491-1.5l-1.24-3.446a1.535 1.535 0 0 0-1.456-1.015H5.545a1.535 1.535 0 0 0-1.431 1.01l-1.228 3.37z" fill="#3e67b1"/></g>
49
+ <text x="1623" y="148" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="11" font-weight="500" text-anchor="middle" letter-spacing="0">Zod</text>
50
+ <rect x="1677" y="76" width="88" height="92" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
51
+ <g transform="translate(1704 90) scale(1.4166666666666667)"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" fill="#f7f5f0"/></g>
52
+ <text x="1721" y="148" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="11" font-weight="500" text-anchor="middle" letter-spacing="0">GitHub</text>
53
+ <rect x="1775" y="76" width="88" height="92" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
54
+ <g transform="translate(1804.9299681673488 90) scale(0.015461573442473852)">
55
+ <path d="M1604.59 26.7414C1694.33 -39.6752 1821.31 25.3379 1819.89 136.971L1809.28 971.026C1774.28 969.39 1738.87 969.434 1703.15 971.237C1334.16 989.855 1017.8 1191.61 837.641 1484.06L122.496 1416.65C-0.793297 1405.03 -44.6847 1247.41 54.8543 1173.73L1604.59 26.7414Z" fill="#f7f5f0"/>
56
+ <path d="M1795.36 2064.84C1793.79 2188.66 1640.25 2245.21 1558.74 2151.98L1083.84 1608.79C1214.01 1305.09 1479.98 1071.11 1809.07 987.262L1795.36 2064.84Z" fill="#f7f5f0"/>
57
+ </g>
58
+ <text x="1819" y="148" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="11" font-weight="500" text-anchor="middle" letter-spacing="0">Anhedral Skills</text>
59
+ <text x="252" y="318" fill="#e9f600" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="17" font-weight="600" text-anchor="middle" letter-spacing="3.2">DEPLOY &amp; DISTRIBUTE</text>
60
+ <text x="805" y="318" fill="#e9f600" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="17" font-weight="600" text-anchor="middle" letter-spacing="3.2">CLIENT SURFACES</text>
61
+ <text x="1497.5" y="318" fill="#e9f600" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="17" font-weight="600" text-anchor="middle" letter-spacing="3.2">BACKEND + SERVICES</text>
62
+ <rect x="54" y="342" width="396" height="102" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
63
+ <rect x="70" y="354" width="78" height="78" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
64
+ <g fill="none" stroke="#f7f5f0" stroke-width="3">
65
+ <circle cx="109" cy="393" r="26.520000000000003"/>
66
+ <ellipse cx="109" cy="393" rx="11.934000000000001" ry="26.520000000000003"/>
67
+ <path d="M 82.47999999999999 393 H 135.52 M 86.72319999999999 379.74 H 131.2768 M 86.72319999999999 406.26 H 131.2768"/>
68
+ </g>
69
+ <path d="M 158 356 L 158 430" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
70
+ <text x="182" y="384" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="22" font-weight="500" text-anchor="start" letter-spacing="0">Web</text>
71
+ <text x="182" y="412" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="16" font-weight="400" text-anchor="start" letter-spacing="0">Vercel preview + production</text>
72
+ <text x="182" y="433" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="13" font-weight="400" text-anchor="start" letter-spacing="0">hosts web + API</text>
73
+ <rect x="54" y="456" width="396" height="102" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
74
+ <rect x="70" y="468" width="78" height="78" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
75
+ <rect x="78" y="476" width="62" height="62" rx="11" fill="url(#app-store-fill)"/>
76
+ <g transform="translate(87 485) scale(1.8333333333333333)"><path d="M8.8086 14.9194l6.1107-11.0368c.0837-.1513.1682-.302.2437-.4584.0685-.142.1267-.2854.1646-.4403.0803-.3259.0588-.6656-.066-.9767-.1238-.3095-.3417-.5678-.6201-.7355a1.4175 1.4175 0 0 0-.921-.1924c-.3207.043-.6135.1935-.8443.4288-.1094.1118-.1996.2361-.2832.369-.092.1463-.175.2979-.259.4492l-.3864.6979-.3865-.6979c-.0837-.1515-.1667-.303-.2587-.4492-.0837-.1329-.1739-.2572-.2835-.369-.2305-.2353-.5233-.3857-.844-.429a1.4181 1.4181 0 0 0-.921.1926c-.2784.1677-.4964.426-.6203.7355-.1246.311-.1461.6508-.066.9767.038.155.0962.2984.1648.4403.0753.1564.1598.307.2437.4584l1.248 2.2543-4.8625 8.7825H2.0295c-.1676 0-.3351-.0007-.5026.0092-.1522.009-.3004.0284-.448.0714-.3108.0906-.5822.2798-.7783.548-.195.2665-.3006.5929-.3006.9279 0 .3352.1057.6612.3006.9277.196.2683.4675.4575.7782.548.1477.043.296.0623.4481.0715.1675.01.335.009.5026.009h13.0974c.0171-.0357.059-.1294.1-.2697.415-1.4151-.6156-2.843-2.0347-2.843zM3.113 18.5418l-.7922 1.5008c-.0818.1553-.1644.31-.2384.4705-.067.1458-.124.293-.1611.452-.0785.3346-.0576.6834.0645 1.0029.1212.3175.3346.583.607.7549.2727.172.5891.2416.9013.1975.3139-.044.6005-.1986.8263-.4402.1072-.1148.1954-.2424.2772-.3787.0902-.1503.1714-.3059.2535-.4612L6 19.4636c-.0896-.149-.9473-1.4704-2.887-.9218m20.5861-3.0056a1.4707 1.4707 0 0 0-.779-.5407c-.1476-.0425-.2961-.0616-.4483-.0705-.1678-.0099-.3352-.0091-.503-.0091H18.648l-4.3891-7.817c-.6655.7005-.9632 1.485-1.0773 2.1976-.1655 1.0333.0367 2.0934.546 3.0004l5.2741 9.3933c.084.1494.167.299.2591.4435.0837.131.1739.2537.2836.364.231.2323.5238.3809.8449.4232.3192.0424.643-.0244.9217-.1899.2784-.1653.4968-.4204.621-.7257.1246-.3072.146-.6425.0658-.9641-.0381-.1529-.0962-.2945-.165-.4346-.0753-.1543-.1598-.303-.2438-.4524l-1.216-2.1662h1.596c.1677 0 .3351.0009.5029-.009.1522-.009.3007-.028.4483-.0705a1.4707 1.4707 0 0 0 .779-.5407A1.5386 1.5386 0 0 0 24 16.452a1.539 1.539 0 0 0-.3009-.9158Z" fill="#f7f5f0"/></g>
77
+ <path d="M 158 470 L 158 544" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
78
+ <text x="182" y="498" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="22" font-weight="500" text-anchor="start" letter-spacing="0">App Store</text>
79
+ <text x="182" y="526" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="16" font-weight="400" text-anchor="start" letter-spacing="0">iOS distribution</text>
80
+ <text x="182" y="547" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="13" font-weight="400" text-anchor="start" letter-spacing="0">EAS signed release</text>
81
+ <rect x="54" y="570" width="396" height="102" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
82
+ <rect x="70" y="582" width="78" height="78" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
83
+ <g transform="translate(74 586) scale(1.09375)" stroke-linejoin="round">
84
+ <path d="M 9 6 L 39 32 L 9 58 Z" fill="#23d7f2"/>
85
+ <path d="M 9 6 L 44 24.5 L 39 32 Z" fill="#2bd66f"/>
86
+ <path d="M 39 32 L 44 24.5 L 56 30.5 Q 59 32 56 33.5 L 44 39.5 Z" fill="#ffd43b"/>
87
+ <path d="M 9 58 L 44 39.5 L 39 32 Z" fill="#f04b55"/>
88
+ </g>
89
+ <path d="M 158 584 L 158 658" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
90
+ <text x="182" y="612" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="22" font-weight="500" text-anchor="start" letter-spacing="0">Google Play</text>
91
+ <text x="182" y="640" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="16" font-weight="400" text-anchor="start" letter-spacing="0">Android distribution</text>
92
+ <text x="182" y="661" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="13" font-weight="400" text-anchor="start" letter-spacing="0">EAS signed release</text>
93
+ <rect x="54" y="684" width="396" height="102" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
94
+ <rect x="70" y="696" width="78" height="78" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
95
+ <rect x="75" y="701" width="68" height="68" rx="11" fill="#f7f5f0"/>
96
+ <path d="M 109 735 L 96.76 713.7996981153569 A 24.48 24.48 0 0 1 133.48 735 Z" fill="#ea4335"/>
97
+ <path d="M 109 735 L 133.48 735 A 24.48 24.48 0 0 1 96.76 756.2003018846431 Z" fill="#fbbc04"/>
98
+ <path d="M 109 735 L 96.76 756.2003018846431 A 24.48 24.48 0 0 1 96.76 713.7996981153569 Z" fill="#34a853"/>
99
+ <circle cx="109" cy="735" r="11.750399999999999" fill="#f7f5f0"/>
100
+ <circle cx="109" cy="735" r="8.8128" fill="#4285f4"/>
101
+ <path d="M 158 698 L 158 772" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
102
+ <text x="182" y="726" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="22" font-weight="500" text-anchor="start" letter-spacing="0">Browser Web Stores</text>
103
+ <text x="182" y="754" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="16" font-weight="400" text-anchor="start" letter-spacing="0">extension distribution</text>
104
+ <text x="182" y="775" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="13" font-weight="400" text-anchor="start" letter-spacing="0">reviewed WXT ZIP</text>
105
+ <rect x="54" y="798" width="396" height="102" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
106
+ <rect x="70" y="810" width="78" height="78" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
107
+ <g fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
108
+ <rect x="79" y="819" width="60" height="51" rx="3"/>
109
+ <path d="M 109 870 V 880 M 91.84 880 H 126.16"/>
110
+ </g>
111
+ <path d="M 158 812 L 158 886" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
112
+ <text x="182" y="840" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="22" font-weight="500" text-anchor="start" letter-spacing="0">Desktop Releases</text>
113
+ <text x="182" y="868" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="16" font-weight="400" text-anchor="start" letter-spacing="0">macOS · Windows · Linux</text>
114
+ <text x="182" y="889" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="13" font-weight="400" text-anchor="start" letter-spacing="0">signed installers + seamless updates</text>
115
+ <rect x="620" y="342" width="370" height="112" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
116
+ <rect x="636" y="354" width="88" height="88" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
117
+ <g transform="translate(651 369) scale(2.4166666666666665)"><path d="M18.665 21.978C16.758 23.255 14.465 24 12 24 5.377 24 0 18.623 0 12S5.377 0 12 0s12 5.377 12 12c0 3.583-1.574 6.801-4.067 9.001L9.219 7.2H7.2v9.596h1.615V9.251l9.85 12.727Zm-3.332-8.533 1.6 2.061V7.2h-1.6v6.245Z" fill="#f7f5f0"/></g>
118
+ <path d="M 734 356 L 734 440" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
119
+ <text x="758" y="384" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="22" font-weight="500" text-anchor="start" letter-spacing="0">Next.js</text>
120
+ <text x="758" y="412" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="16" font-weight="400" text-anchor="start" letter-spacing="0">shadcn/ui</text>
121
+ <text x="758" y="433" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="13" font-weight="400" text-anchor="start" letter-spacing="0">web product + server routes</text>
122
+ <g transform="translate(958 357) scale(0.7083333333333334)"><path d="m12 1.608 12 20.784H0Z" fill="#f7f5f0"/></g>
123
+ <rect x="620" y="494" width="370" height="112" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
124
+ <rect x="636" y="506" width="88" height="88" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
125
+ <g transform="translate(651 521) scale(2.4166666666666665)"><path d="M0 20.084c.043.53.23 1.063.718 1.778.58.849 1.576 1.315 2.303.567.49-.505 5.794-9.776 8.35-13.29a.761.761 0 011.248 0c2.556 3.514 7.86 12.785 8.35 13.29.727.748 1.723.282 2.303-.567.57-.835.728-1.42.728-2.046 0-.426-8.26-15.798-9.092-17.078-.8-1.23-1.044-1.498-2.397-1.542h-1.032c-1.353.044-1.597.311-2.398 1.542C8.267 3.991.33 18.758 0 19.77Z" fill="#f7f5f0"/></g>
126
+ <path d="M 734 508 L 734 592" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
127
+ <text x="758" y="536" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="22" font-weight="500" text-anchor="start" letter-spacing="0">Expo Native</text>
128
+ <text x="758" y="564" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="16" font-weight="400" text-anchor="start" letter-spacing="0">React Native Reusables</text>
129
+ <text x="758" y="585" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="13" font-weight="400" text-anchor="start" letter-spacing="0">iOS + Android</text>
130
+ <rect x="620" y="646" width="370" height="112" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
131
+ <rect x="636" y="658" width="88" height="88" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
132
+ <g transform="translate(651 673) scale(2.4166666666666665)"><path d="M10.18 0c-2.081 0-3.807 1.608-4 3.64H4.019A4.033 4.033 0 0 0 0 7.66v4.017h1.498a2.13 2.13 0 0 1 2.143 2.144 2.13 2.13 0 0 1-2.143 2.143H0V24h8.036v-1.498a2.13 2.13 0 0 1 2.144-2.143 2.13 2.13 0 0 1 2.143 2.143V24h4.018a4.03 4.03 0 0 0 4.018-4.018v-2.163C22.392 17.627 24 15.901 24 13.821s-1.608-3.807-3.64-4V7.66a4.03 4.03 0 0 0-4.019-4.018h-2.162C13.986 1.608 12.26 0 10.179 0m0 1.875a2.13 2.13 0 0 1 2.143 2.143v1.498h4.018a2.13 2.13 0 0 1 2.143 2.143v4.018h1.498a2.13 2.13 0 0 1 2.143 2.144 2.13 2.13 0 0 1-2.143 2.143h-1.498v4.018a2.13 2.13 0 0 1-2.143 2.143h-2.162c-.193-2.033-1.919-3.64-4-3.64s-3.806 1.607-3.998 3.64H1.875V17.82c2.033-.192 3.64-1.918 3.64-3.998s-1.607-3.807-3.64-4V7.66a2.13 2.13 0 0 1 2.143-2.143h4.018V4.018a2.13 2.13 0 0 1 2.144-2.143" fill="#b9f500"/></g>
133
+ <path d="M 734 660 L 734 744" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
134
+ <text x="758" y="688" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="22" font-weight="500" text-anchor="start" letter-spacing="0">WXT Extension</text>
135
+ <text x="758" y="716" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="16" font-weight="400" text-anchor="start" letter-spacing="0">Chrome · Firefox · Edge</text>
136
+ <text x="758" y="737" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="13" font-weight="400" text-anchor="start" letter-spacing="0">MV3 background + side panel</text>
137
+ <rect x="620" y="798" width="370" height="112" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
138
+ <rect x="636" y="810" width="88" height="88" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
139
+ <g transform="translate(651 825) scale(2.4166666666666665)"><path d="M12.0111 0c-.85 0-1.5392.6891-1.5392 1.5392 0 .8501.6891 1.5393 1.5392 1.5393.595 0 1.11-.338 1.3662-.832 2.2208 1.2675 3.847 5.4728 3.847 10.3623 0 2.0715-.2891 4.056-.825 5.7685a.3215.3215 0 0 0 .2107.403.322.322 0 0 0 .4033-.2111c.5558-1.7763.8542-3.8251.8542-5.9604 0-5.1927-1.7717-9.686-4.3206-11.0027.001-.0223.0035-.0443.0035-.0669 0-.85-.6891-1.5392-1.5393-1.5392zm0 .6432a.896.896 0 1 1 0 1.792.896.896 0 1 1 0-1.792zm-5.486 4.3052c-2.067.0074-3.6473.6646-4.3885 1.9485-.7375 1.2774-.5267 2.971.5113 4.7813a.3217.3217 0 0 0 .558-.32C2.271 9.7274 2.089 8.266 2.6938 7.2185c.821-1.422 3.033-1.9552 5.9321-1.4271a.3216.3216 0 0 0 .1153-.6329c-.784-.1428-1.5271-.2125-2.216-.21zm11.0522.0176a.3216.3216 0 0 0-.0084.6432c1.8337.0239 3.1556.5956 3.7502 1.6256.8192 1.419.1798 3.5947-1.7182 5.837a.322.322 0 0 0 .0377.4535.3215.3215 0 0 0 .4532-.0377c2.0535-2.426 2.7708-4.8661 1.7845-6.5744-.7257-1.257-2.26-1.9207-4.299-1.9472zm-2.6984.2924a.3225.3225 0 0 0-.0647.0072c-1.8568.3979-3.8333 1.1755-5.7314 2.2714-4.5699 2.6384-7.5924 6.4948-7.3601 9.3717-.4726.2628-.7928.7664-.7928 1.3455 0 .85.6892 1.5392 1.5393 1.5392.85 0 1.5392-.6891 1.5392-1.5392 0-.8501-.6891-1.5393-1.5392-1.5393-.038 0-.0754.003-.1128.0057-.1002-2.5597 2.7434-6.1412 7.048-8.6265 1.8413-1.063 3.7551-1.8163 5.5445-2.1997a.3217.3217 0 0 0-.07-.636zm-2.8787 6.2364a1.1192 1.1192 0 0 0-.2243.0255c-.6012.1301-.983.7225-.8533 1.3238.1302.6012.7226.9832 1.3238.8533.6012-.1302.9832-.7226.8533-1.3238-.1139-.526-.5816-.8844-1.0995-.8788zM4.532 13.341a.321.321 0 0 0-.2318.0835.3214.3214 0 0 0-.0214.4542c1.2682 1.3936 2.9157 2.701 4.7946 3.7857 4.4146 2.5489 9.1056 3.2849 11.5608 1.8392a1.53 1.53 0 0 0 .8966.2899c.8501 0 1.5392-.6891 1.5392-1.5392 0-.8501-.689-1.5393-1.5392-1.5393-.85 0-1.5392.6892-1.5392 1.5393 0 .276.0737.5344.201.7584-2.2448 1.214-6.631.5002-10.7976-1.9054-1.8228-1.0524-3.418-2.3181-4.6404-3.6614a.3206.3206 0 0 0-.2226-.1049zm-2.0628 4.0172a.896.896 0 1 1 0 1.792.896.896 0 1 1 0-1.792zm19.0616 0a.896.896 0 1 1 0 1.792.891.891 0 0 1-.5864-.2194c-.0025-.004-.0039-.0083-.0066-.0123a.3195.3195 0 0 0-.0957-.0914.896.896 0 0 1 .6887-1.4689zm-14.0045 1.368a.3215.3215 0 0 0-.3207.4296C8.2793 22.154 10.036 24 12.0111 24c1.4406 0 2.7735-.9822 3.8128-2.711a.3215.3215 0 0 0-.11-.4413.3219.3219 0 0 0-.4415.11c-.934 1.5537-2.0812 2.399-3.2613 2.399-1.6407 0-3.2075-1.6465-4.2-4.4179a.3216.3216 0 0 0-.2848-.2126z" fill="#51dce9"/></g>
140
+ <path d="M 734 812 L 734 896" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
141
+ <text x="758" y="840" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="22" font-weight="500" text-anchor="start" letter-spacing="0">Electron Desktop</text>
142
+ <text x="758" y="868" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="16" font-weight="400" text-anchor="start" letter-spacing="0">macOS · Windows · Linux</text>
143
+ <text x="758" y="889" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="13" font-weight="400" text-anchor="start" letter-spacing="0">electron-updater enabled</text>
144
+ <rect x="1130" y="474" width="208" height="296" rx="14" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
145
+ <rect x="1190" y="490" width="88" height="88" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
146
+ <g transform="translate(1200 500) scale(2.8333333333333335)"><path d="M23.245 6.49L24 4.533l-.031-.121-7.473 1.967c.797-1.153.523-2.078.523-2.078s-2.387 1.524-4.193 1.485c-1.804-.04-2.387-.52-5.155.362-2.768.882-3.551 3.59-4.351 4.173-.804.583-3.32 2.477-3.32 2.477l.006.034 2.27-.724s-.622.585-1.945 2.37l-.062-.057.002.011s1.064 1.626 2.107 1.324a2.14 2.14 0 0 0 .353-.147c.419.234.967.463 1.572.525 0 0-.41-.475-.752-1.017l.238-.154.865.318-.096-.812c.003-.003.006-.003.008-.006l.849.311-.105-.738a5.65 5.65 0 0 1 .322-.158l.885-3.345 3.662-2.497-.291.733c-.741 1.826-2.135 2.256-2.135 2.256l-.582.22c-.433.512-.614.637-.764 2.353.348-.088.682-.107.984-.028 1.564.421 2.107 2.307 1.685 2.827-.104.13-.356.354-.673.617H7.77l-.008.514-.065.051h-.645l-.009.504-.17.127c-.607.011-1.373-.518-1.373-.518 0 .481.401 1.225.401 1.225l.07-.034-.061.045s1.625 1.083 2.646.681c.91-.356 3.263-2.213 5.296-3.093l6.15-1.62.811-2.1-4.688 1.235v-1.889l5.5-1.448.811-2.1-6.31 1.662V8.367zm-11.163 4l1.459-.384.02.074-.455 1.179-1.513.398zm.503 2.526l-1.512.398.489-1.266 1.459-.385.02.074zm1.971-.424l-1.513.398.49-1.266 1.459-.385.02.073Z" fill="#f7f5f0"/></g>
147
+ <g transform="translate(1306 490) scale(0.7083333333333334)"><path d="m12 1.608 12 20.784H0Z" fill="#f7f5f0"/></g>
148
+ <path d="M 1148 602 L 1320 602" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
149
+ <text x="1234" y="643" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="25" font-weight="500" text-anchor="middle" letter-spacing="0">Fastify Backend</text>
150
+ <text x="1234" y="675" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="17" font-weight="400" text-anchor="middle" letter-spacing="0">API + business logic</text>
151
+ <rect x="1435" y="342" width="430" height="88" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
152
+ <rect x="1451" y="354" width="64" height="64" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
153
+ <g transform="translate(1456 373) scale(1.0833333333333333)"><path d="M24 0V24l-9.365-8.045V24H0V0ZM2.942 21.087h8.751V9.563l9.365 8.204V2.919L2.942 2.914Z" fill="#35d6a8"/></g>
154
+ <g transform="translate(1484 373) scale(1.0833333333333333)"><path d="M5.353 11.823a1.036 1.036 0 0 0-.395-1.422 1.063 1.063 0 0 0-1.437.399L.138 16.702a1.035 1.035 0 0 0 .395 1.422 1.063 1.063 0 0 0 1.437-.398l3.383-5.903Zm11.216 0a1.036 1.036 0 0 0-.394-1.422 1.064 1.064 0 0 0-1.438.399l-3.382 5.902a1.036 1.036 0 0 0 .394 1.422c.506.283 1.15.104 1.438-.398l3.382-5.903Zm7.293-4.525a1.036 1.036 0 0 0-.395-1.422 1.062 1.062 0 0 0-1.437.399l-3.383 5.902a1.036 1.036 0 0 0 .395 1.422 1.063 1.063 0 0 0 1.437-.399l3.383-5.902Zm-11.219 0a1.035 1.035 0 0 0-.394-1.422 1.064 1.064 0 0 0-1.438.398l-3.382 5.903a1.036 1.036 0 0 0 .394 1.422c.506.282 1.15.104 1.438-.399l3.382-5.902Z" fill="#e9f600"/></g>
155
+ <path d="M 1527 356 L 1527 416" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
156
+ <text x="1547" y="373" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="18" font-weight="500" text-anchor="start" letter-spacing="0">Neon + Drizzle</text>
157
+ <text x="1547" y="397" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="14" font-weight="400" text-anchor="start" letter-spacing="0">Postgres + ORM</text>
158
+ <text x="1547" y="417" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="12" font-weight="400" text-anchor="start" letter-spacing="0">reviewed migrations</text>
159
+ <rect x="1435" y="438" width="430" height="88" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
160
+ <rect x="1451" y="450" width="64" height="64" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
161
+ <g transform="translate(1455 454) scale(2.3333333333333335)"><path d="m21.47 20.829-2.881-2.881a.572.572 0 0 0-.7-.084 6.854 6.854 0 0 1-7.081 0 .576.576 0 0 0-.7.084l-2.881 2.881a.576.576 0 0 0-.103.69.57.57 0 0 0 .166.186 12 12 0 0 0 14.113 0 .58.58 0 0 0 .239-.423.576.576 0 0 0-.172-.453Zm.002-17.668-2.88 2.88a.569.569 0 0 1-.701.084A6.857 6.857 0 0 0 8.724 8.08a6.862 6.862 0 0 0-1.222 3.692 6.86 6.86 0 0 0 .978 3.764.573.573 0 0 1-.083.699l-2.881 2.88a.567.567 0 0 1-.864-.063A11.993 11.993 0 0 1 6.771 2.7a11.99 11.99 0 0 1 14.637-.405.566.566 0 0 1 .232.418.57.57 0 0 1-.168.448Zm-7.118 12.261a3.427 3.427 0 1 0 0-6.854 3.427 3.427 0 0 0 0 6.854Z" fill="#f7f5f0"/></g>
162
+ <path d="M 1527 452 L 1527 512" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
163
+ <text x="1547" y="469" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="18" font-weight="500" text-anchor="start" letter-spacing="0">Clerk Auth</text>
164
+ <text x="1547" y="493" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="14" font-weight="400" text-anchor="start" letter-spacing="0">identity + sessions</text>
165
+ <text x="1547" y="513" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="12" font-weight="400" text-anchor="start" letter-spacing="0">verified server-side</text>
166
+ <rect x="1435" y="534" width="430" height="88" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
167
+ <rect x="1451" y="546" width="64" height="64" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
168
+ <g transform="translate(1456 565) scale(1.0833333333333333)"><path d="M4.3036.3999c-1.5246 0-3.2129.1508-4.303.4136v14.9997c.3083.1722.8432.28 1.5632.28.7404 0 1.2553-.1072 1.5433-.28v-5.2323a14.8588 14.8588 0 0 0 2.121.1512h.3294l2.8604 5.0588c.432.195 1.0288.3024 1.9348.3024.8033 0 1.38-.1104 1.6476-.3024l-3.437-5.8358c1.4195-.8004 2.326-2.2698 2.326-4.4964C10.8894 1.827 8.4232.4 4.3037.4zm15.4543 0c-1.3788 0-2.624.2707-3.6901.7945-2.4552 1.203-3.9609 3.7376-3.9609 7.3627 0 4.8245 2.6552 7.7155 7.1659 7.7155.9 0 1.5868-.3014 2.005.2554.4194.5568-.3582 1.2165-.7746 1.5105-1.6338 1.1544-5.7217-.1024-9.4908-.4804C5.5994 17.015.9264 16.3009.146 19.1928c-.4104 1.5264.1225 2.5013.6421 3.0503 1.044 1.1046 2.882 1.357 4.344 1.357a13.959 13.959 0 0 0 2.0508-.1558 1.311 1.311 0 0 0 1.023-.8063c.1674-.4254.0861-.904-.212-1.2562a1.3464 1.3464 0 0 0-1.2352-.4523c-1.5012.2706-3.6213.8685-4.4343.0105-.2748-.291-.2268-1.0037 0-1.2257.6048-.8748 4.493-.5393 8.4127-.0293 4.329.4344 8.4023 1.8609 10.945.6351.9955-.48 2.318-1.1941 2.318-3.792h-.0012c0-1.1473-.1489-2.274-.4476-3.3797-1.3818.1872-2.4783.2857-3.2883.2941-2.845 0-4.869-1.4484-4.869-5.0963 0-3.648 2.0461-5.1573 5.0179-5.1573 1.2011 0 2.129.2512 3.1405.7336.1062-.9234-.1058-2.1605-.5906-2.8523-.78-.4608-2.0014-.6703-3.2038-.6703zM4.51 3.1889c2.0579 0 3.2108.7111 3.2108 2.4421 0 1.6824-1.0912 2.3554-2.8816 2.3554a10.2838 10.2838 0 0 1-1.7706-.1511V3.3166a7.7782 7.7782 0 0 1 1.4413-.1277z" fill="#ff3b3f"/></g>
169
+ <g transform="translate(1484 565) scale(1.0833333333333333)"><path d="M13.976 9.15c-2.172-.806-3.356-1.426-3.356-2.409 0-.831.683-1.305 1.901-1.305 2.227 0 4.515.858 6.09 1.631l.89-5.494C18.252.975 15.697 0 12.165 0 9.667 0 7.589.654 6.104 1.872 4.56 3.147 3.757 4.992 3.757 7.218c0 4.039 2.467 5.76 6.476 7.219 2.585.92 3.445 1.574 3.445 2.583 0 .98-.84 1.545-2.354 1.545-1.875 0-4.965-.921-6.99-2.109l-.9 5.555C5.175 22.99 8.385 24 11.714 24c2.641 0 4.843-.624 6.328-1.813 1.664-1.305 2.525-3.236 2.525-5.732 0-4.128-2.524-5.851-6.594-7.305h.003z" fill="#635bff"/></g>
170
+ <path d="M 1527 548 L 1527 608" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
171
+ <text x="1547" y="565" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="18" font-weight="500" text-anchor="start" letter-spacing="0">RevenueCat + Stripe</text>
172
+ <text x="1547" y="589" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="14" font-weight="400" text-anchor="start" letter-spacing="0">subscriptions + payments</text>
173
+ <text x="1547" y="609" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="12" font-weight="400" text-anchor="start" letter-spacing="0">billing integration + shared entitlements</text>
174
+ <rect x="1435" y="630" width="430" height="88" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
175
+ <rect x="1451" y="642" width="64" height="64" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
176
+ <g transform="translate(1457 652.6666666666666) scale(0.6666666666666666)">
177
+ <path d="M38.5717 0L6.29575 59.0738L0 54.6586L29.8639 0H38.5717ZM39.0214 0L71.2973 59.0738L77.5931 54.6586L47.7292 0H39.0214Z" fill="url(#ably-symbol-a)"/>
178
+ <path d="M70.8477 59.4213L38.7966 34.3201L6.74548 59.4213L13.2865 64L38.7966 44.0294L64.3066 64L70.8477 59.4213Z" fill="url(#ably-symbol-b)"/>
179
+ <defs>
180
+ <linearGradient id="ably-symbol-a" x1="10.9472" y1="74.8439" x2="64.9206" y2="14.9005" gradientUnits="userSpaceOnUse"><stop stop-color="#FF5416"/><stop offset="0.461" stop-color="#FF4712"/><stop offset="1" stop-color="#FF0000"/></linearGradient>
181
+ <linearGradient id="ably-symbol-b" x1="21.4169" y1="78.7187" x2="53.3166" y2="43.2904" gradientUnits="userSpaceOnUse"><stop stop-color="#FF5416"/><stop offset="0.461" stop-color="#FF4712"/><stop offset="1" stop-color="#FF0000"/></linearGradient>
182
+ </defs>
183
+ </g>
184
+ <path d="M 1527 644 L 1527 704" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
185
+ <text x="1547" y="661" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="18" font-weight="500" text-anchor="start" letter-spacing="0">Ably Realtime</text>
186
+ <text x="1547" y="685" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="14" font-weight="400" text-anchor="start" letter-spacing="0">scoped invalidations</text>
187
+ <text x="1547" y="705" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="12" font-weight="400" text-anchor="start" letter-spacing="0">outbox → event → client refetch</text>
188
+ <rect x="1435" y="726" width="430" height="88" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
189
+ <rect x="1451" y="738" width="64" height="64" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
190
+ <g transform="translate(1457 744) scale(2.1666666666666665)"><path d="m8.213.063 8.879 12.136-8.67 11.739h2.476l8.665-11.735-8.89-12.14Zm4.728 0 9.02 11.992-9.018 11.883h2.496L24 12.656v-1.199L15.434.063ZM7.178 2.02.01 11.398l-.01 1.2 7.203 9.644 1.238-1.676-6.396-8.556 6.361-8.313Z" fill="#f48120"/></g>
191
+ <path d="M 1527 740 L 1527 800" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
192
+ <text x="1547" y="757" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="18" font-weight="500" text-anchor="start" letter-spacing="0">Assets Worker</text>
193
+ <text x="1547" y="781" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="14" font-weight="400" text-anchor="start" letter-spacing="0">PRIVATE R2 assets binding</text>
194
+ <text x="1547" y="801" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="12" font-weight="400" text-anchor="start" letter-spacing="0">assets.example.com · authorized reads</text>
195
+ <rect x="1435" y="822" width="430" height="88" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
196
+ <rect x="1451" y="834" width="64" height="64" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
197
+ <g transform="translate(1456 853) scale(1.0833333333333333)"><path d="m8.213.063 8.879 12.136-8.67 11.739h2.476l8.665-11.735-8.89-12.14Zm4.728 0 9.02 11.992-9.018 11.883h2.496L24 12.656v-1.199L15.434.063ZM7.178 2.02.01 11.398l-.01 1.2 7.203 9.644 1.238-1.676-6.396-8.556 6.361-8.313Z" fill="#f48120"/></g>
198
+ <g transform="translate(1484 853) scale(1.0833333333333333)"><path d="M12.0111 0c-.85 0-1.5392.6891-1.5392 1.5392 0 .8501.6891 1.5393 1.5392 1.5393.595 0 1.11-.338 1.3662-.832 2.2208 1.2675 3.847 5.4728 3.847 10.3623 0 2.0715-.2891 4.056-.825 5.7685a.3215.3215 0 0 0 .2107.403.322.322 0 0 0 .4033-.2111c.5558-1.7763.8542-3.8251.8542-5.9604 0-5.1927-1.7717-9.686-4.3206-11.0027.001-.0223.0035-.0443.0035-.0669 0-.85-.6891-1.5392-1.5393-1.5392zm0 .6432a.896.896 0 1 1 0 1.792.896.896 0 1 1 0-1.792zm-5.486 4.3052c-2.067.0074-3.6473.6646-4.3885 1.9485-.7375 1.2774-.5267 2.971.5113 4.7813a.3217.3217 0 0 0 .558-.32C2.271 9.7274 2.089 8.266 2.6938 7.2185c.821-1.422 3.033-1.9552 5.9321-1.4271a.3216.3216 0 0 0 .1153-.6329c-.784-.1428-1.5271-.2125-2.216-.21zm11.0522.0176a.3216.3216 0 0 0-.0084.6432c1.8337.0239 3.1556.5956 3.7502 1.6256.8192 1.419.1798 3.5947-1.7182 5.837a.322.322 0 0 0 .0377.4535.3215.3215 0 0 0 .4532-.0377c2.0535-2.426 2.7708-4.8661 1.7845-6.5744-.7257-1.257-2.26-1.9207-4.299-1.9472zm-2.6984.2924a.3225.3225 0 0 0-.0647.0072c-1.8568.3979-3.8333 1.1755-5.7314 2.2714-4.5699 2.6384-7.5924 6.4948-7.3601 9.3717-.4726.2628-.7928.7664-.7928 1.3455 0 .85.6892 1.5392 1.5393 1.5392.85 0 1.5392-.6891 1.5392-1.5392 0-.8501-.6891-1.5393-1.5392-1.5393-.038 0-.0754.003-.1128.0057-.1002-2.5597 2.7434-6.1412 7.048-8.6265 1.8413-1.063 3.7551-1.8163 5.5445-2.1997a.3217.3217 0 0 0-.07-.636zm-2.8787 6.2364a1.1192 1.1192 0 0 0-.2243.0255c-.6012.1301-.983.7225-.8533 1.3238.1302.6012.7226.9832 1.3238.8533.6012-.1302.9832-.7226.8533-1.3238-.1139-.526-.5816-.8844-1.0995-.8788zM4.532 13.341a.321.321 0 0 0-.2318.0835.3214.3214 0 0 0-.0214.4542c1.2682 1.3936 2.9157 2.701 4.7946 3.7857 4.4146 2.5489 9.1056 3.2849 11.5608 1.8392a1.53 1.53 0 0 0 .8966.2899c.8501 0 1.5392-.6891 1.5392-1.5392 0-.8501-.689-1.5393-1.5392-1.5393-.85 0-1.5392.6892-1.5392 1.5393 0 .276.0737.5344.201.7584-2.2448 1.214-6.631.5002-10.7976-1.9054-1.8228-1.0524-3.418-2.3181-4.6404-3.6614a.3206.3206 0 0 0-.2226-.1049zm-2.0628 4.0172a.896.896 0 1 1 0 1.792.896.896 0 1 1 0-1.792zm19.0616 0a.896.896 0 1 1 0 1.792.891.891 0 0 1-.5864-.2194c-.0025-.004-.0039-.0083-.0066-.0123a.3195.3195 0 0 0-.0957-.0914.896.896 0 0 1 .6887-1.4689zm-14.0045 1.368a.3215.3215 0 0 0-.3207.4296C8.2793 22.154 10.036 24 12.0111 24c1.4406 0 2.7735-.9822 3.8128-2.711a.3215.3215 0 0 0-.11-.4413.3219.3219 0 0 0-.4415.11c-.934 1.5537-2.0812 2.399-3.2613 2.399-1.6407 0-3.2075-1.6465-4.2-4.4179a.3216.3216 0 0 0-.2848-.2126z" fill="#51dce9"/></g>
199
+ <path d="M 1527 836 L 1527 896" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
200
+ <text x="1547" y="853" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="18" font-weight="500" text-anchor="start" letter-spacing="0">Updater Worker</text>
201
+ <text x="1547" y="877" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="14" font-weight="400" text-anchor="start" letter-spacing="0">PRIVATE R2 updates binding</text>
202
+ <text x="1547" y="897" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="12" font-weight="400" text-anchor="start" letter-spacing="0">updates.example.com → electron-updater</text>
203
+ <rect x="1435" y="918" width="430" height="88" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
204
+ <rect x="1451" y="930" width="64" height="64" rx="11" fill="#07121d" stroke="#34424e" stroke-width="1.15"/>
205
+ <g transform="translate(1456 949) scale(1.0833333333333333)"><path d="M16.5088 16.8447c.1475-.5068.0908-.9707-.1553-1.3154-.2246-.3164-.6045-.499-1.0615-.5205l-8.6592-.1123a.1559.1559 0 0 1-.1333-.0713c-.0283-.042-.0351-.0986-.021-.1553.0278-.084.1123-.1484.2036-.1562l8.7359-.1123c1.0351-.0489 2.1601-.8868 2.5537-1.9136l.499-1.3013c.0215-.0561.0293-.1128.0147-.168-.5625-2.5463-2.835-4.4453-5.5499-4.4453-2.5039 0-4.6284 1.6177-5.3876 3.8614-.4927-.3658-1.1187-.5625-1.794-.499-1.2026.119-2.1665 1.083-2.2861 2.2856-.0283.31-.0069.6128.0635.894C1.5683 13.171 0 14.7754 0 16.752c0 .1748.0142.3515.0352.5273.0141.083.0844.1475.1689.1475h15.9814c.0909 0 .1758-.0645.2032-.1553l.12-.4268zm2.7568-5.5634c-.0771 0-.1611 0-.2383.0112-.0566 0-.1054.0415-.127.0976l-.3378 1.1744c-.1475.5068-.0918.9707.1543 1.3164.2256.3164.6055.498 1.0625.5195l1.8437.1133c.0557 0 .1055.0263.1329.0703.0283.043.0351.1074.0214.1562-.0283.084-.1132.1485-.204.1553l-1.921.1123c-1.041.0488-2.1582.8867-2.5527 1.914l-.1406.3585c-.0283.0713.0215.1416.0986.1416h6.5977c.0771 0 .1474-.0489.169-.126.1122-.4082.1757-.837.1757-1.2803 0-2.6025-2.125-4.727-4.7344-4.727" fill="#f48120"/></g>
206
+ <g transform="translate(1484 949) scale(1.0833333333333333)"><path d="m12 1.608 12 20.784H0Z" fill="#f7f5f0"/></g>
207
+ <path d="M 1527 932 L 1527 992" fill="none" stroke="#34424e" stroke-width="1" stroke-linecap="round"/>
208
+ <text x="1547" y="949" fill="#f7f5f0" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="18" font-weight="500" text-anchor="start" letter-spacing="0">Cloudflare DNS + Vercel</text>
209
+ <text x="1547" y="973" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="14" font-weight="400" text-anchor="start" letter-spacing="0">app domain: DNS-only → Vercel</text>
210
+ <text x="1547" y="993" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="12" font-weight="400" text-anchor="start" letter-spacing="0">DNSSEC · assets/updates Worker domains</text>
211
+ <path d="M 620 398 C 541.8 398 528.2 393 450 393" fill="none" stroke="#e9f600" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="10 8" marker-end="url(#arrow-yellow)"/>
212
+ <path d="M 620 550 C 541.8 550 528.2 507 450 507" fill="none" stroke="#e9f600" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="10 8" marker-end="url(#arrow-yellow)"/>
213
+ <path d="M 620 550 C 541.8 550 528.2 621 450 621" fill="none" stroke="#e9f600" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="10 8" marker-end="url(#arrow-yellow)"/>
214
+ <path d="M 620 702 C 541.8 702 528.2 735 450 735" fill="none" stroke="#e9f600" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="10 8" marker-end="url(#arrow-yellow)"/>
215
+ <path d="M 620 854 C 541.8 854 528.2 849 450 849" fill="none" stroke="#e9f600" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="10 8" marker-end="url(#arrow-yellow)"/>
216
+ <path d="M 990 398 C 1054.4 398 1065.6 520 1130 520" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-white)"/>
217
+ <path d="M 990 550 C 1054.4 550 1065.6 590 1130 590" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-white)"/>
218
+ <path d="M 990 702 C 1054.4 702 1065.6 660 1130 660" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-white)"/>
219
+ <path d="M 990 854 C 1054.4 854 1065.6 730 1130 730" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-white)"/>
220
+ <path d="M 1338 500 C 1382.62 500 1390.38 386 1435 386" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
221
+ <circle cx="1435" cy="386" r="8.5" fill="#b9f500" filter="url(#endpoint-glow)"/>
222
+ <path d="M 1338 555 C 1382.62 555 1390.38 482 1435 482" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
223
+ <circle cx="1435" cy="482" r="8.5" fill="#b9f500" filter="url(#endpoint-glow)"/>
224
+ <path d="M 1338 610 C 1382.62 610 1390.38 578 1435 578" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
225
+ <circle cx="1435" cy="578" r="8.5" fill="#b9f500" filter="url(#endpoint-glow)"/>
226
+ <path d="M 1338 665 C 1382.62 665 1390.38 674 1435 674" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
227
+ <circle cx="1435" cy="674" r="8.5" fill="#b9f500" filter="url(#endpoint-glow)"/>
228
+ <path d="M 1338 720 C 1382.62 720 1390.38 770 1435 770" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
229
+ <circle cx="1435" cy="770" r="8.5" fill="#b9f500" filter="url(#endpoint-glow)"/>
230
+ <rect x="126" y="1050" width="1668" height="86" rx="12" fill="url(#card-fill)" stroke="#73777b" stroke-width="1.15"/>
231
+ <path d="M 246 1093 L 350 1093" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round" marker-end="url(#arrow-white)"/>
232
+ <text x="374" y="1100" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="17" font-weight="400" text-anchor="start" letter-spacing="0">runtime API flow</text>
233
+ <path d="M 720 1093 L 824 1093" fill="none" stroke="#e9f600" stroke-width="3" stroke-linecap="round" stroke-dasharray="10 8" marker-end="url(#arrow-yellow)"/>
234
+ <text x="848" y="1100" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="17" font-weight="400" text-anchor="start" letter-spacing="0">deploy / publish</text>
235
+ <path d="M 1198 1093 L 1302 1093" fill="none" stroke="#f7f5f0" stroke-width="3" stroke-linecap="round"/>
236
+ <circle cx="1302" cy="1093" r="8.5" fill="#b9f500" filter="url(#endpoint-glow)"/>
237
+ <text x="1332" y="1100" fill="#c4c7ca" font-family="Inter, Helvetica Neue, Arial, sans-serif" font-size="17" font-weight="400" text-anchor="start" letter-spacing="0">backend service connection</text>
238
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="78" height="64" viewBox="0 0 78 64" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M38.5717 0L6.29575 59.0738L0 54.6586L29.8639 0H38.5717ZM39.0214 0L71.2973 59.0738L77.5931 54.6586L47.7292 0H39.0214Z" fill="url(#ably-symbol-a)"/>
3
+ <path d="M70.8477 59.4213L38.7966 34.3201L6.74548 59.4213L13.2865 64L38.7966 44.0294L64.3066 64L70.8477 59.4213Z" fill="url(#ably-symbol-b)"/>
4
+ <defs>
5
+ <linearGradient id="ably-symbol-a" x1="10.9472" y1="74.8439" x2="64.9206" y2="14.9005" gradientUnits="userSpaceOnUse"><stop stop-color="#FF5416"/><stop offset="0.461" stop-color="#FF4712"/><stop offset="1" stop-color="#FF0000"/></linearGradient>
6
+ <linearGradient id="ably-symbol-b" x1="21.4169" y1="78.7187" x2="53.3166" y2="43.2904" gradientUnits="userSpaceOnUse"><stop stop-color="#FF5416"/><stop offset="0.461" stop-color="#FF4712"/><stop offset="1" stop-color="#FF0000"/></linearGradient>
7
+ </defs>
8
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="1820" height="2199" viewBox="0 0 1820 2199" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M1604.59 26.7414C1694.33 -39.6752 1821.31 25.3379 1819.89 136.971L1809.28 971.026C1774.28 969.39 1738.87 969.434 1703.15 971.237C1334.16 989.855 1017.8 1191.61 837.641 1484.06L122.496 1416.65C-0.793297 1405.03 -44.6847 1247.41 54.8543 1173.73L1604.59 26.7414Z" fill="white"/>
3
+ <path d="M1795.36 2064.84C1793.79 2188.66 1640.25 2245.21 1558.74 2151.98L1083.84 1608.79C1214.01 1305.09 1479.98 1071.11 1809.07 987.262L1795.36 2064.84Z" fill="white"/>
4
+ </svg>
@@ -1,5 +1,5 @@
1
- export { DEFAULT_MODULE_DEFINITIONS, DEFAULT_MODULE_REGISTRY, MODULE_IDS, ModuleRegistryError, ModuleResolutionError, createModuleRegistry, isModuleId, resolveModules, } from './modules.js';
2
- export type { DependencyEdge, ModuleDefinition, ModuleId, ModuleKind, ModuleRegistry, ModuleRegistryErrorCode, ModuleResolution, ModuleResolutionErrorCode, } from './modules.js';
1
+ export { APP_MODULES, DEFAULT_MODULE_DEFINITIONS, DEFAULT_MODULE_REGISTRY, FEATURE_MODULES, MODULE_IDS, ModuleRegistryError, ModuleResolutionError, createModuleRegistry, isModuleId, resolveModules, } from './modules.js';
2
+ export type { AppModule, DependencyEdge, FeatureModule, ModuleDefinition, ModuleId, ModuleKind, ModuleRegistry, ModuleRegistryErrorCode, ModuleResolution, ModuleResolutionErrorCode, } from './modules.js';
3
3
  export { FILE_OWNERSHIP_CLASSES, PlanBuildError, buildGenerationPlan, hashContent, isFileOwnershipClass, isSha256, normalizePlanPath, writePolicyForOwnership, } from './plan.js';
4
4
  export type { BuildGenerationPlanInput, FileOwner, FileOwnershipClass, FileWritePolicy, GenerationOperation, GenerationPlan, ModulePlanContribution, PlanBuildErrorCode, PlanFileInput, PlannedFile, } from './plan.js';
5
5
  export { MANIFEST_SCHEMA_VERSION, ManifestValidationError, createManifest, readManifest, serializeManifest, } from './manifest.js';
@@ -1,4 +1,4 @@
1
- export { DEFAULT_MODULE_DEFINITIONS, DEFAULT_MODULE_REGISTRY, MODULE_IDS, ModuleRegistryError, ModuleResolutionError, createModuleRegistry, isModuleId, resolveModules, } from './modules.js';
1
+ export { APP_MODULES, DEFAULT_MODULE_DEFINITIONS, DEFAULT_MODULE_REGISTRY, FEATURE_MODULES, MODULE_IDS, ModuleRegistryError, ModuleResolutionError, createModuleRegistry, isModuleId, resolveModules, } from './modules.js';
2
2
  export { FILE_OWNERSHIP_CLASSES, PlanBuildError, buildGenerationPlan, hashContent, isFileOwnershipClass, isSha256, normalizePlanPath, writePolicyForOwnership, } from './plan.js';
3
3
  export { MANIFEST_SCHEMA_VERSION, ManifestValidationError, createManifest, readManifest, serializeManifest, } from './manifest.js';
4
4
  export { TEMPLATE_IDS, isTemplateId, templateIdsForModules, } from './templates.js';
@@ -1,4 +1,8 @@
1
+ export declare const APP_MODULES: readonly ["web", "mobile", "api", "desktop", "extension"];
2
+ export declare const FEATURE_MODULES: readonly ["db", "auth", "billing", "storage", "native-subscriptions", "electron-updater"];
1
3
  export declare const MODULE_IDS: readonly ["web", "mobile", "api", "desktop", "extension", "db", "auth", "billing", "storage", "native-subscriptions", "electron-updater"];
4
+ export type AppModule = (typeof APP_MODULES)[number];
5
+ export type FeatureModule = (typeof FEATURE_MODULES)[number];
2
6
  export type ModuleId = (typeof MODULE_IDS)[number];
3
7
  export type ModuleKind = 'app' | 'feature';
4
8
  export type ModuleDefinition = {
@@ -33,5 +37,5 @@ export declare class ModuleResolutionError extends Error {
33
37
  export declare function isModuleId(value: unknown): value is ModuleId;
34
38
  export declare function createModuleRegistry(definitions: readonly ModuleDefinition[]): ModuleRegistry;
35
39
  export declare const DEFAULT_MODULE_DEFINITIONS: readonly ModuleDefinition[];
36
- export declare const DEFAULT_MODULE_REGISTRY: Readonly<Record<"electron-updater" | "auth" | "billing" | "storage" | "api" | "desktop" | "web" | "mobile" | "extension" | "db" | "native-subscriptions", ModuleDefinition>>;
40
+ export declare const DEFAULT_MODULE_REGISTRY: Readonly<Record<"electron-updater" | "web" | "mobile" | "desktop" | "extension" | "auth" | "billing" | "storage" | "api" | "db" | "native-subscriptions", ModuleDefinition>>;
37
41
  export declare function resolveModules(requested: readonly string[], registry?: ModuleRegistry): ModuleResolution;
@@ -1,9 +1,11 @@
1
- export const MODULE_IDS = [
1
+ export const APP_MODULES = [
2
2
  'web',
3
3
  'mobile',
4
4
  'api',
5
5
  'desktop',
6
6
  'extension',
7
+ ];
8
+ export const FEATURE_MODULES = [
7
9
  'db',
8
10
  'auth',
9
11
  'billing',
@@ -11,6 +13,7 @@ export const MODULE_IDS = [
11
13
  'native-subscriptions',
12
14
  'electron-updater',
13
15
  ];
16
+ export const MODULE_IDS = [...APP_MODULES, ...FEATURE_MODULES];
14
17
  export class ModuleRegistryError extends Error {
15
18
  code;
16
19
  modules;