13 "js": "application/javascript",
14 "json": "application/json",
15 "png": "image/png",
16 "jpg": "image/jpeg",
17 "jpeg": "image/jpeg",
18 "gif": "image/gif",
19 "svg": "image/svg+xml",
20 "woff": "font/woff",
21 "woff2": "font/woff2",
22 "ttf": "font/ttf",
23 "ico": "image/x-icon",
24 };
25 return types[ext] || "application/octet-stream";
3 <head>
4 <meta charset="UTF-8" />
5 <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 <title>Vite + React + TS</title>
2import deleteCreation from "./deleteCreation";
3import getCreation from "./getCreation";
4import getCreationImage from "./getCreationImage";
5import getCreations from "./getCreations";
6import updateTable from "./updateTable";
15 case "/get-creation":
16 return getCreation(req);
17 case "/get-creation-image":
18 return getCreationImage(req);
19 case "/get-creations":
20 return getCreations(req);
9 // - data (string)
10 // - type (string)
11 // - image (data url string)
12 // sanity checks:
13 // - title, not toooo long
14 // - data, hmm this needs to be long i guess.. maybe some crazy upper limit sanity check though
15 // - type, not too long
16 // - image, not toooo large a file size
17 let body;
18 try {
25 const data = body.data;
26 const type = body.type;
27 const image = body.image;
28
29 // Sanity checks
37 }
38
39 if (image && image.length > 20 * 1024 * 1024) {
40 return Response.json({ ok: false, error: "Thumbnail too large" });
41 }
57 );
58
59 // only creates blob if there is indeed an image and updates the image column to represent that
60 if (image) {
61 const imageName = "pondiverse_image" + id.lastInsertRowid;
62 const imageAddr = `${Deno.env.get("PONDIVERSE_STORE_BASE_PATH")}/get-creation-image?id=${id.lastInsertRowid}`;
63 await blob.set(imageName, image);
64 await sqlite.execute(
65 `UPDATE ${TABLE_NAME} SET image = "${imageAddr}" WHERE id = ${id.lastInsertRowid}`,
66 );
67 }
68
69 return Response.json({ ok: true, image: image });
70}
13 href="/public/favicon.svg"
14 sizes="any"
15 type="image/svg+xml"
16 >
17 <style>
99)
100
101interface ImageProps extends Omit<JSX.ImgHTMLAttributes<HTMLImageElement>, 'width' | 'height'> {
102 src: string
103 w?: number | string
107
108
109const Image: FunctionalComponent<ImageProps> = (props) => {
110 const { src, w, h, fit, children, style, className, ...rest } = props
111 const altText = children?.toString() || ''
236<VStack gap="32" alignX="center" alignY="center" p="16" h="screen">
237 <HStack gap="16" alignX="start" alignY="center" bg="light-blue">
238 <Image src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Stripe_Logo%2C_revised_2016.svg/1024px-Stripe_Logo%2C_revised_2016.svg.png" w="100">
239 Stripe logo
240 </Image>
241 </HStack>
242
6 <title>React Hono Val Town Starter</title>
7 <link rel="stylesheet" href="/public/style.css">
8 <link rel="icon" href="/public/favicon.svg" sizes="any" type="image/svg+xml">
9 </head>
10 <body>
9import { useUsageStats } from "../hooks/useUsageStats.ts";
10import { Messages } from "./Messages.tsx";
11import { InputBox, ImageDropContainer } from "./InputBox.tsx";
12import { PreviewFrame } from "./PreviewFrame.tsx";
13import { BranchSelect } from "./BranchSelect.tsx";
65 refetch: () => void;
66}) {
67 const [images, setImages] = useState<(string|null)[]>([]);
68 const [selectedFiles, setSelectedFiles] = useState<string[]>([]);
69 const { audio, user } = useContext(AppContext);
83 branchId,
84 selectedFiles,
85 images,
86 soundEnabled: audio,
87 });
107
108 return (
109 <ImageDropContainer
110 running={running}
111 images={images}
112 setImages={setImages}>
113 <div className="single-column-container">
114 <div className="single-sticky-header">
118 rel="norefferer"
119 className="block-link text-link lockup">
120 {project.imageUrl ? (
121 <img src={project.imageUrl} className="image-thumbnail" />
122 ) : user?.profileImageUrl ? (
123 <img
124 src={user.profileImageUrl}
125 className="avatar"
126 alt={user.username}
129 />
130 ) : (
131 <div className="image-placeholder" />
132 )}
133 <div>{project.name}</div>
152 onSubmit={e => {
153 handleSubmit(e);
154 setImages([]);
155 }}
156 onCancel={handleStop}
157 running={running}
158 error={error}
159 images={images}
160 setImages={setImages}
161 />
162 </div>
163 </div>
164 </ImageDropContainer>
165 );
166}
172
173- **Redirects:** Use `return new Response(null, { status: 302, headers: { Location: "/place/to/redirect" }})` instead of `Response.redirect` which is broken
174- **Images:** Avoid external images or base64 images. Use emojis, unicode symbols, or icon fonts/libraries instead
175- **AI Image:** To inline generate an AI image use: `<img src="https://maxm-imggenurl.web.val.run/the-description-of-your-image" />`
176- **Storage:** DO NOT use the Deno KV module for storage
177- **Browser APIs:** DO NOT use the `alert()`, `prompt()`, or `confirm()` methods
32 <button className="h6">Log out</button>
33 </form>
34 {user?.profileImageUrl && (
35 <img
36 src={user.profileImageUrl}
37 alt={user.username}
38 width="32"