Skip to content

Commit 1b518b0

Browse files
committed
feat: better CLI
1 parent 3ceb99b commit 1b518b0

12 files changed

Lines changed: 561 additions & 17 deletions

File tree

apps/web/app/page.tsx

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Metadata } from "next";
22
import { AsciiPhoneShowcase } from "@/components/ascii-phone-showcase";
3-
import { AsciiClawsShowcase } from "@/components/claws-showcase";
3+
import { LandingCommandDemo } from "@/components/landing-command-demo";
4+
import { LobsterClawIcon } from "@/components/lobster-claw";
45
import { OpenClawPageShell } from "@/components/openclaw-page-shell";
56
import { TemplateCard } from "@/components/template-card";
67
import { CATEGORIES } from "@/lib/categories";
@@ -44,22 +45,20 @@ export default async function Page() {
4445

4546
return (
4647
<>
47-
<div className="overflow-x-clip min-h-screen relative mt-40 px-6 md:px-0">
48+
<div className="overflow-x-clip min-h-screen relative mt-20 px-6 md:px-0">
4849
<OpenClawPageShell contentClassName="w-full max-w-4xl space-y-10">
49-
<div className="flex items-stretch gap-10">
50-
<div className="2xl:block hidden aspect-square h-full w-full max-w-40 overflow-clip relative bg-primary/[0.03]">
51-
<AsciiClawsShowcase />
52-
</div>
53-
<div className="flex-1 flex flex-col gap-4">
54-
<h1 className="text-3xl sm:text-3xl md:text-4xl xl:text-5xl leading-[1.3] tracking-tight text-balance">
55-
Explore and sell vetted OpenClaw templates.
56-
</h1>
50+
<div className="flex-1 flex flex-col gap-4">
51+
<LobsterClawIcon className="size-13" />
52+
<h1 className="text-3xl sm:text-3xl md:text-4xl xl:text-5xl leading-[1.3] tracking-tight text-balance">
53+
Explore and sell vetted OpenClaw templates.
54+
</h1>
5755

58-
<p className="text-sm sm:text-base text-muted-foreground max-w-xl leading-relaxed">
59-
Discover trending Openclaw templates and deploy pre-configured,
60-
production-ready OpenClaw AI agents faster.
61-
</p>
62-
</div>
56+
<p className="text-sm sm:text-base text-muted-foreground max-w-xl leading-relaxed">
57+
Discover trending Openclaw templates and deploy pre-configured,
58+
production-ready OpenClaw AI agents faster.
59+
</p>
60+
61+
<LandingCommandDemo />
6362
</div>
6463

6564
<section className="space-y-12 pt-8 md:pt-12">
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { CopyButton } from "@/components/ui/copy-button";
2+
import { cn } from "@/lib/utils";
3+
4+
type CommandCopyRowProps = {
5+
label: string;
6+
command: string;
7+
className?: string;
8+
};
9+
10+
export function CommandCopyRow({
11+
label,
12+
command,
13+
className,
14+
}: CommandCopyRowProps) {
15+
return (
16+
<article className={cn("space-y-2 mt-4", className)}>
17+
<h2 className="font-pixel text-sm tracking-widest uppercase text-foreground/90">
18+
{label}
19+
</h2>
20+
<div className="flex min-w-0 items-center gap-2 rounded-xl border border-border bg-primary/10 p-2 sm:p-3">
21+
<code className="min-w-0 flex-1 overflow-x-auto whitespace-nowrap px-2 text-sm sm:text-base">
22+
$ {command}
23+
</code>
24+
<CopyButton value={command} ariaLabel={`Copy command for ${label}`} />
25+
</div>
26+
</article>
27+
);
28+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { CommandCopyRow } from "@/components/command-copy-row";
2+
3+
export function LandingCommandDemo() {
4+
return (
5+
<section
6+
className="w-full max-w-xl gap-6 flex items-center"
7+
aria-label="Quick template command demo"
8+
>
9+
<CommandCopyRow
10+
label="TRY IT NOW"
11+
command="npx claws-supply <template-slug>"
12+
/>
13+
<CommandCopyRow
14+
label="CREATE YOUR TEMPLATE"
15+
command="npx claws-supply build"
16+
/>
17+
</section>
18+
);
19+
}
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
import { useId } from "react";
2+
import { cn } from "@/lib/utils";
3+
4+
export function LobsterClawIcon({ className }: { className?: string }) {
5+
const uid = useId().replace(/:/g, "");
6+
const bodyGradientId = `${uid}-lobster-body-gradient`;
7+
const bodyHighlightId = `${uid}-lobster-body-highlight`;
8+
const bodyRimId = `${uid}-lobster-body-rim`;
9+
const leftClawGradientId = `${uid}-lobster-left-claw-gradient`;
10+
const rightClawGradientId = `${uid}-lobster-right-claw-gradient`;
11+
const clawHighlightId = `${uid}-lobster-claw-highlight`;
12+
const clawRimId = `${uid}-lobster-claw-rim`;
13+
const glowFilterId = `${uid}-lobster-glow-filter`;
14+
15+
return (
16+
<svg
17+
className={cn("shrink-0", className)}
18+
viewBox="0 0 120 120"
19+
fill="none"
20+
xmlns="http://www.w3.org/2000/svg"
21+
aria-hidden="true"
22+
focusable="false"
23+
>
24+
<g filter={`url(#${glowFilterId})`}>
25+
<path
26+
d="M60 10 C30 10 15 35 15 55 C15 75 30 95 45 100 L45 110 L55 110 L55 100 C55 100 60 102 65 100 L65 110 L75 110 L75 100 C90 95 105 75 105 55 C105 35 90 10 60 10Z"
27+
fill={`url(#${bodyGradientId})`}
28+
stroke={`url(#${bodyRimId})`}
29+
strokeWidth={1.4}
30+
/>
31+
<path
32+
d="M60 10 C30 10 15 35 15 55 C15 75 30 95 45 100 L45 110 L55 110 L55 100 C55 100 60 102 65 100 L65 110 L75 110 L75 100 C90 95 105 75 105 55 C105 35 90 10 60 10Z"
33+
fill={`url(#${bodyHighlightId})`}
34+
opacity={0.54}
35+
/>
36+
37+
<path
38+
d="M20 45 C5 40 0 50 5 60 C10 70 20 65 25 55 C28 48 25 45 20 45Z"
39+
fill={`url(#${leftClawGradientId})`}
40+
stroke={`url(#${clawRimId})`}
41+
strokeWidth={1}
42+
/>
43+
<path
44+
d="M100 45 C115 40 120 50 115 60 C110 70 100 65 95 55 C92 48 95 45 100 45Z"
45+
fill={`url(#${rightClawGradientId})`}
46+
stroke={`url(#${clawRimId})`}
47+
strokeWidth={1}
48+
/>
49+
<path
50+
d="M20 45 C5 40 0 50 5 60 C10 70 20 65 25 55 C28 48 25 45 20 45Z"
51+
fill={`url(#${clawHighlightId})`}
52+
opacity={0.4}
53+
/>
54+
<path
55+
d="M100 45 C115 40 120 50 115 60 C110 70 100 65 95 55 C92 48 95 45 100 45Z"
56+
fill={`url(#${clawHighlightId})`}
57+
opacity={0.3}
58+
/>
59+
</g>
60+
61+
<path
62+
d="M45 15 Q35 5 30 8"
63+
stroke="color-mix(in srgb, var(--cossistant-orange) 80%, white)"
64+
strokeWidth={2.2}
65+
strokeLinecap="round"
66+
/>
67+
<path
68+
d="M45 15 Q35 5 30 8"
69+
stroke="color-mix(in srgb, var(--cossistant-orange) 55%, black)"
70+
strokeWidth={1.1}
71+
strokeLinecap="round"
72+
opacity={0.7}
73+
/>
74+
<path
75+
d="M75 15 Q85 5 90 8"
76+
stroke="color-mix(in srgb, var(--cossistant-orange) 80%, white)"
77+
strokeWidth={2.2}
78+
strokeLinecap="round"
79+
/>
80+
<path
81+
d="M75 15 Q85 5 90 8"
82+
stroke="color-mix(in srgb, var(--cossistant-orange) 55%, black)"
83+
strokeWidth={1.1}
84+
strokeLinecap="round"
85+
opacity={0.7}
86+
/>
87+
88+
<circle
89+
cx="45"
90+
cy="35"
91+
r="6"
92+
fill="color-mix(in srgb, var(--cossistant-orange) 40%, black)"
93+
/>
94+
<circle
95+
cx="75"
96+
cy="35"
97+
r="6"
98+
fill="color-mix(in srgb, var(--cossistant-orange) 40%, black)"
99+
/>
100+
<circle
101+
cx="46"
102+
cy="34"
103+
r="1.8"
104+
fill="color-mix(in srgb, var(--cossistant-orange) 75%, white)"
105+
/>
106+
<circle
107+
cx="76"
108+
cy="34"
109+
r="1.8"
110+
fill="color-mix(in srgb, var(--cossistant-orange) 75%, white)"
111+
/>
112+
<circle
113+
cx="44"
114+
cy="36"
115+
r="0.8"
116+
fill="color-mix(in srgb, var(--cossistant-orange) 90%, white)"
117+
opacity={0.75}
118+
/>
119+
<circle
120+
cx="74"
121+
cy="36"
122+
r="0.8"
123+
fill="color-mix(in srgb, var(--cossistant-orange) 90%, white)"
124+
opacity={0.75}
125+
/>
126+
127+
<defs>
128+
<linearGradient
129+
id={bodyGradientId}
130+
x1="24"
131+
y1="14"
132+
x2="96"
133+
y2="108"
134+
gradientUnits="userSpaceOnUse"
135+
>
136+
<stop
137+
offset="0%"
138+
stopColor="color-mix(in srgb, var(--cossistant-orange) 78%, white)"
139+
/>
140+
<stop offset="42%" stopColor="var(--cossistant-orange)" />
141+
<stop
142+
offset="100%"
143+
stopColor="color-mix(in srgb, var(--cossistant-orange) 48%, black)"
144+
/>
145+
</linearGradient>
146+
147+
<linearGradient
148+
id={leftClawGradientId}
149+
x1="6"
150+
y1="43"
151+
x2="28"
152+
y2="66"
153+
gradientUnits="userSpaceOnUse"
154+
>
155+
<stop
156+
offset="0%"
157+
stopColor="color-mix(in srgb, var(--cossistant-orange) 74%, white)"
158+
/>
159+
<stop offset="58%" stopColor="var(--cossistant-orange)" />
160+
<stop
161+
offset="100%"
162+
stopColor="color-mix(in srgb, var(--cossistant-orange) 46%, black)"
163+
/>
164+
</linearGradient>
165+
166+
<linearGradient
167+
id={rightClawGradientId}
168+
x1="114"
169+
y1="43"
170+
x2="92"
171+
y2="66"
172+
gradientUnits="userSpaceOnUse"
173+
>
174+
<stop
175+
offset="0%"
176+
stopColor="color-mix(in srgb, var(--cossistant-orange) 68%, white)"
177+
/>
178+
<stop
179+
offset="56%"
180+
stopColor="color-mix(in srgb, var(--cossistant-orange) 95%, black)"
181+
/>
182+
<stop
183+
offset="100%"
184+
stopColor="color-mix(in srgb, var(--cossistant-orange) 44%, black)"
185+
/>
186+
</linearGradient>
187+
188+
<linearGradient
189+
id={bodyRimId}
190+
x1="18"
191+
y1="12"
192+
x2="102"
193+
y2="110"
194+
gradientUnits="userSpaceOnUse"
195+
>
196+
<stop
197+
offset="0%"
198+
stopColor="color-mix(in srgb, var(--cossistant-orange) 72%, white)"
199+
/>
200+
<stop
201+
offset="45%"
202+
stopColor="color-mix(in srgb, var(--cossistant-orange) 90%, black)"
203+
/>
204+
<stop
205+
offset="100%"
206+
stopColor="color-mix(in srgb, var(--cossistant-orange) 52%, black)"
207+
/>
208+
</linearGradient>
209+
210+
<linearGradient
211+
id={clawRimId}
212+
x1="2"
213+
y1="42"
214+
x2="118"
215+
y2="68"
216+
gradientUnits="userSpaceOnUse"
217+
>
218+
<stop
219+
offset="0%"
220+
stopColor="color-mix(in srgb, var(--cossistant-orange) 70%, white)"
221+
/>
222+
<stop
223+
offset="48%"
224+
stopColor="color-mix(in srgb, var(--cossistant-orange) 88%, black)"
225+
/>
226+
<stop
227+
offset="100%"
228+
stopColor="color-mix(in srgb, var(--cossistant-orange) 52%, black)"
229+
/>
230+
</linearGradient>
231+
232+
<radialGradient
233+
id={bodyHighlightId}
234+
cx="0"
235+
cy="0"
236+
r="1"
237+
gradientUnits="userSpaceOnUse"
238+
gradientTransform="translate(50 30) rotate(38) scale(44 31)"
239+
>
240+
<stop
241+
offset="0%"
242+
stopColor="color-mix(in srgb, var(--cossistant-orange) 88%, white)"
243+
/>
244+
<stop
245+
offset="100%"
246+
stopColor="color-mix(in srgb, var(--cossistant-orange) 88%, white)"
247+
stopOpacity={0}
248+
/>
249+
</radialGradient>
250+
251+
<radialGradient
252+
id={clawHighlightId}
253+
cx="0"
254+
cy="0"
255+
r="1"
256+
gradientUnits="userSpaceOnUse"
257+
gradientTransform="translate(60 48) rotate(0) scale(42 16)"
258+
>
259+
<stop
260+
offset="0%"
261+
stopColor="color-mix(in srgb, var(--cossistant-orange) 82%, white)"
262+
/>
263+
<stop
264+
offset="100%"
265+
stopColor="color-mix(in srgb, var(--cossistant-orange) 82%, white)"
266+
stopOpacity={0}
267+
/>
268+
</radialGradient>
269+
270+
<filter
271+
id={glowFilterId}
272+
x="-22%"
273+
y="-20%"
274+
width="144%"
275+
height="156%"
276+
colorInterpolationFilters="sRGB"
277+
>
278+
<feDropShadow
279+
dx="0"
280+
dy="0.7"
281+
stdDeviation="1.1"
282+
floodColor="color-mix(in srgb, var(--cossistant-orange) 62%, black)"
283+
floodOpacity="0.32"
284+
/>
285+
<feDropShadow
286+
dx="0"
287+
dy="0"
288+
stdDeviation="2.4"
289+
floodColor="color-mix(in srgb, var(--cossistant-orange) 70%, black)"
290+
floodOpacity="0.14"
291+
/>
292+
</filter>
293+
</defs>
294+
</svg>
295+
);
296+
}

0 commit comments

Comments
 (0)