loopwind 0.9.1

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 (245) hide show
  1. package/FONTS.md +156 -0
  2. package/HELPERS_DEMO.md +134 -0
  3. package/PROJECT_STRUCTURE.md +286 -0
  4. package/PUBLISHING.md +171 -0
  5. package/README.md +1020 -0
  6. package/REGISTRY_SETUP.md +427 -0
  7. package/SHADCN_INTEGRATION.md +269 -0
  8. package/TAILWIND.md +228 -0
  9. package/TEMPLATE_SOURCES.md +363 -0
  10. package/_dsgn/templates/banner-hero/banner-hero.tsx +57 -0
  11. package/_dsgn/templates/banner-hero/meta.json +14 -0
  12. package/_dsgn/templates/composite-card/meta.json +16 -0
  13. package/_dsgn/templates/composite-card/template.tsx +44 -0
  14. package/_dsgn/templates/image/meta.json +13 -0
  15. package/_dsgn/templates/image/template.tsx +28 -0
  16. package/_dsgn/templates/kitchen-sink/meta.json +13 -0
  17. package/_dsgn/templates/kitchen-sink/template.tsx +72 -0
  18. package/_dsgn/templates/qr-card/meta.json +14 -0
  19. package/_dsgn/templates/qr-card/template.tsx +39 -0
  20. package/_dsgn/templates/test-parent/child/meta.json +11 -0
  21. package/_dsgn/templates/test-parent/child/template.tsx +27 -0
  22. package/_dsgn/templates/test-parent/meta.json +12 -0
  23. package/_dsgn/templates/test-parent/template.tsx +30 -0
  24. package/_dsgn/templates/test-sibling/meta.json +11 -0
  25. package/_dsgn/templates/test-sibling/template.tsx +20 -0
  26. package/_dsgn/templates/video/.tmp/template-1763421345296.mjs +43 -0
  27. package/_dsgn/templates/video/.tmp/template-1763421362228.mjs +43 -0
  28. package/_dsgn/templates/video/.tmp/template-1763421377706.mjs +43 -0
  29. package/_dsgn/templates/video/meta.json +17 -0
  30. package/_dsgn/templates/video/template.tsx +48 -0
  31. package/dist/cli.d.ts +3 -0
  32. package/dist/cli.d.ts.map +1 -0
  33. package/dist/cli.js +70 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/commands/add.d.ts +6 -0
  36. package/dist/commands/add.d.ts.map +1 -0
  37. package/dist/commands/add.js +86 -0
  38. package/dist/commands/add.js.map +1 -0
  39. package/dist/commands/default.d.ts +2 -0
  40. package/dist/commands/default.d.ts.map +1 -0
  41. package/dist/commands/default.js +69 -0
  42. package/dist/commands/default.js.map +1 -0
  43. package/dist/commands/init.d.ts +2 -0
  44. package/dist/commands/init.d.ts.map +1 -0
  45. package/dist/commands/init.js +75 -0
  46. package/dist/commands/init.js.map +1 -0
  47. package/dist/commands/list.d.ts +2 -0
  48. package/dist/commands/list.d.ts.map +1 -0
  49. package/dist/commands/list.js +83 -0
  50. package/dist/commands/list.js.map +1 -0
  51. package/dist/commands/preview.d.ts +3 -0
  52. package/dist/commands/preview.d.ts.map +1 -0
  53. package/dist/commands/preview.js +296 -0
  54. package/dist/commands/preview.js.map +1 -0
  55. package/dist/commands/render.d.ts +10 -0
  56. package/dist/commands/render.d.ts.map +1 -0
  57. package/dist/commands/render.js +204 -0
  58. package/dist/commands/render.js.map +1 -0
  59. package/dist/commands/validate.d.ts +2 -0
  60. package/dist/commands/validate.d.ts.map +1 -0
  61. package/dist/commands/validate.js +107 -0
  62. package/dist/commands/validate.js.map +1 -0
  63. package/dist/default-templates/AGENTS.md +229 -0
  64. package/dist/default-templates/image/meta.json +13 -0
  65. package/dist/default-templates/image/template.d.ts +20 -0
  66. package/dist/default-templates/image/template.d.ts.map +1 -0
  67. package/dist/default-templates/image/template.js +18 -0
  68. package/dist/default-templates/image/template.js.map +1 -0
  69. package/dist/default-templates/image/template.tsx +20 -0
  70. package/dist/default-templates/image-template/meta.json +13 -0
  71. package/dist/default-templates/image-template/template.tsx +19 -0
  72. package/dist/default-templates/kitchen-sink/meta.json +13 -0
  73. package/dist/default-templates/kitchen-sink/template.tsx +64 -0
  74. package/dist/default-templates/page/meta.json +17 -0
  75. package/dist/default-templates/page/template.tsx +37 -0
  76. package/dist/default-templates/video/meta.json +17 -0
  77. package/dist/default-templates/video/template.d.ts +26 -0
  78. package/dist/default-templates/video/template.d.ts.map +1 -0
  79. package/dist/default-templates/video/template.js +33 -0
  80. package/dist/default-templates/video/template.js.map +1 -0
  81. package/dist/default-templates/video/template.tsx +37 -0
  82. package/dist/default-templates/video-template/meta.json +17 -0
  83. package/dist/default-templates/video-template/template.tsx +36 -0
  84. package/dist/default-templates/website/meta.json +16 -0
  85. package/dist/default-templates/website/pages/home.tsx +17 -0
  86. package/dist/default-templates/website/parts/footer.tsx +17 -0
  87. package/dist/default-templates/website/parts/header.tsx +17 -0
  88. package/dist/default-templates/website/template.tsx +17 -0
  89. package/dist/default-templates/website-template/meta.json +16 -0
  90. package/dist/default-templates/website-template/pages/home.tsx +16 -0
  91. package/dist/default-templates/website-template/parts/footer.tsx +16 -0
  92. package/dist/default-templates/website-template/parts/header.tsx +16 -0
  93. package/dist/default-templates/website-template/template.tsx +16 -0
  94. package/dist/lib/config.d.ts +34 -0
  95. package/dist/lib/config.d.ts.map +1 -0
  96. package/dist/lib/config.js +248 -0
  97. package/dist/lib/config.js.map +1 -0
  98. package/dist/lib/constants.d.ts +7 -0
  99. package/dist/lib/constants.d.ts.map +1 -0
  100. package/dist/lib/constants.js +12 -0
  101. package/dist/lib/constants.js.map +1 -0
  102. package/dist/lib/helpers.d.ts +29 -0
  103. package/dist/lib/helpers.d.ts.map +1 -0
  104. package/dist/lib/helpers.js +159 -0
  105. package/dist/lib/helpers.js.map +1 -0
  106. package/dist/lib/installer.d.ts +51 -0
  107. package/dist/lib/installer.d.ts.map +1 -0
  108. package/dist/lib/installer.js +215 -0
  109. package/dist/lib/installer.js.map +1 -0
  110. package/dist/lib/renderer.d.ts +51 -0
  111. package/dist/lib/renderer.d.ts.map +1 -0
  112. package/dist/lib/renderer.js +524 -0
  113. package/dist/lib/renderer.js.map +1 -0
  114. package/dist/lib/tailwind-config-loader.d.ts +47 -0
  115. package/dist/lib/tailwind-config-loader.d.ts.map +1 -0
  116. package/dist/lib/tailwind-config-loader.js +432 -0
  117. package/dist/lib/tailwind-config-loader.js.map +1 -0
  118. package/dist/lib/tailwind-detector.d.ts +36 -0
  119. package/dist/lib/tailwind-detector.d.ts.map +1 -0
  120. package/dist/lib/tailwind-detector.js +156 -0
  121. package/dist/lib/tailwind-detector.js.map +1 -0
  122. package/dist/lib/tailwind.d.ts +8 -0
  123. package/dist/lib/tailwind.d.ts.map +1 -0
  124. package/dist/lib/tailwind.js +994 -0
  125. package/dist/lib/tailwind.js.map +1 -0
  126. package/dist/lib/template-validator.d.ts +22 -0
  127. package/dist/lib/template-validator.d.ts.map +1 -0
  128. package/dist/lib/template-validator.js +174 -0
  129. package/dist/lib/template-validator.js.map +1 -0
  130. package/dist/lib/utils.d.ts +44 -0
  131. package/dist/lib/utils.d.ts.map +1 -0
  132. package/dist/lib/utils.js +207 -0
  133. package/dist/lib/utils.js.map +1 -0
  134. package/dist/lib/version-check.d.ts +16 -0
  135. package/dist/lib/version-check.d.ts.map +1 -0
  136. package/dist/lib/version-check.js +88 -0
  137. package/dist/lib/version-check.js.map +1 -0
  138. package/dist/lib/video-renderer.d.ts +32 -0
  139. package/dist/lib/video-renderer.d.ts.map +1 -0
  140. package/dist/lib/video-renderer.js +226 -0
  141. package/dist/lib/video-renderer.js.map +1 -0
  142. package/dist/sdk/index.d.ts +58 -0
  143. package/dist/sdk/index.d.ts.map +1 -0
  144. package/dist/sdk/index.js +119 -0
  145. package/dist/sdk/index.js.map +1 -0
  146. package/dist/sdk/template.d.ts +40 -0
  147. package/dist/sdk/template.d.ts.map +1 -0
  148. package/dist/sdk/template.js +60 -0
  149. package/dist/sdk/template.js.map +1 -0
  150. package/dist/types/config.d.ts +62 -0
  151. package/dist/types/config.d.ts.map +1 -0
  152. package/dist/types/config.js +47 -0
  153. package/dist/types/config.js.map +1 -0
  154. package/dist/types/template.d.ts +79 -0
  155. package/dist/types/template.d.ts.map +1 -0
  156. package/dist/types/template.js +2 -0
  157. package/dist/types/template.js.map +1 -0
  158. package/examples/nextjs-api/README.md +180 -0
  159. package/examples/nextjs-api/package.json +21 -0
  160. package/examples/nextjs-api/pages/api/intro-video.ts +53 -0
  161. package/examples/nextjs-api/pages/api/og-image.ts +50 -0
  162. package/netlify.toml +13 -0
  163. package/package.json +84 -0
  164. package/patches/satori+0.18.3.patch +13 -0
  165. package/test-templates/TESTS.md +63 -0
  166. package/test-templates/_dsgn/templates/absolute-spin/meta.json +7 -0
  167. package/test-templates/_dsgn/templates/absolute-spin/template.tsx +16 -0
  168. package/test-templates/_dsgn/templates/animated-intro/.tmp/template-1763468771640.mjs +7 -0
  169. package/test-templates/_dsgn/templates/animated-intro/meta.json +10 -0
  170. package/test-templates/_dsgn/templates/animated-intro/template.tsx +23 -0
  171. package/test-templates/_dsgn/templates/centered-spin/.tmp/template-1763468525386.mjs +7 -0
  172. package/test-templates/_dsgn/templates/centered-spin/meta.json +7 -0
  173. package/test-templates/_dsgn/templates/centered-spin/template.tsx +11 -0
  174. package/test-templates/_dsgn/templates/composite/.tmp/template-1763468815645.mjs +7 -0
  175. package/test-templates/_dsgn/templates/composite/meta.json +9 -0
  176. package/test-templates/_dsgn/templates/composite/template.tsx +23 -0
  177. package/test-templates/_dsgn/templates/easing-test/.tmp/template-1763468824501.mjs +7 -0
  178. package/test-templates/_dsgn/templates/easing-test/meta.json +7 -0
  179. package/test-templates/_dsgn/templates/easing-test/template.tsx +47 -0
  180. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466364336.mjs +10 -0
  181. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466584319.mjs +10 -0
  182. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466667797.mjs +10 -0
  183. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466746504.mjs +10 -0
  184. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466930225.mjs +10 -0
  185. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467004552.mjs +10 -0
  186. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467060334.mjs +10 -0
  187. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467124493.mjs +10 -0
  188. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467174690.mjs +10 -0
  189. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467359134.mjs +10 -0
  190. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467451928.mjs +10 -0
  191. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467758275.mjs +10 -0
  192. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467985201.mjs +10 -0
  193. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468020563.mjs +10 -0
  194. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468090428.mjs +10 -0
  195. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468211036.mjs +10 -0
  196. package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468394057.mjs +10 -0
  197. package/test-templates/_dsgn/templates/minimal-spin/meta.json +7 -0
  198. package/test-templates/_dsgn/templates/minimal-spin/template.tsx +13 -0
  199. package/test-templates/_dsgn/templates/no-origin-spin/meta.json +7 -0
  200. package/test-templates/_dsgn/templates/no-origin-spin/template.tsx +10 -0
  201. package/test-templates/_dsgn/templates/opacity-test/meta.json +7 -0
  202. package/test-templates/_dsgn/templates/opacity-test/template.tsx +9 -0
  203. package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468758954.mjs +17 -0
  204. package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468815672.mjs +17 -0
  205. package/test-templates/_dsgn/templates/qr-code/meta.json +9 -0
  206. package/test-templates/_dsgn/templates/qr-code/template.tsx +20 -0
  207. package/test-templates/_dsgn/templates/rotation-abs-test/meta.json +7 -0
  208. package/test-templates/_dsgn/templates/rotation-abs-test/template.tsx +15 -0
  209. package/test-templates/_dsgn/templates/rotation-corner/meta.json +7 -0
  210. package/test-templates/_dsgn/templates/rotation-corner/template.tsx +12 -0
  211. package/test-templates/_dsgn/templates/rotation-test/meta.json +7 -0
  212. package/test-templates/_dsgn/templates/rotation-test/template.tsx +12 -0
  213. package/test-templates/_dsgn/templates/shake-test/meta.json +7 -0
  214. package/test-templates/_dsgn/templates/shake-test/template.tsx +12 -0
  215. package/test-templates/_dsgn/templates/static-image/.tmp/template-1763468746271.mjs +7 -0
  216. package/test-templates/_dsgn/templates/static-image/meta.json +9 -0
  217. package/test-templates/_dsgn/templates/static-image/template.tsx +19 -0
  218. package/test-templates/_dsgn/templates/translate-test/meta.json +7 -0
  219. package/test-templates/_dsgn/templates/translate-test/template.tsx +9 -0
  220. package/test-templates/_dsgn/templates/video-loops/.tmp/template-1763468793192.mjs +15 -0
  221. package/test-templates/_dsgn/templates/video-loops/meta.json +9 -0
  222. package/test-templates/_dsgn/templates/video-loops/template.tsx +39 -0
  223. package/test-templates/_dsgn/templates/wrapped-spin/meta.json +7 -0
  224. package/test-templates/_dsgn/templates/wrapped-spin/template.tsx +17 -0
  225. package/test-templates/compare-svgs.mjs +30 -0
  226. package/test-templates/convert-frames.mjs +15 -0
  227. package/test-templates/debug-rotation.mjs +25 -0
  228. package/test-templates/run-tests.sh +39 -0
  229. package/test-templates/test-sdk.mjs +115 -0
  230. package/website/.astro/settings.json +5 -0
  231. package/website/.astro/types.d.ts +1 -0
  232. package/website/README.md +112 -0
  233. package/website/astro.config.mjs +18 -0
  234. package/website/dist/_astro/fonts.DHdiHGBO.css +1 -0
  235. package/website/dist/fonts/index.html +193 -0
  236. package/website/dist/helpers/index.html +166 -0
  237. package/website/dist/images/index.html +314 -0
  238. package/website/dist/index.html +219 -0
  239. package/website/dist/llm.txt +2448 -0
  240. package/website/dist/styling/index.html +365 -0
  241. package/website/dist/templates/index.html +124 -0
  242. package/website/dist/video/index.html +636 -0
  243. package/website/package-lock.json +7606 -0
  244. package/website/package.json +23 -0
  245. package/website/public/robots.txt +5 -0
