opentwig 1.1.0 → 1.1.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/AGENTS.md +49 -200
- package/package.json +2 -3
- package/src/live-ui/editor.js +1 -0
- package/src/live-ui/sidebar.js +2 -0
- package/src/utils/favicon.js +20 -0
- package/src/utils/loadConfig.js +3 -1
- package/src/utils/setupWatcher.js +2 -2
- package/src/utils/startLiveServer.js +11 -8
- package/theme/default/index.js +2 -0
- package/vitest.config.js +19 -10
- package/website/README.md +42 -0
- package/website/components.json +16 -0
- package/website/eslint.config.js +36 -0
- package/website/package-lock.json +4136 -0
- package/website/package.json +41 -0
- package/website/shadcn-svelte.md +118 -0
- package/website/src/app.d.ts +13 -0
- package/website/src/lib/components/ui/badge/badge.svelte +50 -0
- package/website/src/lib/components/ui/badge/index.ts +2 -0
- package/website/src/lib/components/ui/button/button.svelte +82 -0
- package/website/src/lib/components/ui/button/index.ts +17 -0
- package/website/src/lib/components/ui/card/card-action.svelte +20 -0
- package/website/src/lib/components/ui/card/card-content.svelte +15 -0
- package/website/src/lib/components/ui/card/card-description.svelte +20 -0
- package/website/src/lib/components/ui/card/card-footer.svelte +20 -0
- package/website/src/lib/components/ui/card/card-header.svelte +23 -0
- package/website/src/lib/components/ui/card/card-title.svelte +20 -0
- package/website/src/lib/components/ui/card/card.svelte +23 -0
- package/website/src/lib/components/ui/card/index.ts +25 -0
- package/website/src/lib/components/ui/separator/index.ts +7 -0
- package/website/src/lib/components/ui/separator/separator.svelte +21 -0
- package/website/src/lib/components/ui/tooltip/index.ts +19 -0
- package/website/src/lib/components/ui/tooltip/tooltip-content.svelte +52 -0
- package/website/src/lib/components/ui/tooltip/tooltip-portal.svelte +7 -0
- package/website/src/lib/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/website/src/lib/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/website/src/lib/components/ui/tooltip/tooltip.svelte +7 -0
- package/website/src/lib/index.ts +1 -0
- package/website/src/lib/utils.ts +13 -0
- package/website/src/routes/+layout.svelte +23 -0
- package/website/src/routes/+page.server.ts +82 -0
- package/website/src/routes/+page.svelte +892 -0
- package/website/static/robots.txt +3 -0
- package/website/svelte.config.js +31 -0
- package/website/vite.config.ts +5 -0
- package/test-og.js +0 -40
|
@@ -0,0 +1,892 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button } from "$lib/components/ui/button";
|
|
3
|
+
import {
|
|
4
|
+
Card,
|
|
5
|
+
CardContent,
|
|
6
|
+
CardHeader,
|
|
7
|
+
CardTitle,
|
|
8
|
+
CardDescription,
|
|
9
|
+
} from "$lib/components/ui/card";
|
|
10
|
+
import { Badge } from "$lib/components/ui/badge";
|
|
11
|
+
import { Separator } from "$lib/components/ui/separator";
|
|
12
|
+
import {
|
|
13
|
+
Github,
|
|
14
|
+
Package,
|
|
15
|
+
Star,
|
|
16
|
+
Download,
|
|
17
|
+
Palette,
|
|
18
|
+
Smartphone,
|
|
19
|
+
Zap,
|
|
20
|
+
Code,
|
|
21
|
+
Image,
|
|
22
|
+
QrCode,
|
|
23
|
+
Share2,
|
|
24
|
+
ExternalLink,
|
|
25
|
+
Leaf,
|
|
26
|
+
Command,
|
|
27
|
+
Eye,
|
|
28
|
+
CheckCircle2,
|
|
29
|
+
ArrowRight,
|
|
30
|
+
Sparkles,
|
|
31
|
+
Copy,
|
|
32
|
+
Check,
|
|
33
|
+
} from "@lucide/svelte";
|
|
34
|
+
|
|
35
|
+
import {
|
|
36
|
+
Tooltip,
|
|
37
|
+
TooltipContent,
|
|
38
|
+
TooltipProvider,
|
|
39
|
+
TooltipTrigger,
|
|
40
|
+
} from "$lib/components/ui/tooltip";
|
|
41
|
+
import type { PageData } from "./$types";
|
|
42
|
+
|
|
43
|
+
let { data }: { data: PageData } = $props();
|
|
44
|
+
|
|
45
|
+
let copied = $state(false);
|
|
46
|
+
|
|
47
|
+
const installCommand = "npx opentwig --init";
|
|
48
|
+
|
|
49
|
+
function copyCommand() {
|
|
50
|
+
navigator.clipboard.writeText(installCommand);
|
|
51
|
+
copied = true;
|
|
52
|
+
setTimeout(() => (copied = false), 2000);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const features = [
|
|
56
|
+
{
|
|
57
|
+
icon: Palette,
|
|
58
|
+
title: "4 Beautiful Themes",
|
|
59
|
+
description:
|
|
60
|
+
"Choose from default, dark, minimal, and colorful themes. Each crafted with attention to detail.",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
icon: Smartphone,
|
|
64
|
+
title: "Mobile First",
|
|
65
|
+
description:
|
|
66
|
+
"Perfectly responsive design that looks stunning on any device, from phones to desktops.",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
icon: Zap,
|
|
70
|
+
title: "Lightning Fast",
|
|
71
|
+
description:
|
|
72
|
+
"Generates static HTML/CSS with zero JavaScript dependencies. Instant page loads.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
icon: Eye,
|
|
76
|
+
title: "Live Preview Mode",
|
|
77
|
+
description:
|
|
78
|
+
"Interactive editor with real-time preview. Edit config, see changes instantly.",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
icon: Image,
|
|
82
|
+
title: "Social Previews",
|
|
83
|
+
description:
|
|
84
|
+
"Auto-generated Open Graph images for perfect sharing on social media platforms.",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
icon: QrCode,
|
|
88
|
+
title: "QR Code Built-in",
|
|
89
|
+
description:
|
|
90
|
+
"Every page includes a QR code for easy mobile sharing and offline distribution.",
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
const themes = [
|
|
95
|
+
{
|
|
96
|
+
name: "Default",
|
|
97
|
+
description: "Clean & Modern",
|
|
98
|
+
style: "bg-gradient-to-br from-slate-50 to-slate-100 border-slate-200",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "Dark",
|
|
102
|
+
description: "Elegant & Sophisticated",
|
|
103
|
+
style: "bg-gradient-to-br from-slate-900 to-slate-800 border-slate-700",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: "Minimal",
|
|
107
|
+
description: "Simple & Focused",
|
|
108
|
+
style: "bg-gradient-to-br from-gray-50 to-white border-gray-200",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "Colorful",
|
|
112
|
+
description: "Vibrant & Bold",
|
|
113
|
+
style: "bg-gradient-to-br from-indigo-500 via-purple-500 to-pink-500",
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<TooltipProvider>
|
|
119
|
+
<div class="min-h-screen bg-background leaf-pattern">
|
|
120
|
+
<!-- Navigation -->
|
|
121
|
+
<nav
|
|
122
|
+
class="sticky top-0 z-50 w-full border-b border-border/50 bg-background/80 backdrop-blur-md"
|
|
123
|
+
>
|
|
124
|
+
<div
|
|
125
|
+
class="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:px-6 lg:px-8"
|
|
126
|
+
>
|
|
127
|
+
<div class="flex items-center gap-2">
|
|
128
|
+
<Leaf class="h-6 w-6 text-primary" />
|
|
129
|
+
<span class="text-xl font-bold tracking-tight"
|
|
130
|
+
>OpenTwig</span
|
|
131
|
+
>
|
|
132
|
+
</div>
|
|
133
|
+
<div class="flex items-center gap-4">
|
|
134
|
+
<a
|
|
135
|
+
href="https://github.com/tufantunc/opentwig"
|
|
136
|
+
target="_blank"
|
|
137
|
+
rel="noopener noreferrer"
|
|
138
|
+
class="flex items-center gap-2 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground"
|
|
139
|
+
>
|
|
140
|
+
<Github class="h-4 w-4" />
|
|
141
|
+
<span class="hidden sm:inline">GitHub</span>
|
|
142
|
+
</a>
|
|
143
|
+
<a
|
|
144
|
+
href="https://www.npmjs.com/package/opentwig"
|
|
145
|
+
target="_blank"
|
|
146
|
+
rel="noopener noreferrer"
|
|
147
|
+
class="flex items-center gap-2 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground"
|
|
148
|
+
>
|
|
149
|
+
<Package class="h-4 w-4" />
|
|
150
|
+
<span class="hidden sm:inline">NPM</span>
|
|
151
|
+
</a>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
</nav>
|
|
155
|
+
|
|
156
|
+
<!-- Hero Section -->
|
|
157
|
+
<section
|
|
158
|
+
class="relative overflow-hidden px-4 py-20 sm:px-6 sm:py-32 lg:px-8"
|
|
159
|
+
>
|
|
160
|
+
<div class="mx-auto max-w-4xl text-center">
|
|
161
|
+
<!-- Badge -->
|
|
162
|
+
<div class="mb-8 flex justify-center">
|
|
163
|
+
<Badge
|
|
164
|
+
variant="secondary"
|
|
165
|
+
class="gap-1.5 px-3 py-1.5 text-sm font-medium"
|
|
166
|
+
>
|
|
167
|
+
<Sparkles class="h-3.5 w-3.5" />
|
|
168
|
+
<span>100% Free & Open Source</span>
|
|
169
|
+
</Badge>
|
|
170
|
+
</div>
|
|
171
|
+
|
|
172
|
+
<!-- Headline -->
|
|
173
|
+
<h1
|
|
174
|
+
class="mb-6 text-4xl font-extrabold tracking-tight text-foreground sm:text-5xl md:text-6xl lg:text-7xl"
|
|
175
|
+
>
|
|
176
|
+
Create Your
|
|
177
|
+
<span class="gradient-text">Link in Bio</span>
|
|
178
|
+
Page
|
|
179
|
+
</h1>
|
|
180
|
+
|
|
181
|
+
<!-- Subheadline -->
|
|
182
|
+
<p
|
|
183
|
+
class="mx-auto mb-10 max-w-2xl text-lg text-muted-foreground sm:text-xl"
|
|
184
|
+
>
|
|
185
|
+
A beautiful, customizable link page generator that puts you
|
|
186
|
+
in control. No third-party services. No tracking. Just you
|
|
187
|
+
and your links.
|
|
188
|
+
</p>
|
|
189
|
+
|
|
190
|
+
<!-- CTAs -->
|
|
191
|
+
<div
|
|
192
|
+
class="flex flex-col items-center justify-center gap-4 sm:flex-row"
|
|
193
|
+
>
|
|
194
|
+
<Tooltip>
|
|
195
|
+
<TooltipTrigger>
|
|
196
|
+
<Button
|
|
197
|
+
size="lg"
|
|
198
|
+
class="gap-2 px-8"
|
|
199
|
+
href="https://github.com/tufantunc/opentwig"
|
|
200
|
+
target="_blank"
|
|
201
|
+
rel="noopener noreferrer"
|
|
202
|
+
>
|
|
203
|
+
<Github class="h-5 w-5" />
|
|
204
|
+
<span>Star on GitHub</span>
|
|
205
|
+
</Button>
|
|
206
|
+
</TooltipTrigger>
|
|
207
|
+
<TooltipContent>
|
|
208
|
+
<p>Show your support!</p>
|
|
209
|
+
</TooltipContent>
|
|
210
|
+
</Tooltip>
|
|
211
|
+
|
|
212
|
+
<Button
|
|
213
|
+
variant="outline"
|
|
214
|
+
size="lg"
|
|
215
|
+
class="gap-2 px-8"
|
|
216
|
+
href="#get-started"
|
|
217
|
+
>
|
|
218
|
+
<Command class="h-5 w-5" />
|
|
219
|
+
<span>Get Started</span>
|
|
220
|
+
</Button>
|
|
221
|
+
</div>
|
|
222
|
+
|
|
223
|
+
<!-- Stats Bar -->
|
|
224
|
+
<div
|
|
225
|
+
class="mt-16 grid grid-cols-2 gap-8 border-y border-border/50 py-8 sm:grid-cols-4"
|
|
226
|
+
>
|
|
227
|
+
<div class="text-center">
|
|
228
|
+
<div
|
|
229
|
+
class="flex items-center justify-center gap-1.5 text-3xl font-bold text-foreground"
|
|
230
|
+
>
|
|
231
|
+
<Download class="h-6 w-6 text-primary" />
|
|
232
|
+
<span>{data.stats.formattedNpmDownloads}</span>
|
|
233
|
+
</div>
|
|
234
|
+
<p class="mt-1 text-sm text-muted-foreground">
|
|
235
|
+
NPM Downloads
|
|
236
|
+
</p>
|
|
237
|
+
</div>
|
|
238
|
+
<div class="text-center">
|
|
239
|
+
<div
|
|
240
|
+
class="flex items-center justify-center gap-1.5 text-3xl font-bold text-foreground"
|
|
241
|
+
>
|
|
242
|
+
<Star class="h-6 w-6 text-primary" />
|
|
243
|
+
<span>{data.stats.formattedGithubStars}</span>
|
|
244
|
+
</div>
|
|
245
|
+
<p class="mt-1 text-sm text-muted-foreground">
|
|
246
|
+
GitHub Stars
|
|
247
|
+
</p>
|
|
248
|
+
</div>
|
|
249
|
+
<div class="text-center">
|
|
250
|
+
<div
|
|
251
|
+
class="flex items-center justify-center gap-1.5 text-3xl font-bold text-foreground"
|
|
252
|
+
>
|
|
253
|
+
<Palette class="h-6 w-6 text-primary" />
|
|
254
|
+
<span>4</span>
|
|
255
|
+
</div>
|
|
256
|
+
<p class="mt-1 text-sm text-muted-foreground">Themes</p>
|
|
257
|
+
</div>
|
|
258
|
+
<div class="text-center">
|
|
259
|
+
<div
|
|
260
|
+
class="flex items-center justify-center gap-1.5 text-3xl font-bold text-foreground"
|
|
261
|
+
>
|
|
262
|
+
<CheckCircle2 class="h-6 w-6 text-primary" />
|
|
263
|
+
<span>MIT</span>
|
|
264
|
+
</div>
|
|
265
|
+
<p class="mt-1 text-sm text-muted-foreground">
|
|
266
|
+
License
|
|
267
|
+
</p>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
</section>
|
|
272
|
+
|
|
273
|
+
<!-- Features Section -->
|
|
274
|
+
<section id="features" class="px-4 py-20 sm:px-6 lg:px-8">
|
|
275
|
+
<div class="mx-auto max-w-7xl">
|
|
276
|
+
<div class="mb-16 text-center">
|
|
277
|
+
<h2
|
|
278
|
+
class="mb-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl"
|
|
279
|
+
>
|
|
280
|
+
Everything You Need
|
|
281
|
+
</h2>
|
|
282
|
+
<p class="mx-auto max-w-2xl text-lg text-muted-foreground">
|
|
283
|
+
Powerful features packed into a simple CLI tool. No
|
|
284
|
+
bloat, no dependencies, just results.
|
|
285
|
+
</p>
|
|
286
|
+
</div>
|
|
287
|
+
|
|
288
|
+
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
|
289
|
+
{#each features as feature}
|
|
290
|
+
<Card
|
|
291
|
+
class="group relative overflow-hidden transition-all hover:shadow-lg hover:border-primary/20"
|
|
292
|
+
>
|
|
293
|
+
<CardHeader>
|
|
294
|
+
<div
|
|
295
|
+
class="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-xl bg-primary/10 text-primary transition-colors group-hover:bg-primary group-hover:text-primary-foreground"
|
|
296
|
+
>
|
|
297
|
+
<feature.icon class="h-6 w-6" />
|
|
298
|
+
</div>
|
|
299
|
+
<CardTitle class="text-xl"
|
|
300
|
+
>{feature.title}</CardTitle
|
|
301
|
+
>
|
|
302
|
+
<CardDescription class="text-base">
|
|
303
|
+
{feature.description}
|
|
304
|
+
</CardDescription>
|
|
305
|
+
</CardHeader>
|
|
306
|
+
</Card>
|
|
307
|
+
{/each}
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
</section>
|
|
311
|
+
|
|
312
|
+
<Separator class="mx-auto max-w-7xl" />
|
|
313
|
+
|
|
314
|
+
<!-- Live Preview Demo Section -->
|
|
315
|
+
<section class="px-4 py-20 sm:px-6 lg:px-8">
|
|
316
|
+
<div class="mx-auto max-w-7xl">
|
|
317
|
+
<div class="mb-12 text-center">
|
|
318
|
+
<h2
|
|
319
|
+
class="mb-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl"
|
|
320
|
+
>
|
|
321
|
+
Live Preview Mode
|
|
322
|
+
</h2>
|
|
323
|
+
<p class="mx-auto max-w-2xl text-lg text-muted-foreground">
|
|
324
|
+
Edit your configuration in real-time with our built-in
|
|
325
|
+
live editor. See changes instantly.
|
|
326
|
+
</p>
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
<!-- Screenshot Placeholder -->
|
|
330
|
+
<div class="relative mx-auto max-w-5xl">
|
|
331
|
+
<div
|
|
332
|
+
class="relative overflow-hidden rounded-2xl border border-border bg-card shadow-2xl"
|
|
333
|
+
>
|
|
334
|
+
<!-- Browser Chrome -->
|
|
335
|
+
<div
|
|
336
|
+
class="flex items-center gap-2 border-b border-border bg-muted/50 px-4 py-3"
|
|
337
|
+
>
|
|
338
|
+
<div class="flex gap-1.5">
|
|
339
|
+
<div
|
|
340
|
+
class="h-3 w-3 rounded-full bg-red-400"
|
|
341
|
+
></div>
|
|
342
|
+
<div
|
|
343
|
+
class="h-3 w-3 rounded-full bg-yellow-400"
|
|
344
|
+
></div>
|
|
345
|
+
<div
|
|
346
|
+
class="h-3 w-3 rounded-full bg-green-400"
|
|
347
|
+
></div>
|
|
348
|
+
</div>
|
|
349
|
+
<div
|
|
350
|
+
class="ml-4 flex-1 rounded-md bg-background px-3 py-1 text-xs text-muted-foreground"
|
|
351
|
+
>
|
|
352
|
+
localhost:3000
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
|
|
356
|
+
<!-- Placeholder Content -->
|
|
357
|
+
<div
|
|
358
|
+
class="relative overflow-hidden rounded-lg border border-border bg-background shadow-2xl"
|
|
359
|
+
>
|
|
360
|
+
<img
|
|
361
|
+
src="/live-editor.png"
|
|
362
|
+
alt="OpenTwig Live Editor Interface"
|
|
363
|
+
class="w-full h-auto object-cover"
|
|
364
|
+
loading="lazy"
|
|
365
|
+
/>
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
<!-- Floating Features -->
|
|
370
|
+
<div
|
|
371
|
+
class="absolute -right-4 top-1/4 hidden lg:block animate-float"
|
|
372
|
+
>
|
|
373
|
+
<div
|
|
374
|
+
class="rounded-xl border border-border bg-card p-4 shadow-lg"
|
|
375
|
+
>
|
|
376
|
+
<div class="flex items-center gap-2 text-sm">
|
|
377
|
+
<Palette class="h-4 w-4 text-primary" />
|
|
378
|
+
<span>Theme switcher</span>
|
|
379
|
+
</div>
|
|
380
|
+
</div>
|
|
381
|
+
</div>
|
|
382
|
+
|
|
383
|
+
<div
|
|
384
|
+
class="absolute -left-4 bottom-1/4 hidden lg:block animate-float-delayed"
|
|
385
|
+
>
|
|
386
|
+
<div
|
|
387
|
+
class="rounded-xl border border-border bg-card p-4 shadow-lg"
|
|
388
|
+
>
|
|
389
|
+
<div class="flex items-center gap-2 text-sm">
|
|
390
|
+
<Eye class="h-4 w-4 text-primary" />
|
|
391
|
+
<span>Live Preview</span>
|
|
392
|
+
</div>
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
395
|
+
|
|
396
|
+
<div
|
|
397
|
+
class="absolute -right-4 bottom-8 hidden lg:block animate-float"
|
|
398
|
+
>
|
|
399
|
+
<div
|
|
400
|
+
class="rounded-xl border border-border bg-card p-4 shadow-lg"
|
|
401
|
+
>
|
|
402
|
+
<div class="flex items-center gap-3">
|
|
403
|
+
<div
|
|
404
|
+
class="h-2 w-2 rounded-full bg-green-500 animate-pulse"
|
|
405
|
+
></div>
|
|
406
|
+
<span class="text-sm font-medium"
|
|
407
|
+
>Auto-save enabled</span
|
|
408
|
+
>
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
</div>
|
|
412
|
+
</div>
|
|
413
|
+
|
|
414
|
+
<!-- Feature List -->
|
|
415
|
+
<div class="mt-12 grid gap-6 sm:grid-cols-3">
|
|
416
|
+
<div class="flex items-start gap-3">
|
|
417
|
+
<div
|
|
418
|
+
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary/10 text-primary"
|
|
419
|
+
>
|
|
420
|
+
<CheckCircle2 class="h-4 w-4" />
|
|
421
|
+
</div>
|
|
422
|
+
<div>
|
|
423
|
+
<h4 class="font-semibold text-foreground">
|
|
424
|
+
Real-time Updates
|
|
425
|
+
</h4>
|
|
426
|
+
<p class="text-sm text-muted-foreground">
|
|
427
|
+
See changes as you type with WebSocket-powered
|
|
428
|
+
live reload
|
|
429
|
+
</p>
|
|
430
|
+
</div>
|
|
431
|
+
</div>
|
|
432
|
+
<div class="flex items-start gap-3">
|
|
433
|
+
<div
|
|
434
|
+
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary/10 text-primary"
|
|
435
|
+
>
|
|
436
|
+
<CheckCircle2 class="h-4 w-4" />
|
|
437
|
+
</div>
|
|
438
|
+
<div>
|
|
439
|
+
<h4 class="font-semibold text-foreground">
|
|
440
|
+
Drag & Drop
|
|
441
|
+
</h4>
|
|
442
|
+
<p class="text-sm text-muted-foreground">
|
|
443
|
+
Easily reorder your links with intuitive drag
|
|
444
|
+
and drop
|
|
445
|
+
</p>
|
|
446
|
+
</div>
|
|
447
|
+
</div>
|
|
448
|
+
<div class="flex items-start gap-3">
|
|
449
|
+
<div
|
|
450
|
+
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary/10 text-primary"
|
|
451
|
+
>
|
|
452
|
+
<CheckCircle2 class="h-4 w-4" />
|
|
453
|
+
</div>
|
|
454
|
+
<div>
|
|
455
|
+
<h4 class="font-semibold text-foreground">
|
|
456
|
+
Avatar Upload
|
|
457
|
+
</h4>
|
|
458
|
+
<p class="text-sm text-muted-foreground">
|
|
459
|
+
Upload and preview profile pictures directly in
|
|
460
|
+
the editor
|
|
461
|
+
</p>
|
|
462
|
+
</div>
|
|
463
|
+
</div>
|
|
464
|
+
</div>
|
|
465
|
+
</div>
|
|
466
|
+
</section>
|
|
467
|
+
|
|
468
|
+
<Separator class="mx-auto max-w-7xl" />
|
|
469
|
+
|
|
470
|
+
<!-- Themes Showcase -->
|
|
471
|
+
<section id="themes" class="px-4 py-20 sm:px-6 lg:px-8">
|
|
472
|
+
<div class="mx-auto max-w-7xl">
|
|
473
|
+
<div class="mb-12 text-center">
|
|
474
|
+
<h2
|
|
475
|
+
class="mb-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl"
|
|
476
|
+
>
|
|
477
|
+
Choose Your Style
|
|
478
|
+
</h2>
|
|
479
|
+
<p class="mx-auto max-w-2xl text-lg text-muted-foreground">
|
|
480
|
+
Four carefully crafted themes to match your personality
|
|
481
|
+
and brand.
|
|
482
|
+
</p>
|
|
483
|
+
</div>
|
|
484
|
+
|
|
485
|
+
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
|
486
|
+
{#each themes as theme}
|
|
487
|
+
<Card
|
|
488
|
+
class="group overflow-hidden transition-all hover:shadow-lg"
|
|
489
|
+
>
|
|
490
|
+
<!-- Theme Preview -->
|
|
491
|
+
<div
|
|
492
|
+
class="relative aspect-[4/3] overflow-hidden border-b"
|
|
493
|
+
>
|
|
494
|
+
<img
|
|
495
|
+
src="/theme-{theme.name.toLowerCase()}.png"
|
|
496
|
+
alt="{theme.name} theme preview"
|
|
497
|
+
class="h-full w-full object-cover object-top transition-transform duration-500 group-hover:scale-105"
|
|
498
|
+
loading="lazy"
|
|
499
|
+
/>
|
|
500
|
+
</div>
|
|
501
|
+
<CardHeader class="text-center">
|
|
502
|
+
<CardTitle class="text-lg"
|
|
503
|
+
>{theme.name}</CardTitle
|
|
504
|
+
>
|
|
505
|
+
<CardDescription
|
|
506
|
+
>{theme.description}</CardDescription
|
|
507
|
+
>
|
|
508
|
+
</CardHeader>
|
|
509
|
+
</Card>
|
|
510
|
+
{/each}
|
|
511
|
+
</div>
|
|
512
|
+
|
|
513
|
+
<!-- Theme Preview Screenshots Row -->
|
|
514
|
+
<div class="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
|
515
|
+
{#each themes as theme, i}
|
|
516
|
+
<div
|
|
517
|
+
class="relative aspect-[9/16] overflow-hidden rounded-xl border border-border bg-card shadow-lg"
|
|
518
|
+
>
|
|
519
|
+
<img
|
|
520
|
+
src="/theme-{theme.name.toLowerCase()}.png"
|
|
521
|
+
alt="{theme.name} theme preview"
|
|
522
|
+
class="h-full w-full object-cover object-top transition-transform duration-500 group-hover:scale-105"
|
|
523
|
+
loading="lazy"
|
|
524
|
+
/>
|
|
525
|
+
<div
|
|
526
|
+
class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent"
|
|
527
|
+
></div>
|
|
528
|
+
<div
|
|
529
|
+
class="absolute bottom-0 left-0 right-0 p-4 text-white"
|
|
530
|
+
>
|
|
531
|
+
<p class="text-sm font-semibold">
|
|
532
|
+
{theme.name}
|
|
533
|
+
</p>
|
|
534
|
+
<p class="text-xs text-white/80">
|
|
535
|
+
{theme.description}
|
|
536
|
+
</p>
|
|
537
|
+
</div>
|
|
538
|
+
</div>
|
|
539
|
+
{/each}
|
|
540
|
+
</div>
|
|
541
|
+
</div>
|
|
542
|
+
</section>
|
|
543
|
+
|
|
544
|
+
<Separator class="mx-auto max-w-7xl" />
|
|
545
|
+
|
|
546
|
+
<!-- Quick Start Section -->
|
|
547
|
+
<section id="get-started" class="px-4 py-20 sm:px-6 lg:px-8">
|
|
548
|
+
<div class="mx-auto max-w-3xl">
|
|
549
|
+
<div class="mb-12 text-center">
|
|
550
|
+
<h2
|
|
551
|
+
class="mb-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl"
|
|
552
|
+
>
|
|
553
|
+
Get Started in Seconds
|
|
554
|
+
</h2>
|
|
555
|
+
<p class="mx-auto max-w-2xl text-lg text-muted-foreground">
|
|
556
|
+
No complex setup. Just run one command and you're ready
|
|
557
|
+
to go.
|
|
558
|
+
</p>
|
|
559
|
+
</div>
|
|
560
|
+
|
|
561
|
+
<!-- Installation Card -->
|
|
562
|
+
<Card class="overflow-hidden">
|
|
563
|
+
<CardHeader class="bg-muted/50">
|
|
564
|
+
<CardTitle class="flex items-center gap-2 text-lg">
|
|
565
|
+
<Command class="h-5 w-5 text-primary" />
|
|
566
|
+
Installation
|
|
567
|
+
</CardTitle>
|
|
568
|
+
</CardHeader>
|
|
569
|
+
<CardContent class="p-6">
|
|
570
|
+
<div class="relative">
|
|
571
|
+
<pre
|
|
572
|
+
class="relative overflow-x-auto rounded-lg bg-[#1a3320] p-4 text-sm text-[#e8f0e8]"><code
|
|
573
|
+
>{installCommand}</code
|
|
574
|
+
></pre>
|
|
575
|
+
<Button
|
|
576
|
+
variant="ghost"
|
|
577
|
+
size="sm"
|
|
578
|
+
class="absolute right-2 top-2 gap-1.5 text-[#e8f0e8] hover:bg-[#2d4a35] hover:text-[#e8f0e8]"
|
|
579
|
+
onclick={copyCommand}
|
|
580
|
+
>
|
|
581
|
+
{#if copied}
|
|
582
|
+
<Check class="h-4 w-4" />
|
|
583
|
+
<span>Copied!</span>
|
|
584
|
+
{:else}
|
|
585
|
+
<Copy class="h-4 w-4" />
|
|
586
|
+
<span>Copy</span>
|
|
587
|
+
{/if}
|
|
588
|
+
</Button>
|
|
589
|
+
</div>
|
|
590
|
+
</CardContent>
|
|
591
|
+
</Card>
|
|
592
|
+
|
|
593
|
+
<!-- Steps -->
|
|
594
|
+
<div class="mt-8 space-y-4">
|
|
595
|
+
<div class="flex items-start gap-4">
|
|
596
|
+
<div
|
|
597
|
+
class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground font-bold"
|
|
598
|
+
>
|
|
599
|
+
1
|
|
600
|
+
</div>
|
|
601
|
+
<div class="flex-1 pt-2">
|
|
602
|
+
<h4 class="font-semibold text-foreground">
|
|
603
|
+
Initialize your project
|
|
604
|
+
</h4>
|
|
605
|
+
<p class="text-sm text-muted-foreground">
|
|
606
|
+
Run the command above to create a sample
|
|
607
|
+
config.json file
|
|
608
|
+
</p>
|
|
609
|
+
</div>
|
|
610
|
+
</div>
|
|
611
|
+
|
|
612
|
+
<div class="flex items-start gap-4">
|
|
613
|
+
<div
|
|
614
|
+
class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground font-bold"
|
|
615
|
+
>
|
|
616
|
+
2
|
|
617
|
+
</div>
|
|
618
|
+
<div class="flex-1 pt-2">
|
|
619
|
+
<h4 class="font-semibold text-foreground">
|
|
620
|
+
Edit your configuration
|
|
621
|
+
</h4>
|
|
622
|
+
<p class="text-sm text-muted-foreground">
|
|
623
|
+
Customize your links, bio, theme, and avatar in
|
|
624
|
+
config.json
|
|
625
|
+
</p>
|
|
626
|
+
</div>
|
|
627
|
+
</div>
|
|
628
|
+
|
|
629
|
+
<div class="flex items-start gap-4">
|
|
630
|
+
<div
|
|
631
|
+
class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground font-bold"
|
|
632
|
+
>
|
|
633
|
+
3
|
|
634
|
+
</div>
|
|
635
|
+
<div class="flex-1 pt-2">
|
|
636
|
+
<h4 class="font-semibold text-foreground">
|
|
637
|
+
Generate your page
|
|
638
|
+
</h4>
|
|
639
|
+
<p class="text-sm text-muted-foreground">
|
|
640
|
+
Run <code
|
|
641
|
+
class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono"
|
|
642
|
+
>npx opentwig</code
|
|
643
|
+
> to build your static site
|
|
644
|
+
</p>
|
|
645
|
+
</div>
|
|
646
|
+
</div>
|
|
647
|
+
|
|
648
|
+
<div class="flex items-start gap-4">
|
|
649
|
+
<div
|
|
650
|
+
class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground font-bold"
|
|
651
|
+
>
|
|
652
|
+
4
|
|
653
|
+
</div>
|
|
654
|
+
<div class="flex-1 pt-2">
|
|
655
|
+
<h4 class="font-semibold text-foreground">
|
|
656
|
+
Deploy anywhere
|
|
657
|
+
</h4>
|
|
658
|
+
<p class="text-sm text-muted-foreground">
|
|
659
|
+
Upload the dist/ folder to GitHub Pages,
|
|
660
|
+
Netlify, Vercel, or any static host
|
|
661
|
+
</p>
|
|
662
|
+
</div>
|
|
663
|
+
</div>
|
|
664
|
+
</div>
|
|
665
|
+
|
|
666
|
+
<!-- Live Mode CTA -->
|
|
667
|
+
<Card class="mt-8 border-primary/20 bg-primary/5">
|
|
668
|
+
<CardContent
|
|
669
|
+
class="flex flex-col items-center gap-4 p-6 text-center sm:flex-row sm:text-left"
|
|
670
|
+
>
|
|
671
|
+
<div
|
|
672
|
+
class="flex h-12 w-12 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground"
|
|
673
|
+
>
|
|
674
|
+
<Zap class="h-6 w-6" />
|
|
675
|
+
</div>
|
|
676
|
+
<div class="flex-1">
|
|
677
|
+
<h4 class="font-semibold text-foreground">
|
|
678
|
+
Prefer a visual editor?
|
|
679
|
+
</h4>
|
|
680
|
+
<p class="text-sm text-muted-foreground">
|
|
681
|
+
Use our live preview mode with real-time editing
|
|
682
|
+
and auto-save
|
|
683
|
+
</p>
|
|
684
|
+
</div>
|
|
685
|
+
<Button variant="outline" class="gap-2">
|
|
686
|
+
<span>npx opentwig --live</span>
|
|
687
|
+
<ArrowRight class="h-4 w-4" />
|
|
688
|
+
</Button>
|
|
689
|
+
</CardContent>
|
|
690
|
+
</Card>
|
|
691
|
+
</div>
|
|
692
|
+
</section>
|
|
693
|
+
|
|
694
|
+
<Separator class="mx-auto max-w-7xl" />
|
|
695
|
+
|
|
696
|
+
<!-- Open Source Banner -->
|
|
697
|
+
<section class="px-4 py-20 sm:px-6 lg:px-8">
|
|
698
|
+
<div class="mx-auto max-w-4xl text-center">
|
|
699
|
+
<div
|
|
700
|
+
class="mb-8 inline-flex h-20 w-20 items-center justify-center rounded-2xl bg-primary/10"
|
|
701
|
+
>
|
|
702
|
+
<svg
|
|
703
|
+
class="h-10 w-10 text-primary"
|
|
704
|
+
viewBox="0 0 24 24"
|
|
705
|
+
fill="none"
|
|
706
|
+
stroke="currentColor"
|
|
707
|
+
stroke-width="2"
|
|
708
|
+
stroke-linecap="round"
|
|
709
|
+
stroke-linejoin="round"
|
|
710
|
+
>
|
|
711
|
+
<path
|
|
712
|
+
d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"
|
|
713
|
+
/>
|
|
714
|
+
</svg>
|
|
715
|
+
</div>
|
|
716
|
+
<h2
|
|
717
|
+
class="mb-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl"
|
|
718
|
+
>
|
|
719
|
+
Built with Love, Free Forever
|
|
720
|
+
</h2>
|
|
721
|
+
<p class="mx-auto mb-8 max-w-2xl text-lg text-muted-foreground">
|
|
722
|
+
OpenTwig is and always will be 100% free and open source. No
|
|
723
|
+
hidden fees, no premium tiers, no tracking. Just a tool
|
|
724
|
+
built by the community, for the community.
|
|
725
|
+
</p>
|
|
726
|
+
<div class="flex flex-wrap items-center justify-center gap-4">
|
|
727
|
+
<Badge
|
|
728
|
+
variant="secondary"
|
|
729
|
+
class="gap-1.5 px-4 py-2 text-sm"
|
|
730
|
+
>
|
|
731
|
+
<CheckCircle2 class="h-4 w-4" />
|
|
732
|
+
<span>MIT Licensed</span>
|
|
733
|
+
</Badge>
|
|
734
|
+
<Badge
|
|
735
|
+
variant="secondary"
|
|
736
|
+
class="gap-1.5 px-4 py-2 text-sm"
|
|
737
|
+
>
|
|
738
|
+
<CheckCircle2 class="h-4 w-4" />
|
|
739
|
+
<span>No Tracking</span>
|
|
740
|
+
</Badge>
|
|
741
|
+
<Badge
|
|
742
|
+
variant="secondary"
|
|
743
|
+
class="gap-1.5 px-4 py-2 text-sm"
|
|
744
|
+
>
|
|
745
|
+
<CheckCircle2 class="h-4 w-4" />
|
|
746
|
+
<span>No Vendor Lock-in</span>
|
|
747
|
+
</Badge>
|
|
748
|
+
</div>
|
|
749
|
+
</div>
|
|
750
|
+
</section>
|
|
751
|
+
|
|
752
|
+
<!-- Footer -->
|
|
753
|
+
<footer
|
|
754
|
+
class="border-t border-border bg-muted/30 px-4 py-12 sm:px-6 lg:px-8"
|
|
755
|
+
>
|
|
756
|
+
<div class="mx-auto max-w-7xl">
|
|
757
|
+
<div class="grid gap-8 sm:grid-cols-2 lg:grid-cols-4">
|
|
758
|
+
<div>
|
|
759
|
+
<div class="flex items-center gap-2 mb-4">
|
|
760
|
+
<Leaf class="h-5 w-5 text-primary" />
|
|
761
|
+
<span class="font-bold">OpenTwig</span>
|
|
762
|
+
</div>
|
|
763
|
+
<p class="text-sm text-muted-foreground">
|
|
764
|
+
Free and open source link in bio page generator.
|
|
765
|
+
</p>
|
|
766
|
+
</div>
|
|
767
|
+
|
|
768
|
+
<div>
|
|
769
|
+
<h4 class="mb-4 font-semibold text-foreground">
|
|
770
|
+
Product
|
|
771
|
+
</h4>
|
|
772
|
+
<ul class="space-y-2 text-sm">
|
|
773
|
+
<li>
|
|
774
|
+
<a
|
|
775
|
+
href="#features"
|
|
776
|
+
class="text-muted-foreground transition-colors hover:text-foreground"
|
|
777
|
+
>Features</a
|
|
778
|
+
>
|
|
779
|
+
</li>
|
|
780
|
+
<li>
|
|
781
|
+
<a
|
|
782
|
+
href="#themes"
|
|
783
|
+
class="text-muted-foreground transition-colors hover:text-foreground"
|
|
784
|
+
>Themes</a
|
|
785
|
+
>
|
|
786
|
+
</li>
|
|
787
|
+
<li>
|
|
788
|
+
<a
|
|
789
|
+
href="#get-started"
|
|
790
|
+
class="text-muted-foreground transition-colors hover:text-foreground"
|
|
791
|
+
>Documentation</a
|
|
792
|
+
>
|
|
793
|
+
</li>
|
|
794
|
+
</ul>
|
|
795
|
+
</div>
|
|
796
|
+
|
|
797
|
+
<div>
|
|
798
|
+
<h4 class="mb-4 font-semibold text-foreground">
|
|
799
|
+
Resources
|
|
800
|
+
</h4>
|
|
801
|
+
<ul class="space-y-2 text-sm">
|
|
802
|
+
<li>
|
|
803
|
+
<a
|
|
804
|
+
href="https://github.com/tufantunc/opentwig"
|
|
805
|
+
target="_blank"
|
|
806
|
+
rel="noopener noreferrer"
|
|
807
|
+
class="inline-flex items-center gap-1 text-muted-foreground transition-colors hover:text-foreground"
|
|
808
|
+
>
|
|
809
|
+
GitHub
|
|
810
|
+
<ExternalLink class="h-3 w-3" />
|
|
811
|
+
</a>
|
|
812
|
+
</li>
|
|
813
|
+
<li>
|
|
814
|
+
<a
|
|
815
|
+
href="https://www.npmjs.com/package/opentwig"
|
|
816
|
+
target="_blank"
|
|
817
|
+
rel="noopener noreferrer"
|
|
818
|
+
class="inline-flex items-center gap-1 text-muted-foreground transition-colors hover:text-foreground"
|
|
819
|
+
>
|
|
820
|
+
NPM Package
|
|
821
|
+
<ExternalLink class="h-3 w-3" />
|
|
822
|
+
</a>
|
|
823
|
+
</li>
|
|
824
|
+
<li>
|
|
825
|
+
<a
|
|
826
|
+
href="https://github.com/tufantunc/opentwig/issues"
|
|
827
|
+
target="_blank"
|
|
828
|
+
rel="noopener noreferrer"
|
|
829
|
+
class="inline-flex items-center gap-1 text-muted-foreground transition-colors hover:text-foreground"
|
|
830
|
+
>
|
|
831
|
+
Issues
|
|
832
|
+
<ExternalLink class="h-3 w-3" />
|
|
833
|
+
</a>
|
|
834
|
+
</li>
|
|
835
|
+
</ul>
|
|
836
|
+
</div>
|
|
837
|
+
|
|
838
|
+
<div>
|
|
839
|
+
<h4 class="mb-4 font-semibold text-foreground">
|
|
840
|
+
Legal
|
|
841
|
+
</h4>
|
|
842
|
+
<ul class="space-y-2 text-sm">
|
|
843
|
+
<li>
|
|
844
|
+
<a
|
|
845
|
+
href="https://github.com/tufantunc/opentwig/blob/main/LICENSE"
|
|
846
|
+
target="_blank"
|
|
847
|
+
rel="noopener noreferrer"
|
|
848
|
+
class="text-muted-foreground transition-colors hover:text-foreground"
|
|
849
|
+
>
|
|
850
|
+
MIT License
|
|
851
|
+
</a>
|
|
852
|
+
</li>
|
|
853
|
+
<li>
|
|
854
|
+
<span class="text-muted-foreground"
|
|
855
|
+
>© 2025 OpenTwig</span
|
|
856
|
+
>
|
|
857
|
+
</li>
|
|
858
|
+
</ul>
|
|
859
|
+
</div>
|
|
860
|
+
</div>
|
|
861
|
+
|
|
862
|
+
<Separator class="my-8" />
|
|
863
|
+
|
|
864
|
+
<div
|
|
865
|
+
class="flex flex-col items-center justify-between gap-4 sm:flex-row"
|
|
866
|
+
>
|
|
867
|
+
<p class="text-sm text-muted-foreground">
|
|
868
|
+
Made with love for open source community
|
|
869
|
+
</p>
|
|
870
|
+
<div class="flex items-center gap-4">
|
|
871
|
+
<a
|
|
872
|
+
href="https://github.com/tufantunc/opentwig"
|
|
873
|
+
target="_blank"
|
|
874
|
+
rel="noopener noreferrer"
|
|
875
|
+
class="text-muted-foreground transition-colors hover:text-foreground"
|
|
876
|
+
>
|
|
877
|
+
<Github class="h-5 w-5" />
|
|
878
|
+
</a>
|
|
879
|
+
<a
|
|
880
|
+
href="https://www.npmjs.com/package/opentwig"
|
|
881
|
+
target="_blank"
|
|
882
|
+
rel="noopener noreferrer"
|
|
883
|
+
class="text-muted-foreground transition-colors hover:text-foreground"
|
|
884
|
+
>
|
|
885
|
+
<Package class="h-5 w-5" />
|
|
886
|
+
</a>
|
|
887
|
+
</div>
|
|
888
|
+
</div>
|
|
889
|
+
</div>
|
|
890
|
+
</footer>
|
|
891
|
+
</div>
|
|
892
|
+
</TooltipProvider>
|