Skip to content

Commit 10ae304

Browse files
committedJan 24, 2025·
wip
1 parent 0047a9c commit 10ae304

File tree

3 files changed

+69
-31
lines changed

3 files changed

+69
-31
lines changed
 

‎app/page.tsx

+26-29
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ import logo from "@/public/logo.png";
1111
import { ArrowUpRightIcon } from "@heroicons/react/24/solid";
1212
import * as RadioGroup from "@radix-ui/react-radio-group";
1313
import { useQuery } from "@tanstack/react-query";
14-
import { ExternalLink } from "lucide-react";
1514
import { AnimatePresence, motion } from "motion/react";
1615
import Image from "next/image";
1716
import { useEffect, useState } from "react";
1817
import { z } from "zod";
1918

2019
export default function Home() {
2120
const [prompt, setPrompt] = useState("");
21+
const [submittedPrompt, setSubmittedPrompt] = useState("");
2222
const [userAPIKey, setUserAPIKey] = useState("");
2323
const [selectedLoraModel, setSelectedLoraModel] = useState<Lora["model"]>();
2424

@@ -38,15 +38,15 @@ export default function Home() {
3838

3939
const { data, isFetching } = useQuery({
4040
placeholderData: (previousData) => previousData,
41-
queryKey: [prompt, selectedLoraModel, userAPIKey],
41+
queryKey: [submittedPrompt, selectedLoraModel, userAPIKey],
4242
queryFn: async () => {
4343
let res = await fetch("/api/generateImages", {
4444
method: "POST",
4545
headers: {
4646
"Content-Type": "application/json",
4747
},
4848
body: JSON.stringify({
49-
prompt,
49+
prompt: submittedPrompt,
5050
lora: selectedLoraModel,
5151
userAPIKey,
5252
}),
@@ -61,16 +61,11 @@ export default function Home() {
6161

6262
return imageResponseSchema.parse(data);
6363
},
64-
enabled: !!(prompt.trim() && selectedLoraModel),
64+
enabled: !!(submittedPrompt.trim() && selectedLoraModel),
6565
staleTime: Infinity,
6666
retry: false,
6767
});
6868

69-
async function action(formData: FormData) {
70-
let { prompt } = Object.fromEntries(formData.entries());
71-
setPrompt(typeof prompt === "string" ? prompt : "");
72-
}
73-
7469
const selectedLora = LORAS.find((l) => l.model === selectedLoraModel);
7570

7671
return (
@@ -105,7 +100,7 @@ export default function Home() {
105100
</header>
106101

107102
<main className="mx-auto mt-10 w-full max-w-5xl grow">
108-
<form className="w-full" action={action}>
103+
<form className="w-full" action={() => setSubmittedPrompt(prompt)}>
109104
<fieldset className="flex w-full flex-col gap-8 md:flex-row">
110105
<div className="max-w-sm rounded-lg bg-gray-100 p-5">
111106
<p className="font-mono font-medium">Choose your LoRA</p>
@@ -163,28 +158,30 @@ export default function Home() {
163158
spellCheck={false}
164159
placeholder="Describe your image..."
165160
required
166-
defaultValue={prompt}
161+
value={prompt}
162+
onChange={(e) => setPrompt(e.target.value)}
167163
className="block w-full resize-none rounded-lg border border-gray-300 bg-white px-4 py-3 text-base text-gray-600 placeholder-gray-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-300"
168164
/>
169165

170-
<div className="mt-4">
171-
<p className="text-xs font-bold text-gray-400">Suggestions</p>
172-
<div className="mt-2 flex flex-wrap gap-2">
173-
{[
174-
"New York City",
175-
"Elon Musk",
176-
"Morocco",
177-
"Italian cuisine",
178-
].map((suggestion) => (
179-
<button
180-
key={suggestion}
181-
className="shrink-0 rounded-full bg-gray-100 px-2.5 py-1.5 text-sm text-gray-600 hover:bg-gray-200"
182-
>
183-
{suggestion}
184-
</button>
185-
))}
166+
{selectedLora && (
167+
<div className="mt-4">
168+
<p className="text-xs font-bold text-gray-400">
169+
Suggestions
170+
</p>
171+
<div className="mt-2 flex flex-wrap gap-2">
172+
{selectedLora.suggestions.map((suggestion, i) => (
173+
<button
174+
type="button"
175+
key={i}
176+
onClick={() => setPrompt(suggestion.prompt)}
177+
className="shrink-0 rounded-full bg-gray-100 px-2.5 py-1.5 text-sm text-gray-600 hover:bg-gray-200"
178+
>
179+
{suggestion.label}
180+
</button>
181+
))}
182+
</div>
186183
</div>
187-
</div>
184+
)}
188185

189186
<div className="mt-10">
190187
<button
@@ -198,7 +195,7 @@ export default function Home() {
198195
</div>
199196

200197
<div className="mt-20">
201-
{prompt && selectedLora ? (
198+
{submittedPrompt && selectedLora ? (
202199
<AnimatePresence mode="wait">
203200
{isFetching ? (
204201
<motion.div

‎data/loras.ts

+42
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export type Lora = {
2424
refinement: string | boolean;
2525
height?: number;
2626
width?: number;
27+
suggestions: { prompt: string; label: string }[];
2728
};
2829

2930
export const LORAS: Lora[] = [
@@ -42,6 +43,11 @@ export const LORAS: Lora[] = [
4243
steps: 33,
4344
height: 832,
4445
width: 1280,
46+
suggestions: [
47+
{ label: "Flaming red torch", prompt: "A flaming red torch" },
48+
{ label: "Brown briefcase", prompt: "A brown briefcase" },
49+
{ label: "Snow globe", prompt: "A snow globe" },
50+
],
4551
},
4652
{
4753
id: 6,
@@ -56,6 +62,7 @@ export const LORAS: Lora[] = [
5662
"Refine the prompt so that it describes a professional and minimalist logo. If the prompt describes two items, then just return those two items.",
5763
scale: 0.8,
5864
steps: 28,
65+
suggestions: [{ label: "Cat and flame", prompt: "cat and flame" }],
5966
},
6067
{
6168
id: 1,
@@ -72,6 +79,10 @@ export const LORAS: Lora[] = [
7279
steps: 33,
7380
height: 832,
7481
width: 1280,
82+
suggestions: [
83+
{ label: "Albert Einstein", prompt: "Albert Einstein" },
84+
{ label: "New York City", prompt: "New York City" },
85+
],
7586
},
7687
{
7788
id: 7,
@@ -87,6 +98,7 @@ export const LORAS: Lora[] = [
8798
"Refine that prompt so it mimics MidJourney's style, blending intricate and artistic designs. Edit for photorealism and close-up shots.",
8899
scale: 1,
89100
steps: 28,
101+
suggestions: [{ label: "A flaming red torch", prompt: "" }],
90102
},
91103

92104
{
@@ -103,6 +115,11 @@ export const LORAS: Lora[] = [
103115
"Change the prompt does that it describes a piece of clothing. You need to include each of the following details: color, pattern, fit, style, material, and type.",
104116
scale: 1,
105117
steps: 28,
118+
suggestions: [
119+
{ label: "A flaming red torch", prompt: "" },
120+
{ label: "A brown briefcase", prompt: "" },
121+
{ label: "A snow globe", prompt: "" },
122+
],
106123
},
107124
{
108125
id: 2,
@@ -117,6 +134,11 @@ export const LORAS: Lora[] = [
117134
refinement: false,
118135
scale: 1,
119136
steps: 28,
137+
suggestions: [
138+
{ label: "A flaming red torch", prompt: "" },
139+
{ label: "A brown briefcase", prompt: "" },
140+
{ label: "A snow globe", prompt: "" },
141+
],
120142
},
121143
{
122144
id: 3,
@@ -133,6 +155,11 @@ export const LORAS: Lora[] = [
133155
"Refine the prompt so that it describes a smooth, scalable vector-style sketch that is ideal for digital designs.",
134156
scale: 1,
135157
steps: 28,
158+
suggestions: [
159+
{ label: "A flaming red torch", prompt: "" },
160+
{ label: "A brown briefcase", prompt: "" },
161+
{ label: "A snow globe", prompt: "" },
162+
],
136163
},
137164
{
138165
id: 4,
@@ -146,6 +173,11 @@ export const LORAS: Lora[] = [
146173
refinement: false,
147174
scale: 1,
148175
steps: 28,
176+
suggestions: [
177+
{ label: "A flaming red torch", prompt: "" },
178+
{ label: "A brown briefcase", prompt: "" },
179+
{ label: "A snow globe", prompt: "" },
180+
],
149181
},
150182
{
151183
id: 5,
@@ -161,6 +193,11 @@ export const LORAS: Lora[] = [
161193
"Refine the prompt so that it combines anime inspired designs with textured block print aesthetics. The refinement should only include a description that would exist in both anime and block print.",
162194
scale: 1,
163195
steps: 28,
196+
suggestions: [
197+
{ label: "A flaming red torch", prompt: "" },
198+
{ label: "A brown briefcase", prompt: "" },
199+
{ label: "A snow globe", prompt: "" },
200+
],
164201
},
165202
{
166203
id: 10,
@@ -175,5 +212,10 @@ export const LORAS: Lora[] = [
175212
refinement: false,
176213
scale: 1,
177214
steps: 28,
215+
suggestions: [
216+
{ label: "A flaming red torch", prompt: "" },
217+
{ label: "A brown briefcase", prompt: "" },
218+
{ label: "A snow globe", prompt: "" },
219+
],
178220
},
179221
];

‎middleware.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
/* eslint-disable @typescript-eslint/no-unused-vars */
21
import { NextRequest, NextResponse } from "next/server";
32

43
export async function middleware(req: NextRequest) {
5-
let country = req.geo?.country;
4+
const country = req.headers.get("X-Vercel-IP-Country");
65
// Temporarily blocking traffic from Russia since I have too many requests from there.
76
if (country === "RU") {
87
return new NextResponse("Access Denied", { status: 403 });

0 commit comments

Comments
 (0)
Please sign in to comment.