package/TAILWIND.md ADDED
@@ -0,0 +1,228 @@
1
+ # Using Tailwind Classes in Templates
2
+
3
+ ## Overview
4
+
5
+ Templates can use Tailwind utility classes instead of writing inline styles! The `tw()` function is automatically provided to every template and converts Tailwind classes to inline styles that Satori can render.
6
+
7
+ ## Basic Usage
8
+
9
+ ```tsx
10
+ export default function MyTemplate({ title, tw }) {
11
+ return (
12
+ <div style={tw('flex items-center justify-center w-full h-full bg-blue-500')}>
13
+ <h1 style={tw('text-6xl font-bold text-white')}>
14
+ {title}
15
+ </h1>
16
+ </div>
17
+ );
18
+ }
19
+ ```
20
+
21
+ ## Combining with Custom Styles
22
+
23
+ You can mix Tailwind classes with custom styles using the spread operator:
24
+
25
+ ```tsx
26
+ export default function MyTemplate({ title, tw, config }) {
27
+ return (
28
+ <div
29
+ style={{
30
+ ...tw('flex flex-col p-20 text-white'),
31
+ background: `linear-gradient(135deg, ${config?.colors?.primary} 0%, ${config?.colors?.secondary} 100%)`,
32
+ }}
33
+ >
34
+ <h1 style={tw('text-8xl font-bold')}>{title}</h1>
35
+ </div>
36
+ );
37
+ }
38
+ ```
39
+
40
+ ## Supported Tailwind Classes
41
+
42
+ ### Layout
43
+
44
+ - **Display**: `flex`, `inline-flex`, `block`, `inline-block`, `hidden`
45
+ - **Flex Direction**: `flex-row`, `flex-col`, `flex-row-reverse`, `flex-col-reverse`
46
+ - **Justify**: `justify-start`, `justify-end`, `justify-center`, `justify-between`, `justify-around`
47
+ - **Align**: `items-start`, `items-end`, `items-center`, `items-baseline`, `items-stretch`
48
+
49
+ ### Spacing
50
+
51
+ - **Padding**: `p-{n}`, `px-{n}`, `py-{n}`, `pt-{n}`, `pb-{n}`, `pl-{n}`, `pr-{n}`
52
+ - **Margin**: `m-{n}`, `mx-{n}`, `my-{n}`, `mt-{n}`, `mb-{n}`, `ml-{n}`, `mr-{n}`
53
+ - **Gap**: `gap-{n}`, `gap-x-{n}`, `gap-y-{n}`
54
+ - **Sizes**: 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 56, 64
55
+
56
+ Examples:
57
+ ```tsx
58
+ tw('p-4') // padding: 1rem
59
+ tw('px-8') // paddingLeft: 2rem, paddingRight: 2rem
60
+ tw('m-6') // margin: 1.5rem
61
+ tw('gap-4') // gap: 1rem
62
+ ```
63
+
64
+ ### Sizing
65
+
66
+ - **Width**: `w-{n}`, `w-full`, `w-screen`
67
+ - **Height**: `h-{n}`, `h-full`, `h-screen`
68
+
69
+ Examples:
70
+ ```tsx
71
+ tw('w-full') // width: 100%
72
+ tw('h-64') // height: 16rem
73
+ ```
74
+
75
+ ### Typography
76
+
77
+ - **Font Size**: `text-xs`, `text-sm`, `text-base`, `text-lg`, `text-xl`, `text-2xl`, `text-3xl`, `text-4xl`, `text-5xl`, `text-6xl`, `text-7xl`, `text-8xl`, `text-9xl`
78
+ - **Font Weight**: `font-thin`, `font-light`, `font-normal`, `font-medium`, `font-semibold`, `font-bold`, `font-extrabold`, `font-black`
79
+ - **Text Align**: `text-left`, `text-center`, `text-right`
80
+
81
+ Examples:
82
+ ```tsx
83
+ tw('text-6xl') // fontSize: 3.75rem
84
+ tw('font-bold') // fontWeight: 700
85
+ tw('text-center') // textAlign: center
86
+ ```
87
+
88
+ ### Borders
89
+
90
+ - **Border Radius**: `rounded`, `rounded-sm`, `rounded-md`, `rounded-lg`, `rounded-xl`, `rounded-2xl`, `rounded-3xl`, `rounded-full`
91
+
92
+ Examples:
93
+ ```tsx
94
+ tw('rounded-lg') // borderRadius: 0.5rem
95
+ tw('rounded-full') // borderRadius: 9999px
96
+ ```
97
+
98
+ ### Effects
99
+
100
+ - **Opacity**: `opacity-{0-100}`
101
+
102
+ Examples:
103
+ ```tsx
104
+ tw('opacity-50') // opacity: 0.5
105
+ tw('opacity-90') // opacity: 0.9
106
+ ```
107
+
108
+ ### Colors
109
+
110
+ - **Static Colors**: `text-white`, `text-black`, `bg-white`, `bg-black`
111
+ - **Config Colors**: `bg-primary`, `text-primary`, `bg-secondary`, etc. (from dsgn.json)
112
+
113
+ Examples:
114
+ ```tsx
115
+ // Using static colors
116
+ tw('bg-black text-white')
117
+
118
+ // Using config colors (from dsgn.json)
119
+ tw('bg-primary text-secondary')
120
+ ```
121
+
122
+ ## Config Color Integration
123
+
124
+ The `tw()` function automatically uses colors from your `dsgn.json`:
125
+
126
+ ```json
127
+ {
128
+ "colors": {
129
+ "primary": "#667eea",
130
+ "secondary": "#764ba2",
131
+ "accent": "#3b82f6"
132
+ }
133
+ }
134
+ ```
135
+
136
+ ```tsx
137
+ // In your template
138
+ <div style={tw('bg-primary text-white')}>
139
+ {/* background will be #667eea */}
140
+ </div>
141
+ ```
142
+
143
+ ## Complete Example
144
+
145
+ ```tsx
146
+ import React from 'react';
147
+
148
+ export const meta = {
149
+ name: "social-card",
150
+ description: "A social media card",
151
+ size: { width: 1200, height: 630 },
152
+ props: { title: "string", description: "string" }
153
+ };
154
+
155
+ interface SocialCardProps {
156
+ title: string;
157
+ description: string;
158
+ tw?: (classes: string) => any;
159
+ config?: any;
160
+ }
161
+
162
+ export default function SocialCard({
163
+ title,
164
+ description,
165
+ tw = (c) => ({}),
166
+ config
167
+ }: SocialCardProps) {
168
+ return (
169
+ <div style={tw('w-full h-full flex flex-col justify-center items-center bg-primary text-white p-16')}>
170
+ <h1 style={tw('text-6xl font-bold text-center mb-8')}>
171
+ {title}
172
+ </h1>
173
+ <p style={tw('text-2xl text-center opacity-90')}>
174
+ {description}
175
+ </p>
176
+ </div>
177
+ );
178
+ }
179
+ ```
180
+
181
+ ## Fallback for Missing tw
182
+
183
+ Always provide a fallback for the `tw` function in case it's not provided:
184
+
185
+ ```tsx
186
+ export default function MyTemplate({
187
+ title,
188
+ tw = (classes: string) => ({}) // Fallback
189
+ }: MyTemplateProps) {
190
+ // Now tw is always safe to use
191
+ return <div style={tw('flex items-center')}>{title}</div>;
192
+ }
193
+ ```
194
+
195
+ ## Extending Tailwind Support
196
+
197
+ The current implementation supports common Tailwind classes. To add more:
198
+
199
+ 1. Edit `src/lib/tailwind.ts`
200
+ 2. Add to `TAILWIND_MAP` or create a new parser function
201
+ 3. Rebuild the CLI
202
+
203
+ Example adding a new utility:
204
+
205
+ ```typescript
206
+ // In src/lib/tailwind.ts
207
+ const TAILWIND_MAP = {
208
+ // ... existing classes
209
+ 'shadow-lg': { boxShadow: '0 10px 15px rgba(0,0,0,0.1)' },
210
+ 'shadow-xl': { boxShadow: '0 20px 25px rgba(0,0,0,0.15)' },
211
+ };
212
+ ```
213
+
214
+ ## Benefits
215
+
216
+ 1. **Familiar Syntax**: Use the Tailwind classes you already know
217
+ 2. **Cleaner Code**: Less verbose than inline styles
218
+ 3. **Config Integration**: Automatic color mapping from dsgn.json
219
+ 4. **Type Safe**: TypeScript support with CSSProperties
220
+ 5. **Extensible**: Easy to add more utilities
221
+
222
+ ## Limitations
223
+
224
+ - Satori doesn't support all CSS features (no animations, transforms are limited)
225
+ - Pseudo-classes (hover, focus) don't work (Satori renders static images)
226
+ - Some Tailwind utilities may not have equivalents yet
227
+
228
+ For advanced styling needs, combine Tailwind classes with custom inline styles!
@@ -0,0 +1,363 @@
1
+ # Installing Templates from Different Sources
2
+
3
+ ## Overview
4
+
5
+ dsgn supports installing templates from multiple sources:
6
+
7
+ 1. **Official Registry** (default)
8
+ 2. **Direct URLs**
9
+ 3. **GitHub Repositories**
10
+ 4. **Local Filesystem**
11
+
12
+ ## 1. Official Registry (Default)
13
+
14
+ Install templates from the official dsgn registry at `https://dsgncli.com/r`
15
+
16
+ ```bash
17
+ dsgn add banner-hero
18
+ dsgn add product-card
19
+ dsgn add social-og-image
20
+ ```
21
+
22
+ **How it works:**
23
+ - Fetches from: `https://dsgncli.com/r/banner-hero`
24
+ - Returns JSON with template files
25
+ - Installs to: `dsgn/templates/banner-hero/`
26
+
27
+ ### Custom Registry
28
+
29
+ Use a different registry:
30
+
31
+ ```bash
32
+ dsgn add banner-hero --registry https://my-registry.com/templates
33
+ ```
34
+
35
+ ## 2. Direct URLs
36
+
37
+ Install a template from any publicly accessible URL:
38
+
39
+ ```bash
40
+ dsgn add https://example.com/templates/my-template.json
41
+ dsgn add https://cdn.example.com/templates/awesome-banner.json
42
+ ```
43
+
44
+ **Requirements:**
45
+ - URL must return JSON in the registry template format
46
+ - Must be publicly accessible (no authentication)
47
+
48
+ **Example template JSON:**
49
+
50
+ ```json
51
+ {
52
+ "name": "my-template",
53
+ "version": "1.0.0",
54
+ "description": "My custom template",
55
+ "files": [
56
+ {
57
+ "path": "my-template.tsx",
58
+ "content": "import React from 'react';\n\nexport default function..."
59
+ },
60
+ {
61
+ "path": "meta.json",
62
+ "content": "{\"name\":\"my-template\"...}"
63
+ }
64
+ ]
65
+ }
66
+ ```
67
+
68
+ ## 3. GitHub Repositories
69
+
70
+ Install templates directly from GitHub repos:
71
+
72
+ ```bash
73
+ # From a GitHub repo (looks for template.json in repo root)
74
+ dsgn add github:username/repo
75
+
76
+ # From a specific path in the repo
77
+ dsgn add github:username/repo/templates/banner-hero
78
+
79
+ # From an organization
80
+ dsgn add github:myorg/design-templates/social-media/og-image
81
+ ```
82
+
83
+ **How it works:**
84
+ - Converts to raw GitHub URLs
85
+ - Fetches `template.json` from the specified path
86
+ - Downloads all referenced files
87
+ - Uses `main` branch by default
88
+
89
+ **Example repo structure:**
90
+
91
+ ```
92
+ username/repo/
93
+ ├── template.json # Required
94
+ ├── banner-hero.tsx
95
+ └── meta.json
96
+ ```
97
+
98
+ Or with path:
99
+
100
+ ```
101
+ username/repo/
102
+ └── templates/
103
+ └── banner-hero/
104
+ ├── template.json # Required
105
+ ├── banner-hero.tsx
106
+ └── meta.json
107
+ ```
108
+
109
+ **template.json format:**
110
+
111
+ ```json
112
+ {
113
+ "name": "banner-hero",
114
+ "version": "1.0.0",
115
+ "description": "Hero banner template",
116
+ "files": [
117
+ {
118
+ "path": "banner-hero.tsx",
119
+ "content": "..."
120
+ },
121
+ {
122
+ "path": "meta.json",
123
+ "content": "..."
124
+ }
125
+ ]
126
+ }
127
+ ```
128
+
129
+ ## 4. Local Filesystem
130
+
131
+ Install templates from your local filesystem:
132
+
133
+ ```bash
134
+ # Relative path
135
+ dsgn add ./my-templates/banner-hero
136
+ dsgn add ../shared-templates/product-card
137
+
138
+ # Absolute path
139
+ dsgn add /Users/you/templates/social-card
140
+ ```
141
+
142
+ **Requirements:**
143
+ - Directory must contain `template.json` or `meta.json`
144
+ - All template files should be in the directory
145
+
146
+ **Example local structure:**
147
+
148
+ ```
149
+ my-templates/banner-hero/
150
+ ├── meta.json # Required (or template.json)
151
+ ├── banner-hero.tsx
152
+ └── assets/
153
+ └── logo.png
154
+ ```
155
+
156
+ **Use cases:**
157
+ - Development and testing
158
+ - Private templates
159
+ - Shared team templates (monorepo)
160
+ - Before publishing to registry
161
+
162
+ ## Template Format
163
+
164
+ All sources must provide templates in this format:
165
+
166
+ ```typescript
167
+ interface RegistryTemplate {
168
+ name: string;
169
+ version: string;
170
+ description: string;
171
+ files: Array<{
172
+ path: string; // Relative path within template folder
173
+ content: string; // File contents
174
+ }>;
175
+ }
176
+ ```
177
+
178
+ ## Examples
179
+
180
+ ### Example 1: Company Templates on GitHub
181
+
182
+ ```bash
183
+ # Install from company repo
184
+ dsgn add github:mycompany/design-templates/marketing/hero-banner
185
+
186
+ # Result: Installs to dsgn/templates/hero-banner/
187
+ ```
188
+
189
+ ### Example 2: Local Development
190
+
191
+ ```bash
192
+ # Create template locally
193
+ mkdir -p my-template
194
+ cd my-template
195
+
196
+ # Create files...
197
+ # (banner.tsx, meta.json, etc.)
198
+
199
+ # Install from local
200
+ cd ../my-project
201
+ dsgn add ../my-template
202
+
203
+ # Test it
204
+ dsgn render banner --props props.json
205
+ ```
206
+
207
+ ### Example 3: Direct URL
208
+
209
+ ```bash
210
+ # Install from CDN
211
+ dsgn add https://cdn.mycompany.com/templates/v2/social-card.json
212
+
213
+ # Install from gist (if formatted correctly)
214
+ dsgn add https://gist.githubusercontent.com/user/id/raw/template.json
215
+ ```
216
+
217
+ ### Example 4: Custom Registry
218
+
219
+ ```bash
220
+ # Team's private registry
221
+ dsgn add product-card --registry https://templates.mycompany.com/api
222
+
223
+ # Alternative registry
224
+ dsgn add banner --registry https://awesome-templates.dev/registry
225
+ ```
226
+
227
+ ## Creating Shareable Templates
228
+
229
+ ### For GitHub
230
+
231
+ 1. Create a repo with your templates:
232
+
233
+ ```
234
+ my-templates/
235
+ ├── README.md
236
+ └── templates/
237
+ ├── banner-hero/
238
+ │ ├── template.json
239
+ │ ├── banner-hero.tsx
240
+ │ └── meta.json
241
+ └── product-card/
242
+ ├── template.json
243
+ ├── product-card.tsx
244
+ └── meta.json
245
+ ```
246
+
247
+ 2. Share installation command:
248
+
249
+ ```bash
250
+ dsgn add github:username/my-templates/templates/banner-hero
251
+ ```
252
+
253
+ ### For Direct URL
254
+
255
+ 1. Host template JSON on a CDN or static site
256
+ 2. Ensure CORS headers allow access
257
+ 3. Share the URL:
258
+
259
+ ```bash
260
+ dsgn add https://my-cdn.com/templates/banner.json
261
+ ```
262
+
263
+ ### For Local Sharing (Teams)
264
+
265
+ 1. Create templates in shared monorepo:
266
+
267
+ ```
268
+ company-monorepo/
269
+ ├── apps/
270
+ ├── packages/
271
+ └── design-templates/
272
+ ├── banner/
273
+ ├── card/
274
+ └── hero/
275
+ ```
276
+
277
+ 2. Team members install with relative paths:
278
+
279
+ ```bash
280
+ dsgn add ../../design-templates/banner
281
+ ```
282
+
283
+ ## Security Considerations
284
+
285
+ ### URLs
286
+ - Only download from trusted sources
287
+ - Review template code before using
288
+ - URLs should use HTTPS
289
+
290
+ ### GitHub
291
+ - Templates from public repos only
292
+ - Review repository before installing
293
+ - Check template contents
294
+
295
+ ### Local
296
+ - Most secure option
297
+ - Full control over template code
298
+ - Good for development/testing
299
+
300
+ ## Troubleshooting
301
+
302
+ ### "Failed to fetch template"
303
+
304
+ **Registry:**
305
+ - Check template name spelling
306
+ - Verify registry is accessible
307
+ - Try custom registry with `--registry`
308
+
309
+ **URL:**
310
+ - Ensure URL is publicly accessible
311
+ - Check URL returns valid JSON
312
+ - Verify CORS headers
313
+
314
+ **GitHub:**
315
+ - Check repo and path exist
316
+ - Ensure `template.json` exists
317
+ - Verify repo is public
318
+ - Branch must be `main`
319
+
320
+ **Local:**
321
+ - Check path is correct
322
+ - Ensure `meta.json` or `template.json` exists
323
+ - Verify file permissions
324
+
325
+ ### "Template already installed"
326
+
327
+ Delete existing template and reinstall:
328
+
329
+ ```bash
330
+ rm -rf dsgn/templates/banner-hero
331
+ dsgn add github:user/repo/banner-hero
332
+ ```
333
+
334
+ ## Advanced: Publishing Your Own Registry
335
+
336
+ Create a registry server that responds to:
337
+
338
+ ```
339
+ GET /your-template
340
+ ```
341
+
342
+ Returns:
343
+
344
+ ```json
345
+ {
346
+ "name": "your-template",
347
+ "version": "1.0.0",
348
+ "description": "...",
349
+ "files": [...]
350
+ }
351
+ ```
352
+
353
+ Users can install with:
354
+
355
+ ```bash
356
+ dsgn add your-template --registry https://your-registry.com
357
+ ```
358
+
359
+ See `ROADMAP.md` for future registry features (versioning, search, marketplace).
360
+
361
+ ---
362
+
363
+ **Pro tip:** Start with local development, then move to GitHub for sharing, and eventually publish to the official registry!
@@ -0,0 +1,57 @@
1
+
2
+ export const meta = {
3
+ name: "banner-hero",
4
+ description: "A hero banner with shadcn design system",
5
+ type: "image",
6
+ size: {
7
+ width: 1600,
8
+ height: 900
9
+ },
10
+ props: {
11
+ title: "string",
12
+ subtitle: "string?",
13
+ image: "string?"
14
+ }
15
+ };
16
+
17
+ interface BannerHeroProps {
18
+ title: string;
19
+ subtitle?: string;
20
+ image?: string;
21
+ config?: any;
22
+ tw?: (classes: string) => any;
23
+ }
24
+
25
+ export default function BannerHero({
26
+ title,
27
+ subtitle,
28
+ image,
29
+ config,
30
+ tw = (classes: string) => ({})
31
+ }: BannerHeroProps) {
32
+ return (
33
+ <div style={tw('w-full h-full flex flex-col justify-center p-20 bg-background')}>
34
+ <div style={tw('bg-card rounded-xl p-16 border flex flex-col')}>
35
+ <h1 style={tw('text-8xl font-bold mb-5 text-foreground')}>
36
+ {title}
37
+ </h1>
38
+
39
+ {subtitle && (
40
+ <p style={tw('text-4xl text-muted-foreground')}>
41
+ {subtitle}
42
+ </p>
43
+ )}
44
+
45
+ {image && (
46
+ <img
47
+ src={image}
48
+ style={{
49
+ ...tw('rounded-lg mt-10'),
50
+ width: '192px',
51
+ }}
52
+ />
53
+ )}
54
+ </div>
55
+ </div>
56
+ );
57
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "banner-hero",
3
+ "description": "A hero banner with shadcn design system",
4
+ "type": "image",
5
+ "size": {
6
+ "width": 1600,
7
+ "height": 900
8
+ },
9
+ "props": {
10
+ "title": "string",
11
+ "subtitle": "string?",
12
+ "image": "string?"
13
+ }
14
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "composite-card",
3
+ "description": "Card that embeds other templates",
4
+ "type": "image",
5
+ "size": {
6
+ "width": 1200,
7
+ "height": 800
8
+ },
9
+ "props": {
10
+ "title": "string",
11
+ "subtitle": "string?",
12
+ "qrUrl": "string?",
13
+ "bannerTitle": "string?",
14
+ "bannerSubtitle": "string?"
15
+ }
16
+ }
@@ -0,0 +1,44 @@
1
+
2
+ // Template metadata is defined in meta.json
3
+
4
+ export default function Template({ title, subtitle, qrUrl, bannerTitle, bannerSubtitle, template, qr, tw }) {
5
+ return (
6
+ <div style={tw('w-full h-full flex flex-col bg-gradient-to-br from-slate-900 to-slate-800 p-12')}>
7
+ {/* Main Content */}
8
+ <div style={tw('bg-white rounded-3xl p-10 flex flex-col shadow-2xl')}>
9
+ {/* Title */}
10
+ <h1 style={tw('text-5xl font-bold text-gray-900 mb-3')}>
11
+ {title}
12
+ </h1>
13
+
14
+ {subtitle && (
15
+ <p style={tw('text-2xl text-gray-600 mb-8')}>
16
+ {subtitle}
17
+ </p>
18
+ )}
19
+
20
+ {/* Embedded Template - pass props directly, uses template's own meta.json for size */}
21
+ <div style={tw('mb-8 rounded-xl overflow-hidden flex')}>
22
+ {template('image', { title: bannerTitle, subtitle: bannerSubtitle })}
23
+ </div>
24
+
25
+ {/* QR Code if URL provided */}
26
+ {qrUrl && (
27
+ <div style={tw('flex items-center gap-6')}>
28
+ <div style={tw('bg-gray-100 p-4 rounded-xl flex')}>
29
+ <img
30
+ src={qr(qrUrl)}
31
+ width={120}
32
+ height={120}
33
+ alt="QR Code"
34
+ />
35
+ </div>
36
+ <p style={tw('text-lg text-gray-700 font-mono flex-1')}>
37
+ {qrUrl}
38
+ </p>
39
+ </div>
40
+ )}
41
+ </div>
42
+ </div>
43
+ );
44
+ }