Val Town Code SearchReturn to Val Town

API Access

You can access search results via JSON API by adding format=json to your query:

https://codesearch.val.run/?q=image&page=32&format=json

For typeahead suggestions, use the /typeahead endpoint:

https://codesearch.val.run/typeahead?q=image

Returns an array of strings in format "username" or "username/projectName"

Found 2776 results for "image"(436ms)

OpenTownieuseChatLogic.ts4 matches

@jxnblkUpdated 1 week ago
9 bearerToken: string;
10 selectedFiles: string[];
11 images: (string | null)[];
12 soundEnabled: boolean;
13}
19 bearerToken,
20 selectedFiles,
21 images,
22 soundEnabled,
23}: UseChatLogicProps) {
41 anthropicApiKey,
42 selectedFiles,
43 images: images
44 .filter((img): img is string => {
45 const isValid = typeof img === "string" && img.startsWith("data:");
46 if (!isValid && img !== null) {
47 console.warn("Invalid image format:", img?.substring(0, 50) + "...");
48 }
49 return isValid;

OpenTownieTODOs.md1 match

@jxnblkUpdated 1 week ago
29 - [x] File write as a code embed
30 - [x] str_replace as a diff view
31- [x] make image drop area invisible and bigger
32- [x] Give it all the code (except maybe .txt files) as initial context (like cursor sonnet max)
33- [x] I seem to have lost the delete file tool and instructions, try to find them back in history or re-create?

OpenTowniesystem_prompt.txt2 matches

@jxnblkUpdated 1 week ago
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

OpenTowniesend-message.ts11 matches

@jxnblkUpdated 1 week ago
19 }
20
21 const { messages, project, branchId, anthropicApiKey, selectedFiles, images } = await c.req.json();
22 console.log("Original messages:", JSON.stringify(messages, null, 2));
23 console.log("Images received:", JSON.stringify(images, null, 2));
24
25 // Check if API key is available
47 let coreMessages = convertToCoreMessages(messages);
48
49 // If there are images, we need to add them to the last user message
50 if (images && Array.isArray(images) && images.length > 0) {
51 // Find the last user message
52 const lastUserMessageIndex = coreMessages.findIndex(
70 };
71
72 // Add each image to the content array using the correct ImagePart format
73 for (const image of images) {
74 if (image && image.url) {
75 // Extract mime type from data URL if available
76 let mimeType = undefined;
77 if (image.url.startsWith("data:")) {
78 const matches = image.url.match(/^data:([^;]+);/);
79 if (matches && matches.length > 1) {
80 mimeType = matches[1];
83
84 newUserMessage.content.push({
85 type: "image",
86 image: image.url,
87 mimeType,
88 });

OpenTownieMessagePart.tsx11 matches

@jxnblkUpdated 1 week ago
2import { type Message } from "https://esm.sh/@ai-sdk/react?dev&deps=react@18.2.0&react-dom@18.2.0";
3import ReactMarkdown from "https://esm.sh/react-markdown?dev&deps=react@18.2.0&react-dom@18.2.0";
4import { ImagePreview } from "./ImageUpload.tsx";
5
6// Helper function to detect language from file path
322 );
323 }
324 if (part.type === "image") {
325 // Handle both formats: {image: {url: string}} and {image: string}
326 const imageUrl = typeof part.image === "string"
327 ? part.image
328 : part.image.url || (part.image as any).source?.url;
329
330 return (
331 <div className="mt-2">
332 <img
333 src={imageUrl}
334 alt="Uploaded image"
335 className="max-h-64 max-w-full object-contain rounded"
336 />
338 );
339 }
340 // Handle multiple images in a single part
341 if (part.type === "images") {
342 return <ImagePreview images={part.images.map(img => img.url)} />;
343 }
344}

OpenTownieImageUpload.tsx47 matches

@jxnblkUpdated 1 week ago
2import React, { useRef, useState } from "https://esm.sh/react@18.2.0?dev";
3
4// Maximum number of images that can be uploaded
5export const PROMPT_IMAGE_LIMIT = 5;
6
7interface ImageUploadProps {
8 images: (string | null)[];
9 setImages: (images: (string | null)[]) => void;
10 processFiles: (files: File[]) => void;
11}
12
13export function ImageUpload({ images, setImages, processFiles }: ImageUploadProps) {
14 const fileInputRef = useRef<HTMLInputElement>(null);
15
21 };
22
23 // Handle removing an image
24 const removeImage = (index: number) => {
25 const newImages = [...images];
26 newImages.splice(index, 1);
27 setImages(newImages);
28 };
29
30 // Check if we've reached the image limit
31 const isAtLimit = images.filter(Boolean).length >= PROMPT_IMAGE_LIMIT;
32
33 return (
34 <div className="w-full">
35 {/* Image previews */}
36 {images.length > 0 && (
37 <div className="flex flex-wrap gap-2 mb-2">
38 {images.map((image, index) => (
39 <div key={index} className="relative">
40 {image ? (
41 <div className="relative group">
42 <img
43 src={image}
44 alt={`Uploaded ${index + 1}`}
45 className="h-16 w-16 object-cover rounded border border-gray-300"
47 <button
48 className="absolute top-0 right-0 bg-red-500 text-white rounded-full w-5 h-5 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
49 onClick={() => removeImage(index)}
50 title="Remove image"
51 >
52 ×
68 ref={fileInputRef}
69 onChange={handleFileChange}
70 accept="image/*"
71 multiple
72 className="hidden"
80
81// Process files utility function - moved from the component to be reusable
82export const processFiles = async (files: File[], images: (string | null)[], setImages: (images: (string | null)[]) => void) => {
83 // Filter for image files only
84 const imageFiles = files.filter(file => file.type.startsWith('image/'));
85
86 // Limit the number of images
87 const filesToProcess = imageFiles.slice(0, PROMPT_IMAGE_LIMIT - images.filter(Boolean).length);
88
89 if (filesToProcess.length === 0) return;
90
91 // Add null placeholders for loading state
92 const newImages = [...images, ...Array(filesToProcess.length).fill(null)];
93 setImages(newImages);
94
95 // Process each file
96 const processedImages = await Promise.all(
97 filesToProcess.map(async (file) => {
98 return await readFileAsDataURL(file);
100 );
101
102 // Replace null placeholders with actual images
103 const updatedImages = [...images];
104 processedImages.forEach((dataUrl, index) => {
105 updatedImages[images.length + index] = dataUrl;
106 });
107
108 setImages(updatedImages.slice(0, PROMPT_IMAGE_LIMIT));
109};
110
115 reader.onload = () => {
116 const result = reader.result as string;
117 console.log("Image loaded, size:", result.length, "bytes");
118 resolve(result);
119 };
123};
124
125// Component to display images in messages
126export function ImagePreview({ images }: { images: string[] }) {
127 const [expandedImage, setExpandedImage] = useState<string | null>(null);
128
129 if (!images || images.length === 0) return null;
130
131 return (
132 <div className="mt-2">
133 <div className="flex flex-wrap gap-2">
134 {images.map((image, index) => (
135 <div key={index} className="relative">
136 <img
137 src={image}
138 alt={`Image ${index + 1}`}
139 className="max-h-32 max-w-32 object-contain rounded cursor-pointer"
140 onClick={() => setExpandedImage(image)}
141 />
142 </div>
144 </div>
145
146 {/* Modal for expanded image */}
147 {expandedImage && (
148 <div
149 className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50"
150 onClick={() => setExpandedImage(null)}
151 >
152 <div className="max-w-[90%] max-h-[90%]">
153 <img
154 src={expandedImage}
155 alt="Expanded view"
156 className="max-w-full max-h-full object-contain"

OpenTownieChat.tsx8 matches

@jxnblkUpdated 1 week ago
9import { ChatInput } from "./ChatInput.tsx";
10import { ApiKeyWarning } from "./ApiKeyWarning.tsx";
11import { processFiles } from "./ImageUpload.tsx";
12import { Preview } from "./Preview.tsx";
13
26 const [soundEnabled, setSoundEnabled] = useLocalStorage<boolean>("soundEnabled", true);
27 const [selectedFiles, setSelectedFiles] = useState<string[]>([]);
28 const [images, setImages] = useState<(string | null)[]>([]);
29 const [isDragging, setIsDragging] = useState(false);
30
60 bearerToken,
61 selectedFiles,
62 images,
63 soundEnabled,
64 });
95
96 if (e.dataTransfer.files && !running) {
97 processFiles(Array.from(e.dataTransfer.files), images, setImages);
98 }
99 };
125
126 if (e.dataTransfer?.files && !running) {
127 processFiles(Array.from(e.dataTransfer.files), images, setImages);
128 }
129 };
142 document.removeEventListener('drop', handleDocumentDrop);
143 };
144 }, [images, running, setImages]);
145
146 return (
197 handleSubmit={handleSubmit}
198 running={running}
199 images={images}
200 setImages={setImages}
201 isDragging={isDragging}
202 />

OpenTownieChatInput.tsx20 matches

@jxnblkUpdated 1 week ago
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import React, { useEffect, useRef, useState } from "https://esm.sh/react@18.2.0?dev";
3import { ImageUpload, processFiles } from "./ImageUpload.tsx";
4
5interface ChatInputProps {
8 handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
9 running: boolean;
10 images: (string | null)[];
11 setImages: React.Dispatch<React.SetStateAction<(string | null)[]>>;
12 isDragging: boolean;
13}
18 handleSubmit,
19 running,
20 images,
21 setImages,
22 isDragging,
23}: ChatInputProps) {
43 const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
44 e.preventDefault();
45 const validImages = images.filter((img): img is string => typeof img === "string");
46 console.log("Submitting with images:", validImages);
47 if (input.trim() || validImages.length > 0) {
48 handleSubmit(e);
49 setImages([]);
50 }
51 };
52
53 const handleProcessFiles = (files: File[]) => {
54 processFiles(files, images, setImages);
55 };
56
61 disabled={running}
62 >
63 {images.length > 0 && (
64 <ImageUpload
65 images={images}
66 setImages={setImages}
67 processFiles={handleProcessFiles}
68 />
82 if (e.key === "Enter" && !e.shiftKey && !isMobile) {
83 e.preventDefault();
84 if (input.trim() || images.filter(Boolean).length > 0) {
85 handleFormSubmit(e as any);
86 }
103 }
104 }}
105 accept="image/*"
106 multiple
107 className="hidden"
139 </div>
140
141 {/* Attach images button below textarea */}
142 {!running && (
143 <div className="flex justify-start mt-1 mb-2">
150 }
151 }}
152 title="Attach images"
153 >
154 <span>📎</span> Attach images
155 </button>
156 </div>
162 <div className="bg-white p-6 rounded-lg shadow-lg text-center">
163 <div className="text-2xl mb-2">📁</div>
164 <div className="text-xl font-semibold">Drop images here</div>
165 </div>
166 </div>
jeeves

jeevesREADME.md1 match

@brontojorisUpdated 1 week ago
3It's common to have code and types that are needed on both the frontend and the backend. It's important that you write this code in a particularly defensive way because it's limited by what both environments support:
4
5![shapes at 25-02-25 11.57.13.png](https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/75db1d51-d9b3-45e0-d178-25d886c10700/public)
6
7For example, you *cannot* use the `Deno` keyword. For imports, you can't use `npm:` specifiers, so we reccomend `https://esm.sh` because it works on the server & client. You *can* use TypeScript because that is transpiled in `/backend/index.ts` for the frontend. Most code that works on the frontend tends to work in Deno, because Deno is designed to support "web-standards", but there are definitely edge cases to look out for.
jeeves

jeevesREADME.md1 match

@brontojorisUpdated 1 week ago
21## `favicon.svg`
22
23As of this writing Val Town only supports text files, which is why the favicon is an SVG and not an .ico or any other binary image format. If you need binary file storage, check out [Blob Storage](https://docs.val.town/std/blob/).
24
25## `components/`

brainrot_image_gen1 file match

@dcm31Updated 2 days ago
Generate images for Italian Brainrot characters using FAL AI

modifyImage2 file matches

@stevekrouseUpdated 2 days ago