515<meta charset="UTF-8">
516<meta name="viewport" content="width=device-width, initial-scale=1.0">
517<link rel="icon" type="image/png" href="https://labspace.ai/ls2-circle.png" />
518<title>Breakdown</title>
519<meta property="og:title" content="Breakdown" />
520<meta property="og:description" content="Break down topics into different perspectives and arguments with AI-powered balanced analysis" />
521<meta property="og:image" content="https://yawnxyz-og.web.val.run/img2?link=https://breakdown.labspace.ai&title=Breakdown&subtitle=Balanced+perspective+analysis&panelWidth=700&attachment=https://f2.phage.directory/capsid/20bEQGy3/breakdown-scr2_public.png" />
522<meta property="og:url" content="https://breakdown.labspace.ai/" />
523<meta property="og:type" content="website" />
524<meta name="twitter:card" content="summary_large_image" />
525<meta name="twitter:title" content="Breakdown" />
526<meta name="twitter:description" content="Break down topics into different perspectives and arguments with AI-powered balanced analysis" />
527<meta name="twitter:image" content="https://yawnxyz-og.web.val.run/img2?link=https://breakdown.labspace.ai&title=Breakdown&subtitle=Balanced+perspective+analysis&panelWidth=700&attachment=https://f2.phage.directory/capsid/20bEQGy3/breakdown-scr2_public.png" />
528529<script src="https://cdn.tailwindcss.com"></script>
blob_adminREADME.md1 match
3This is a lightweight Blob Admin interface to view and debug your Blob data.
45
67Versions 0-17 of this val were done with Hono and server-rendering.
187<div key={index} className="bg-white shadow-md rounded px-4 sm:px-8 pt-6 pb-8 mb-8">
188<h3 className="text-2xl font-bold mb-4 text-indigo-500">{recipe.name}</h3>
189{recipe.image && (
190<div className="mb-6">
191<img src={recipe.image} alt={recipe.name} className="w-full h-64 object-cover rounded-lg" />
192</div>
193)}
270const recipes = JSON.parse(jsonContent);
271272// Generate images for each recipe
273const recipesWithImages = await Promise.all(
274recipes.map(async (recipe) => {
275try {
276const imageUrl = await generateImage(recipe.name);
277return { ...recipe, image: imageUrl };
278} catch (error) {
279console.error(`Failed to generate image for ${recipe.name}:`, error);
280return { ...recipe, image: null };
281}
282})
283);
284285return new Response(JSON.stringify({ recipes: recipesWithImages }), {
286headers: { "Content-Type": "application/json" },
287});
308<meta property="og:title" content="Lazy Cook">
309<meta property="og:description" content="If you don't feel like going through your recipe books, Lazy Cook to the rescue!">
310<meta property="og:image" content="https://opengraph.b-cdn.net/production/images/90b45fbc-3605-4722-97d5-c707f94488ca.jpg?token=QsSAtAFq7L3G7tMgFKZa1vzT5hYhPOAsXtgLfWUE5zk&height=800&width=1200&expires=33269333680">
311312<!-- Twitter Meta Tags -->
313<meta name="twitter:card" content="summary_large_image">
314<meta property="twitter:domain" content="karkowg-lazycook.web.val.run">
315<meta property="twitter:url" content="https://karkowg-lazycook.web.val.run/">
316<meta name="twitter:title" content="Lazy Cook">
317<meta name="twitter:description" content="If you don't feel like going through your recipe books, Lazy Cook to the rescue!">
318<meta name="twitter:image" content="https://opengraph.b-cdn.net/production/images/90b45fbc-3605-4722-97d5-c707f94488ca.jpg?token=QsSAtAFq7L3G7tMgFKZa1vzT5hYhPOAsXtgLfWUE5zk&height=800&width=1200&expires=33269333680">
319320<!-- Meta Tags Generated via https://www.opengraph.xyz -->
338}
339340async function generateImage(recipeName: string): Promise<string> {
341const response = await fetch(`https://maxm-imggenurl.web.val.run/${encodeURIComponent(recipeName)}`);
342if (!response.ok) {
343throw new Error(`Failed to generate image for ${recipeName}`);
344}
345return response.url;
socialDataSearchmain.tsx1 match
57created_at: string;
58profile_banner_url: string;
59profile_image_url_https: string;
60can_dm: boolean;
61}
sqliteExplorerAppREADME.md1 match
3View and interact with your Val Town SQLite data. It's based off Steve's excellent [SQLite Admin](https://www.val.town/v/stevekrouse/sqlite_admin?v=46) val, adding the ability to run SQLite queries directly in the interface. This new version has a revised UI and that's heavily inspired by [LibSQL Studio](https://github.com/invisal/libsql-studio) by [invisal](https://github.com/invisal). This is now more an SPA, with tables, queries and results showing up on the same page.
45
67## Install
forEmulated1main.tsx23 matches
3import { createRoot } from "https://esm.sh/react-dom/client";
4import debounce from "https://esm.sh/lodash.debounce";
5import imageCompression from "https://esm.sh/browser-image-compression";
67function App() {
11const [editPrompt, setEditPrompt] = useState('');
12const [isRefining, setIsRefining] = useState(false);
13const [lastUploadedImage, setLastUploadedImage] = useState(null);
14const [showCopiedMessage, setShowCopiedMessage] = useState(false);
15const [theme, setTheme] = useState(() => {
42}, []);
4344const generateLandingPage = async (isInitial = true, imageBase64 = null, existingCode = '', editPrompt = '') => {
45setIsLoading(true);
46setIsRefining(isInitial ? false : true);
53body: JSON.stringify({
54isInitial,
55imageBase64,
56existingCode,
57editPrompt
78};
7980const compressImage = async (file) => {
81const options = {
82maxSizeMB: 1,
85};
86try {
87const compressedFile = await imageCompression(file, options);
88return compressedFile;
89} catch (error) {
90console.error("Error compressing image:", error);
91return file;
92}
93};
9495const handleImageUpload = async (event) => {
96const file = event.target.files[0];
97if (file) {
98const compressedFile = await compressImage(file);
99const reader = new FileReader();
100reader.onloadend = () => {
101const base64 = reader.result.split(',')[1];
102setLastUploadedImage(base64);
103generateLandingPage(true, base64);
104};
108109const handleRegenerate = () => {
110if (lastUploadedImage) {
111generateLandingPage(true, lastUploadedImage);
112} else {
113alert("Please upload an image first before regenerating.");
114}
115};
211<input
212type="file"
213accept="image/*"
214ref={fileInputRef}
215onChange={handleImageUpload}
216className="hidden"
217/>
221disabled={isLoading}
222>
223{isLoading ? 'Generating...' : 'Upload Design Image'}
224</button>
225<button
226onClick={handleRegenerate}
227className="bg-green-500 text-white px-4 py-2 rounded dark:bg-green-600 hover:bg-green-600 dark:hover:bg-green-700 transition-colors"
228disabled={isLoading || !lastUploadedImage}
229>
230Regenerate
325const openai = new OpenAI();
326327const { isInitial, imageBase64, existingCode, editPrompt } = await request.json();
328329console.log('Refinement Request Details:', {
330isInitial,
331imageBase64: imageBase64 ? `${imageBase64.slice(0, 50)}...` : null,
332existingCodeLength: existingCode ? existingCode.length : 0,
333editPrompt
336let designDescription = '';
337338if (isInitial && imageBase64) {
339const visionResponse = await openai.chat.completions.create({
340model: "gpt-4-vision-preview",
345{
346type: "text",
347text: "Analyze this landing page design image in detail. Focus on the following aspects:\n\n1. Overall layout structure (header, main sections, footer)\n2. Color scheme (primary, secondary, accent colors)\n3. Typography (font styles, sizes, hierarchy)\n4. Key visual elements (images, icons, illustrations)\n5. Call-to-action buttons and their placement\n6. Navigation menu structure\n7. Content sections and their arrangement\n8. Mobile responsiveness considerations\n9. Any unique or standout design features\n\nProvide a comprehensive description that a web developer could use to accurately recreate this design using HTML and Tailwind CSS."
348},
349{
350type: "image_url",
351image_url: { url: `data:image/jpeg;base64,${imageBase64}` }
352}
353]
noCollectionTrackerREADME.md2 matches
113. **Reflection Stage**: After 5 "No" responses, users enter a reflection stage to contemplate their journey.
124. **Motivational Quotes**: Dynamic quotes change based on the user's progress to provide encouragement.
135. **Journey Visualization**: Users can upload a symbolic image representing their journey.
146. **PDF Generation**: At the end of the challenge, users can generate a PDF summary of their journey.
157. **Data Privacy**: All data is stored locally on the user's device, ensuring privacy and security.
252. **Reflection Stage**:
26- Triggered after receiving 5 "No" responses.
27- Users can upload a symbolic image and write a comprehensive reflection.
28293. **Completion Stage**:
md_links_resolvermain.tsx1 match
220<title>Markdown Links Resolver</title>
221<meta name="viewport" content="width=device-width, initial-scale=1">
222<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'><text font-size='200' x='50%' y='50%' text-anchor='middle' dominant-baseline='central'>🔗</text></svg>">
223<style>
224body, html {
versatileBlackKitemain.tsx79 matches
6function App() {
7const [youtubeUrl, setYoutubeUrl] = useState("https://www.youtube.com/embed/QskiaNqaqlc?si=MvD_ydotKgovS9pC");
8const [postVideoImages, setPostVideoImages] = useState<string[]>([]);
9const [newImageUrl, setNewImageUrl] = useState("");
10const [imageErrors, setImageErrors] = useState<{[key: number]: boolean}>({});
11const [imageProxyUrls, setImageProxyUrls] = useState<{[key: number]: string}>({});
1213useEffect(() => {
1718useEffect(() => {
19// Proxy images that might have CORS issues
20postVideoImages.forEach((imageUrl, index) => {
21proxyImage(imageUrl, index);
22});
23}, [postVideoImages]);
2425const proxyImage = async (imageUrl: string, index: number) => {
26try {
27const response = await fetch(`/proxy-image?url=${encodeURIComponent(imageUrl)}`);
28if (response.ok) {
29const proxyUrl = await response.text();
30setImageProxyUrls(prev => ({...prev, [index]: proxyUrl}));
31} else {
32handleImageError(index);
33}
34} catch (error) {
35console.error("Image proxy error:", error);
36handleImageError(index);
37}
38};
42const { blob } = await import("https://esm.town/v/std/blob");
43const savedYoutubeUrl = await blob.get(`${getLegacyImportUrl(import.meta.url)}_youtubeUrl`);
44const savedImages = await blob.get(`${getLegacyImportUrl(import.meta.url)}_postVideoImages`);
45
46if (savedYoutubeUrl) setYoutubeUrl(savedYoutubeUrl);
47if (savedImages) {
48const parsedImages = JSON.parse(savedImages);
49setPostVideoImages(parsedImages);
50}
51} catch (error) {
54};
5556const saveData = async (type: 'url' | 'images') => {
57try {
58const { blob } = await import("https://esm.town/v/std/blob");
60await blob.set(`${getLegacyImportUrl(import.meta.url)}_youtubeUrl`, youtubeUrl);
61} else {
62await blob.set(`${getLegacyImportUrl(import.meta.url)}_postVideoImages`, JSON.stringify(postVideoImages));
63}
64} catch (error) {
67};
6869const isValidImageUrl = (url: string) => {
70try {
71const parsedUrl = new URL(url);
74(parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:') &&
75(
76// General image extensions
77/\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(parsedUrl.pathname) ||
78// AWS S3 URL patterns
87};
8889const handleAddImage = () => {
90if (newImageUrl.trim() && isValidImageUrl(newImageUrl.trim())) {
91const updatedImages = [...postVideoImages, newImageUrl.trim()];
92setPostVideoImages(updatedImages);
93setNewImageUrl("");
94saveData('images');
95} else {
96alert("Please enter a valid image URL (supports JPG, PNG, GIF, WebP, BMP, and AWS S3 URLs)");
97}
98};
99100const handleRemoveImage = (indexToRemove: number) => {
101const updatedImages = postVideoImages.filter((_, index) => index !== indexToRemove);
102setPostVideoImages(updatedImages);
103
104// Remove any associated error and proxy states
105const newImageErrors = {...imageErrors};
106const newImageProxyUrls = {...imageProxyUrls};
107delete newImageErrors[indexToRemove];
108delete newImageProxyUrls[indexToRemove];
109
110setImageErrors(newImageErrors);
111setImageProxyUrls(newImageProxyUrls);
112
113saveData('images');
114};
115116const handleImageError = (index: number) => {
117setImageErrors(prev => ({...prev, [index]: true}));
118};
119122<h1 style={styles.title}>Interactive Video Presentation</h1>
123<p style={styles.description}>
124Welcome to our dynamic video presentation. You can customize the video and add post-video images.
125</p>
126
153</div>
154155{/* Post Video Images Section */}
156<div style={styles.postVideoSection}>
157<h3>Post Video Images</h3>
158<div style={styles.imageInputContainer}>
159<input
160type="text"
161value={newImageUrl}
162onChange={(e) => setNewImageUrl(e.target.value)}
163style={styles.urlInput}
164placeholder="Enter Image URL (supports AWS S3)"
165/>
166<button onClick={handleAddImage} style={styles.saveButton}>Add Image</button>
167</div>
168
169{/* Image Gallery */}
170<div style={styles.imageGallery}>
171{postVideoImages.map((imageUrl, index) => (
172<div key={index} style={styles.imageItem}>
173{imageErrors[index] ? (
174<div style={styles.errorImage}>
175<span>❌ Image Failed to Load</span>
176<p>{imageUrl}</p>
177</div>
178) : (
179<img
180src={imageProxyUrls[index] || imageUrl}
181alt={`Post video image ${index + 1}`}
182style={styles.galleryImage}
183onError={() => handleImageError(index)}
184/>
185)}
186<button
187onClick={() => handleRemoveImage(index)}
188style={styles.removeButton}
189>
213214export default async function server(request: Request): Promise<Response> {
215// Image proxy endpoint
216const url = new URL(request.url);
217if (url.pathname === '/proxy-image') {
218const imageUrl = url.searchParams.get('url');
219if (!imageUrl) {
220return new Response('No URL provided', { status: 400 });
221}
222223try {
224const imageResponse = await fetch(imageUrl, {
225headers: {
226'User-Agent': 'Mozilla/5.0',
227'Referer': new URL(imageUrl).origin
228}
229});
230231if (!imageResponse.ok) {
232return new Response('Image fetch failed', { status: imageResponse.status });
233}
234235const imageBlob = await imageResponse.blob();
236return new Response(imageBlob, {
237headers: {
238'Content-Type': imageResponse.headers.get('Content-Type') || 'image/jpeg',
239'Cache-Control': 'public, max-age=86400' // Cache for 24 hours
240}
241});
242} catch (error) {
243return new Response('Image proxy error', { status: 500 });
244}
245}
315marginTop: '20px',
316},
317imageInputContainer: {
318display: 'flex',
319marginBottom: '20px',
320gap: '10px',
321},
322imageGallery: {
323display: 'flex',
324flexWrap: 'wrap',
326justifyContent: 'center',
327},
328imageItem: {
329position: 'relative',
330display: 'flex',
332alignItems: 'center',
333},
334galleryImage: {
335maxWidth: '200px',
336maxHeight: '200px',
338borderRadius: '8px',
339},
340errorImage: {
341width: '200px',
342height: '200px',
embedVideoWebPagemain.tsx81 matches
6function App() {
7const [youtubeUrl, setYoutubeUrl] = useState("https://www.youtube.com/embed/QskiaNqaqlc?si=MvD_ydotKgovS9pC");
8const [postVideoImages, setPostVideoImages] = useState<string[]>([]);
9const [newImageUrl, setNewImageUrl] = useState("");
10const [imageErrors, setImageErrors] = useState<{[key: number]: boolean}>({});
11const [imageProxyUrls, setImageProxyUrls] = useState<{[key: number]: string}>({});
1213useEffect(() => {
1617useEffect(() => {
18// Proxy images that might have CORS issues
19postVideoImages.forEach((imageUrl, index) => {
20if (!imageErrors[index]) {
21proxyImage(imageUrl, index);
22}
23});
24}, [postVideoImages]);
2526const proxyImage = async (imageUrl: string, index: number) => {
27try {
28const response = await fetch(`/proxy-image?url=${encodeURIComponent(imageUrl)}`, {
29headers: {
30'Cache-Control': 'no-cache' // Ensure fresh fetch
33if (response.ok) {
34const proxyUrl = await response.text();
35setImageProxyUrls(prev => ({...prev, [index]: proxyUrl}));
36// Reset any previous error for this image
37setImageErrors(prev => {
38const newErrors = {...prev};
39delete newErrors[index];
41});
42} else {
43handleImageError(index);
44}
45} catch (error) {
46console.error("Image proxy error:", error);
47handleImageError(index);
48}
49};
53const { blob } = await import("https://esm.town/v/std/blob");
54const savedYoutubeUrl = await blob.get(`${getLegacyImportUrl(import.meta.url)}_youtubeUrl`);
55const savedImages = await blob.get(`${getLegacyImportUrl(import.meta.url)}_postVideoImages`);
56
57if (savedYoutubeUrl) setYoutubeUrl(savedYoutubeUrl);
58if (savedImages) {
59const parsedImages = JSON.parse(savedImages);
60setPostVideoImages(parsedImages);
61}
62} catch (error) {
65};
6667const saveData = async (type: 'url' | 'images') => {
68try {
69const { blob } = await import("https://esm.town/v/std/blob");
71await blob.set(`${getLegacyImportUrl(import.meta.url)}_youtubeUrl`, youtubeUrl);
72} else {
73await blob.set(`${getLegacyImportUrl(import.meta.url)}_postVideoImages`, JSON.stringify(postVideoImages));
74}
75} catch (error) {
78};
7980const isValidImageUrl = (url: string) => {
81try {
82new URL(url);
87};
8889const handleAddImage = () => {
90if (newImageUrl.trim() && isValidImageUrl(newImageUrl.trim())) {
91const updatedImages = [...postVideoImages, newImageUrl.trim()];
92setPostVideoImages(updatedImages);
93setNewImageUrl("");
94saveData('images');
95} else {
96alert("Please enter a valid image URL with a supported extension");
97}
98};
99100const handleRemoveImage = (indexToRemove: number) => {
101const updatedImages = postVideoImages.filter((_, index) => index !== indexToRemove);
102setPostVideoImages(updatedImages);
103
104// Remove any associated error and proxy states
105const newImageErrors = {...imageErrors};
106const newImageProxyUrls = {...imageProxyUrls};
107delete newImageErrors[indexToRemove];
108delete newImageProxyUrls[indexToRemove];
109
110setImageErrors(newImageErrors);
111setImageProxyUrls(newImageProxyUrls);
112
113saveData('images');
114};
115116const handleImageError = (index: number) => {
117setImageErrors(prev => ({...prev, [index]: true}));
118};
119120const retryImageLoad = (index: number) => {
121const imageUrl = postVideoImages[index];
122proxyImage(imageUrl, index);
123};
124127<h1 style={styles.title}>Interactive Video Presentation</h1>
128<p style={styles.description}>
129Welcome to our dynamic video presentation. You can customize the video and add post-video images.
130</p>
131
158</div>
159160{/* Post Video Images Section */}
161<div style={styles.postVideoSection}>
162<h3>Post Video Images</h3>
163<div style={styles.imageInputContainer}>
164<input
165type="text"
166value={newImageUrl}
167onChange={(e) => setNewImageUrl(e.target.value)}
168style={styles.urlInput}
169placeholder="Enter Image URL"
170/>
171<button onClick={handleAddImage} style={styles.saveButton}>Add Image</button>
172</div>
173
174{/* Image Gallery */}
175<div style={styles.imageGallery}>
176{postVideoImages.map((imageUrl, index) => (
177<div key={index} style={styles.imageItem}>
178{imageErrors[index] ? (
179<div style={styles.errorImage}>
180<span>❌ Image Failed to Load</span>
181<p>{imageUrl}</p>
182<button
183onClick={() => retryImageLoad(index)}
184style={{...styles.saveButton, marginTop: '10px'}}
185>
189) : (
190<img
191src={imageProxyUrls[index] || imageUrl}
192alt={`Post video image ${index + 1}`}
193style={styles.galleryImage}
194onError={() => handleImageError(index)}
195/>
196)}
197<button
198onClick={() => handleRemoveImage(index)}
199style={styles.removeButton}
200>
224225export default async function server(request: Request): Promise<Response> {
226// Image proxy endpoint
227const url = new URL(request.url);
228if (url.pathname === '/proxy-image') {
229const imageUrl = url.searchParams.get('url');
230if (!imageUrl) {
231return new Response('No URL provided', { status: 400 });
232}
233234try {
235const imageResponse = await fetch(imageUrl, {
236headers: {
237'User-Agent': 'Mozilla/5.0',
238'Referer': new URL(imageUrl).origin,
239'Accept': 'image/*'
240}
241});
242243if (!imageResponse.ok) {
244return new Response('Image fetch failed', { status: imageResponse.status });
245}
246247const imageBlob = await imageResponse.blob();
248return new Response(imageBlob, {
249headers: {
250'Content-Type': imageResponse.headers.get('Content-Type') || 'image/jpeg',
251'Cache-Control': 'public, max-age=86400', // Cache for 24 hours
252'Access-Control-Allow-Origin': '*'
254});
255} catch (error) {
256return new Response('Image proxy error', { status: 500 });
257}
258}