Skip to content

Commit 2d9ee4d

Browse files
committed
Homepage halo image
1 parent 972a313 commit 2d9ee4d

1 file changed

Lines changed: 125 additions & 121 deletions

File tree

app/(main)/page.tsx

Lines changed: 125 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use client";
22

3+
import bgImg from "@/public/halo.png";
34
import Fieldset from "@/components/fieldset";
45
import ArrowRightIcon from "@/components/icons/arrow-right";
56
import GithubIcon from "@/components/icons/github-icon";
@@ -46,133 +47,136 @@ export default function Home() {
4647

4748
return (
4849
<>
49-
<header className="py-5">
50-
<Image src={logo} alt="" className="mx-auto h-6 w-auto" priority />
51-
</header>
52-
53-
<div className="mt-16 flex grow flex-col items-center px-4">
54-
<p className="w-auto rounded-full border border-gray-300 px-2 py-1.5 text-xs italic">
55-
Used by <strong>600k+</strong> happy users
56-
</p>
57-
58-
<h1 className="mt-4 text-balance text-center text-4xl leading-none text-gray-700 md:text-[64px]">
59-
Turn your <span className="text-blue-500">idea</span>
60-
<br className="hidden md:block" /> into an{" "}
61-
<span className="text-blue-500">app</span>
62-
</h1>
63-
64-
<form
65-
className="mt-6"
66-
action={async (formData) => {
67-
const { prompt, model, shadcn } = Object.fromEntries(formData);
68-
assert.ok(typeof prompt === "string");
69-
assert.ok(typeof model === "string");
70-
71-
const { chatId, lastMessageId } = await createChat(
72-
prompt,
73-
model,
74-
!!shadcn,
75-
);
76-
const { streamPromise } = await getNextCompletionStreamPromise(
77-
lastMessageId,
78-
model,
79-
);
80-
81-
startTransition(() => {
82-
setStreamPromise(streamPromise);
83-
router.push(`/chats/${chatId}`);
84-
});
85-
}}
86-
>
87-
<Fieldset>
88-
<div className="relative flex rounded-lg border-4 border-gray-300 bg-white pb-10">
89-
<TextareaAutosize
90-
placeholder="Build me a budgeting app..."
91-
required
92-
name="prompt"
93-
rows={1}
94-
className="peer relative w-full resize-none bg-transparent p-2 placeholder-gray-500 focus:outline-none disabled:opacity-50"
95-
value={prompt}
96-
onChange={(e) => setPrompt(e.target.value)}
97-
onKeyDown={(event) => {
98-
if (event.key === "Enter" && !event.shiftKey) {
99-
event.preventDefault();
100-
const target = event.target;
101-
if (!(target instanceof HTMLTextAreaElement)) return;
102-
103-
target.closest("form")?.requestSubmit();
104-
}
105-
}}
106-
/>
107-
<div className="pointer-events-none absolute inset-0 rounded peer-focus:outline peer-focus:outline-offset-0 peer-focus:outline-blue-500" />
50+
<div className="absolute inset-x-0 flex justify-center">
51+
<Image
52+
src={bgImg}
53+
alt=""
54+
className="w-full max-w-[1200px] mix-blend-screen"
55+
priority
56+
/>
57+
</div>
10858

109-
<div className="absolute inset-x-1.5 bottom-1.5 flex items-center justify-between">
110-
<div className="flex items-center gap-2">
111-
<Select
112-
name="model"
113-
className="rounded text-sm italic text-gray-400 focus:outline focus:outline-2 focus:outline-blue-300"
114-
>
115-
{MODELS.map((model) => (
116-
<option key={model.value} value={model.value}>
117-
{model.label}
118-
</option>
119-
))}
120-
</Select>
59+
<div className="isolate flex h-full flex-col">
60+
<header className="shrink-0 py-5">
61+
<Image src={logo} alt="" className="mx-auto h-6 w-auto" priority />
62+
</header>
12163

122-
<label className="inline-flex items-center gap-1.5 text-sm italic text-gray-400">
123-
shadcn/ui
124-
<input
125-
type="checkbox"
126-
name="shadcn"
127-
className="size-4 accent-blue-500 focus:outline focus:outline-2 focus:outline-blue-300"
128-
/>
129-
</label>
64+
<div className="mt-16 flex grow flex-col items-center px-4 lg:mt-24">
65+
<p className="w-auto rounded-full border border-gray-300 px-2 py-1.5 text-xs italic">
66+
Used by <strong>600k+</strong> happy users
67+
</p>
68+
<h1 className="mt-4 text-balance text-center text-4xl leading-none text-gray-700 md:text-[64px]">
69+
Turn your <span className="text-blue-500">idea</span>
70+
<br className="hidden md:block" /> into an{" "}
71+
<span className="text-blue-500">app</span>
72+
</h1>
73+
<form
74+
className="mt-6"
75+
action={async (formData) => {
76+
const { prompt, model, shadcn } = Object.fromEntries(formData);
77+
assert.ok(typeof prompt === "string");
78+
assert.ok(typeof model === "string");
79+
const { chatId, lastMessageId } = await createChat(
80+
prompt,
81+
model,
82+
!!shadcn,
83+
);
84+
const { streamPromise } = await getNextCompletionStreamPromise(
85+
lastMessageId,
86+
model,
87+
);
88+
startTransition(() => {
89+
setStreamPromise(streamPromise);
90+
router.push(`/chats/${chatId}`);
91+
});
92+
}}
93+
>
94+
<Fieldset>
95+
<div className="relative flex rounded-lg border-4 border-gray-300 bg-white pb-10">
96+
<TextareaAutosize
97+
placeholder="Build me a budgeting app..."
98+
required
99+
name="prompt"
100+
rows={1}
101+
className="peer relative w-full resize-none bg-transparent p-2 placeholder-gray-500 focus:outline-none disabled:opacity-50"
102+
value={prompt}
103+
onChange={(e) => setPrompt(e.target.value)}
104+
onKeyDown={(event) => {
105+
if (event.key === "Enter" && !event.shiftKey) {
106+
event.preventDefault();
107+
const target = event.target;
108+
if (!(target instanceof HTMLTextAreaElement)) return;
109+
target.closest("form")?.requestSubmit();
110+
}
111+
}}
112+
/>
113+
<div className="pointer-events-none absolute inset-0 rounded peer-focus:outline peer-focus:outline-offset-0 peer-focus:outline-blue-500" />
114+
<div className="absolute inset-x-1.5 bottom-1.5 flex items-center justify-between">
115+
<div className="flex items-center gap-2">
116+
<Select
117+
name="model"
118+
className="rounded text-sm italic text-gray-400 focus:outline focus:outline-2 focus:outline-blue-300"
119+
>
120+
{MODELS.map((model) => (
121+
<option key={model.value} value={model.value}>
122+
{model.label}
123+
</option>
124+
))}
125+
</Select>
126+
<label className="inline-flex items-center gap-1.5 text-sm italic text-gray-400">
127+
shadcn/ui
128+
<input
129+
type="checkbox"
130+
name="shadcn"
131+
className="size-4 accent-blue-500 focus:outline focus:outline-2 focus:outline-blue-300"
132+
/>
133+
</label>
134+
</div>
135+
<div className="relative flex has-[:disabled]:opacity-50">
136+
<div className="pointer-events-none absolute inset-0 -bottom-[1px] rounded bg-blue-700" />
137+
<LoadingButton
138+
className="relative inline-flex size-6 items-center justify-center rounded bg-blue-500 font-medium text-white shadow-lg outline-blue-300 hover:bg-blue-500/75 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
139+
type="submit"
140+
>
141+
<ArrowRightIcon />
142+
</LoadingButton>
143+
</div>
130144
</div>
131-
132-
<div className="relative flex has-[:disabled]:opacity-50">
133-
<div className="pointer-events-none absolute inset-0 -bottom-[1px] rounded bg-blue-700" />
134-
<LoadingButton
135-
className="relative inline-flex size-6 items-center justify-center rounded bg-blue-500 font-medium text-white shadow-lg outline-blue-300 hover:bg-blue-500/75 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
136-
type="submit"
145+
</div>
146+
<div className="mt-4 flex w-full flex-wrap justify-center gap-3">
147+
{SUGGESTED_PROMPTS.map((v) => (
148+
<button
149+
key={v}
150+
type="button"
151+
onClick={() => setPrompt(v)}
152+
className="rounded bg-gray-200 px-2.5 py-1.5 text-xs hover:bg-gray-300 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-300"
137153
>
138-
<ArrowRightIcon />
139-
</LoadingButton>
140-
</div>
154+
{v}
155+
</button>
156+
))}
141157
</div>
142-
</div>
143-
<div className="mt-4 flex w-full flex-wrap justify-center gap-3">
144-
{SUGGESTED_PROMPTS.map((v) => (
145-
<button
146-
key={v}
147-
type="button"
148-
onClick={() => setPrompt(v)}
149-
className="rounded bg-gray-200 px-2.5 py-1.5 text-xs hover:bg-gray-300 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-300"
150-
>
151-
{v}
152-
</button>
153-
))}
154-
</div>
155-
</Fieldset>
156-
</form>
157-
</div>
158-
159-
<footer className="flex flex-col gap-2 py-4 text-center text-xs text-gray-500">
160-
<div className="flex justify-center gap-2">
161-
<Link
162-
href="#"
163-
className="flex items-center gap-1 rounded border border-gray-300 p-1"
164-
>
165-
<XIcon className="size-2.5" /> Twitter
166-
</Link>
167-
<Link
168-
href="#"
169-
className="flex items-center gap-1 rounded border border-gray-300 p-1"
170-
>
171-
<GithubIcon className="size-2.5" /> GitHub
172-
</Link>
158+
</Fieldset>
159+
</form>
173160
</div>
174-
<p>Powered by Llama 3.1 & Together.ai</p>
175-
</footer>
161+
162+
<footer className="flex shrink-0 flex-col gap-2 py-4 text-center text-xs text-gray-500">
163+
<div className="flex justify-center gap-2">
164+
<Link
165+
href="#"
166+
className="flex items-center gap-1 rounded border border-gray-300 p-1"
167+
>
168+
<XIcon className="size-2.5" /> Twitter
169+
</Link>
170+
<Link
171+
href="#"
172+
className="flex items-center gap-1 rounded border border-gray-300 p-1"
173+
>
174+
<GithubIcon className="size-2.5" /> GitHub
175+
</Link>
176+
</div>
177+
<p>Powered by Llama 3.1 & Together.ai</p>
178+
</footer>
179+
</div>
176180
</>
177181
);
178182
}

0 commit comments

Comments
 (0)