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.
- package/FONTS.md +156 -0
- package/HELPERS_DEMO.md +134 -0
- package/PROJECT_STRUCTURE.md +286 -0
- package/PUBLISHING.md +171 -0
- package/README.md +1020 -0
- package/REGISTRY_SETUP.md +427 -0
- package/SHADCN_INTEGRATION.md +269 -0
- package/TAILWIND.md +228 -0
- package/TEMPLATE_SOURCES.md +363 -0
- package/_dsgn/templates/banner-hero/banner-hero.tsx +57 -0
- package/_dsgn/templates/banner-hero/meta.json +14 -0
- package/_dsgn/templates/composite-card/meta.json +16 -0
- package/_dsgn/templates/composite-card/template.tsx +44 -0
- package/_dsgn/templates/image/meta.json +13 -0
- package/_dsgn/templates/image/template.tsx +28 -0
- package/_dsgn/templates/kitchen-sink/meta.json +13 -0
- package/_dsgn/templates/kitchen-sink/template.tsx +72 -0
- package/_dsgn/templates/qr-card/meta.json +14 -0
- package/_dsgn/templates/qr-card/template.tsx +39 -0
- package/_dsgn/templates/test-parent/child/meta.json +11 -0
- package/_dsgn/templates/test-parent/child/template.tsx +27 -0
- package/_dsgn/templates/test-parent/meta.json +12 -0
- package/_dsgn/templates/test-parent/template.tsx +30 -0
- package/_dsgn/templates/test-sibling/meta.json +11 -0
- package/_dsgn/templates/test-sibling/template.tsx +20 -0
- package/_dsgn/templates/video/.tmp/template-1763421345296.mjs +43 -0
- package/_dsgn/templates/video/.tmp/template-1763421362228.mjs +43 -0
- package/_dsgn/templates/video/.tmp/template-1763421377706.mjs +43 -0
- package/_dsgn/templates/video/meta.json +17 -0
- package/_dsgn/templates/video/template.tsx +48 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +70 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.d.ts +6 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +86 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/default.d.ts +2 -0
- package/dist/commands/default.d.ts.map +1 -0
- package/dist/commands/default.js +69 -0
- package/dist/commands/default.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +75 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +83 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/preview.d.ts +3 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +296 -0
- package/dist/commands/preview.js.map +1 -0
- package/dist/commands/render.d.ts +10 -0
- package/dist/commands/render.d.ts.map +1 -0
- package/dist/commands/render.js +204 -0
- package/dist/commands/render.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +107 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/default-templates/AGENTS.md +229 -0
- package/dist/default-templates/image/meta.json +13 -0
- package/dist/default-templates/image/template.d.ts +20 -0
- package/dist/default-templates/image/template.d.ts.map +1 -0
- package/dist/default-templates/image/template.js +18 -0
- package/dist/default-templates/image/template.js.map +1 -0
- package/dist/default-templates/image/template.tsx +20 -0
- package/dist/default-templates/image-template/meta.json +13 -0
- package/dist/default-templates/image-template/template.tsx +19 -0
- package/dist/default-templates/kitchen-sink/meta.json +13 -0
- package/dist/default-templates/kitchen-sink/template.tsx +64 -0
- package/dist/default-templates/page/meta.json +17 -0
- package/dist/default-templates/page/template.tsx +37 -0
- package/dist/default-templates/video/meta.json +17 -0
- package/dist/default-templates/video/template.d.ts +26 -0
- package/dist/default-templates/video/template.d.ts.map +1 -0
- package/dist/default-templates/video/template.js +33 -0
- package/dist/default-templates/video/template.js.map +1 -0
- package/dist/default-templates/video/template.tsx +37 -0
- package/dist/default-templates/video-template/meta.json +17 -0
- package/dist/default-templates/video-template/template.tsx +36 -0
- package/dist/default-templates/website/meta.json +16 -0
- package/dist/default-templates/website/pages/home.tsx +17 -0
- package/dist/default-templates/website/parts/footer.tsx +17 -0
- package/dist/default-templates/website/parts/header.tsx +17 -0
- package/dist/default-templates/website/template.tsx +17 -0
- package/dist/default-templates/website-template/meta.json +16 -0
- package/dist/default-templates/website-template/pages/home.tsx +16 -0
- package/dist/default-templates/website-template/parts/footer.tsx +16 -0
- package/dist/default-templates/website-template/parts/header.tsx +16 -0
- package/dist/default-templates/website-template/template.tsx +16 -0
- package/dist/lib/config.d.ts +34 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +248 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +7 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +12 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/helpers.d.ts +29 -0
- package/dist/lib/helpers.d.ts.map +1 -0
- package/dist/lib/helpers.js +159 -0
- package/dist/lib/helpers.js.map +1 -0
- package/dist/lib/installer.d.ts +51 -0
- package/dist/lib/installer.d.ts.map +1 -0
- package/dist/lib/installer.js +215 -0
- package/dist/lib/installer.js.map +1 -0
- package/dist/lib/renderer.d.ts +51 -0
- package/dist/lib/renderer.d.ts.map +1 -0
- package/dist/lib/renderer.js +524 -0
- package/dist/lib/renderer.js.map +1 -0
- package/dist/lib/tailwind-config-loader.d.ts +47 -0
- package/dist/lib/tailwind-config-loader.d.ts.map +1 -0
- package/dist/lib/tailwind-config-loader.js +432 -0
- package/dist/lib/tailwind-config-loader.js.map +1 -0
- package/dist/lib/tailwind-detector.d.ts +36 -0
- package/dist/lib/tailwind-detector.d.ts.map +1 -0
- package/dist/lib/tailwind-detector.js +156 -0
- package/dist/lib/tailwind-detector.js.map +1 -0
- package/dist/lib/tailwind.d.ts +8 -0
- package/dist/lib/tailwind.d.ts.map +1 -0
- package/dist/lib/tailwind.js +994 -0
- package/dist/lib/tailwind.js.map +1 -0
- package/dist/lib/template-validator.d.ts +22 -0
- package/dist/lib/template-validator.d.ts.map +1 -0
- package/dist/lib/template-validator.js +174 -0
- package/dist/lib/template-validator.js.map +1 -0
- package/dist/lib/utils.d.ts +44 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +207 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/version-check.d.ts +16 -0
- package/dist/lib/version-check.d.ts.map +1 -0
- package/dist/lib/version-check.js +88 -0
- package/dist/lib/version-check.js.map +1 -0
- package/dist/lib/video-renderer.d.ts +32 -0
- package/dist/lib/video-renderer.d.ts.map +1 -0
- package/dist/lib/video-renderer.js +226 -0
- package/dist/lib/video-renderer.js.map +1 -0
- package/dist/sdk/index.d.ts +58 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +119 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/template.d.ts +40 -0
- package/dist/sdk/template.d.ts.map +1 -0
- package/dist/sdk/template.js +60 -0
- package/dist/sdk/template.js.map +1 -0
- package/dist/types/config.d.ts +62 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +47 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/template.d.ts +79 -0
- package/dist/types/template.d.ts.map +1 -0
- package/dist/types/template.js +2 -0
- package/dist/types/template.js.map +1 -0
- package/examples/nextjs-api/README.md +180 -0
- package/examples/nextjs-api/package.json +21 -0
- package/examples/nextjs-api/pages/api/intro-video.ts +53 -0
- package/examples/nextjs-api/pages/api/og-image.ts +50 -0
- package/netlify.toml +13 -0
- package/package.json +84 -0
- package/patches/satori+0.18.3.patch +13 -0
- package/test-templates/TESTS.md +63 -0
- package/test-templates/_dsgn/templates/absolute-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/absolute-spin/template.tsx +16 -0
- package/test-templates/_dsgn/templates/animated-intro/.tmp/template-1763468771640.mjs +7 -0
- package/test-templates/_dsgn/templates/animated-intro/meta.json +10 -0
- package/test-templates/_dsgn/templates/animated-intro/template.tsx +23 -0
- package/test-templates/_dsgn/templates/centered-spin/.tmp/template-1763468525386.mjs +7 -0
- package/test-templates/_dsgn/templates/centered-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/centered-spin/template.tsx +11 -0
- package/test-templates/_dsgn/templates/composite/.tmp/template-1763468815645.mjs +7 -0
- package/test-templates/_dsgn/templates/composite/meta.json +9 -0
- package/test-templates/_dsgn/templates/composite/template.tsx +23 -0
- package/test-templates/_dsgn/templates/easing-test/.tmp/template-1763468824501.mjs +7 -0
- package/test-templates/_dsgn/templates/easing-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/easing-test/template.tsx +47 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466364336.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466584319.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466667797.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466746504.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466930225.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467004552.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467060334.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467124493.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467174690.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467359134.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467451928.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467758275.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467985201.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468020563.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468090428.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468211036.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468394057.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/minimal-spin/template.tsx +13 -0
- package/test-templates/_dsgn/templates/no-origin-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/no-origin-spin/template.tsx +10 -0
- package/test-templates/_dsgn/templates/opacity-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/opacity-test/template.tsx +9 -0
- package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468758954.mjs +17 -0
- package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468815672.mjs +17 -0
- package/test-templates/_dsgn/templates/qr-code/meta.json +9 -0
- package/test-templates/_dsgn/templates/qr-code/template.tsx +20 -0
- package/test-templates/_dsgn/templates/rotation-abs-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/rotation-abs-test/template.tsx +15 -0
- package/test-templates/_dsgn/templates/rotation-corner/meta.json +7 -0
- package/test-templates/_dsgn/templates/rotation-corner/template.tsx +12 -0
- package/test-templates/_dsgn/templates/rotation-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/rotation-test/template.tsx +12 -0
- package/test-templates/_dsgn/templates/shake-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/shake-test/template.tsx +12 -0
- package/test-templates/_dsgn/templates/static-image/.tmp/template-1763468746271.mjs +7 -0
- package/test-templates/_dsgn/templates/static-image/meta.json +9 -0
- package/test-templates/_dsgn/templates/static-image/template.tsx +19 -0
- package/test-templates/_dsgn/templates/translate-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/translate-test/template.tsx +9 -0
- package/test-templates/_dsgn/templates/video-loops/.tmp/template-1763468793192.mjs +15 -0
- package/test-templates/_dsgn/templates/video-loops/meta.json +9 -0
- package/test-templates/_dsgn/templates/video-loops/template.tsx +39 -0
- package/test-templates/_dsgn/templates/wrapped-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/wrapped-spin/template.tsx +17 -0
- package/test-templates/compare-svgs.mjs +30 -0
- package/test-templates/convert-frames.mjs +15 -0
- package/test-templates/debug-rotation.mjs +25 -0
- package/test-templates/run-tests.sh +39 -0
- package/test-templates/test-sdk.mjs +115 -0
- package/website/.astro/settings.json +5 -0
- package/website/.astro/types.d.ts +1 -0
- package/website/README.md +112 -0
- package/website/astro.config.mjs +18 -0
- package/website/dist/_astro/fonts.DHdiHGBO.css +1 -0
- package/website/dist/fonts/index.html +193 -0
- package/website/dist/helpers/index.html +166 -0
- package/website/dist/images/index.html +314 -0
- package/website/dist/index.html +219 -0
- package/website/dist/llm.txt +2448 -0
- package/website/dist/styling/index.html +365 -0
- package/website/dist/templates/index.html +124 -0
- package/website/dist/video/index.html +636 -0
- package/website/package-lock.json +7606 -0
- package/website/package.json +23 -0
- 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,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
|
+
}
|