437 {profile && (
438 <div className="flex items-center space-x-4">
439 <img src={profile.profileImageUrl} alt="Profile" className="w-8 h-8 rounded-full" />
440 <span>{profile.username}</span>
441 <a href="/auth/logout" className="text-blue-400 hover:text-blue-300">Logout</a>
580 alt="Blob content"
581 className="max-w-full h-auto"
582 onError={() => console.error("Error loading image")}
583 />
584 </div>
630 <li>Create public shareable links for blobs</li>
631 <li>View and manage public folder</li>
632 <li>Preview images directly in the interface</li>
633 </ul>
634 </div>
1# ☔️ Umbrella reminder if there's rain today
2
3
4
5## Setup
186 'md': 'text/markdown',
187 'txt': 'text/plain',
188 'svg': 'image/svg+xml',
189 'png': 'image/png',
190 'jpg': 'image/jpeg',
191 'jpeg': 'image/jpeg',
192 'gif': 'image/gif'
193 };
194
47export interface MCPToolResult {
48 content: Array<{
49 type: "text" | "image" | "resource";
50 text?: string;
51 data?: string;
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.
4
5
6
7## Install
20 try {
21 const formData = await req.formData();
22 const imageFile = formData.get('image') as File;
23
24 if (!imageFile) {
25 return new Response(JSON.stringify({
26 error: 'No image file provided',
27 received_fields: Array.from(formData.keys())
28 }), {
35 }
36
37 // Validate image file
38 if (!imageFile.type.startsWith('image/')) {
39 return new Response(JSON.stringify({
40 error: 'File is not an image',
41 received_type: imageFile.type
42 }), {
43 status: 400,
52 const response = {
53 success: true,
54 message: "Image received successfully!",
55 image_info: {
56 filename: imageFile.name,
57 size_bytes: imageFile.size,
58 type: imageFile.type
59 },
60 timestamp: new Date().toISOString(),
70
71 } catch (error: any) {
72 console.error('Image processing error:', error);
73
74 return new Response(JSON.stringify({
75 error: 'Failed to process image upload',
76 details: error.message,
77 timestamp: new Date().toISOString()
64 headers: {
65 'User-Agent': userAgent,
66 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
67 'Accept-Language': 'en-US,en;q=0.5',
68 'Accept-Encoding': 'gzip, deflate, br',
10 "icons": [
11 {
12 "src": "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🗺️</text></svg>",
13 "sizes": "192x192",
14 "type": "image/svg+xml"
15 },
16 {
17 "src": "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🗺️</text></svg>",
18 "sizes": "512x512",
19 "type": "image/svg+xml"
20 }
21 ],
10 <link rel="manifest" href="/frontend/manifest.json">
11 <meta name="theme-color" content="#2563eb">
12 <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🗺️</text></svg>">
13</head>
14<body class="bg-gray-50 min-h-screen">
430}
431
432.project-card .project-image {
433 width: 24px;
434 height: 24px;
439}
440
441.project-image img {
442 width: 100%;
443 height: 100%;
540}
541
542.search-result .project-image {
543 width: 60px;
544 height: 60px;
549}
550
551.project-image img {
552 width: 100%;
553 height: 100%;