stevensDemoassets.ts6 matches
2// Background
3BACKGROUND:
4"https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/8b501664-722e-4be8-cf71-83aab7756e00/public",
56// Stevens
7STEVENS_FRONT:
8"https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/8b8432bb-add2-44ad-bb12-44b8ea215500/public",
9STEVENS_BACK:
10"https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/e28da8ab-7710-4b82-8e32-8fdf65c2ed00/public",
11STEVENS_WALKING:
12"https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/bd7b9997-09b2-4b35-6eb9-9975a85bb700/public",
1314// Mailman
15MAILMAN_STANDING:
16"https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/20a6493d-cc31-475e-aa83-ac97d317e400/public",
17MAILMAN_WALKING:
18"https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/61604576-8a83-4d85-d5e4-8e8e26641700/public",
19};
20
stevensDemoApp.tsx25 matches
82const [cookieAndTeaMode, setCookieAndTeaMode] = useState(false);
8384// Fetch images from backend instead of blob storage directly
85useEffect(() => {
86// Set default background color in case image doesn't load
87if (document.body) {
88document.body.style.backgroundColor = "#2D1700"; // Dark brown leather color
89}
9091// Fetch avatar image
92fetch("/api/images/stevens.jpg")
93.then((response) => {
94if (response.ok) return response.blob();
95throw new Error("Failed to load avatar image");
96})
97.then((imageBlob) => {
98const url = URL.createObjectURL(imageBlob);
99setAvatarUrl(url);
100})
104105// Fetch wood background
106fetch("/api/images/wood.jpg")
107.then((response) => {
108if (response.ok) return response.blob();
109throw new Error("Failed to load wood background");
110})
111.then((imageBlob) => {
112const url = URL.createObjectURL(imageBlob);
113setWoodUrl(url);
114115// Apply wood background to body
116if (document.body) {
117document.body.style.backgroundImage = `url(${url})`;
118}
119})
362return {
363position: SCENE_ELEMENTS.DESK_SITTING,
364image: ASSETS.STEVENS_FRONT,
365highlightElement: SCENE_ELEMENTS.DESK,
366animationClass: "no-animation",
372return {
373position: SCENE_ELEMENTS.DESK_SITTING,
374image: ASSETS.STEVENS_FRONT,
375highlightElement: null,
376animationClass: "no-animation",
387y: SCENE_ELEMENTS.MAILBOX.y - 20,
388},
389image: ASSETS.STEVENS_BACK,
390highlightElement: SCENE_ELEMENTS.MAILBOX,
391animationClass: "walk-to-mailbox",
398y: SCENE_ELEMENTS.CALENDAR.y + 30,
399},
400image: ASSETS.STEVENS_BACK,
401highlightElement: SCENE_ELEMENTS.CALENDAR,
402animationClass: "walk-to-calendar",
409y: SCENE_ELEMENTS.TELEGRAM.y + 10,
410},
411image: ASSETS.STEVENS_BACK,
412highlightElement: SCENE_ELEMENTS.TELEGRAM,
413animationClass: "walk-to-telegram",
417return {
418position: SCENE_ELEMENTS.OUTSIDE,
419image: ASSETS.STEVENS_FRONT,
420highlightElement: null,
421animationClass: "walk-to-outside",
425return {
426position: SCENE_ELEMENTS.DESK_SITTING,
427image: ASSETS.STEVENS_FRONT,
428highlightElement: SCENE_ELEMENTS.DESK,
429animationClass: "walk-to-desk",
623box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.4),
6240 3px 8px rgba(0, 0, 0, 0.5);
625image-rendering: pixelated;
626cursor: pointer;
627transition: transform 0.2s;
634.notebook-pages {
635background-color: #f8f1e0;
636background-image: linear-gradient(#d6c6a5 1px, transparent 1px);
637background-size: 100% 16px;
638box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.3);
639image-rendering: pixelated;
640}
641652653.pixel-character {
654image-rendering: pixelated;
655position: absolute;
656transition: left 0.7s ease-in-out, top 0.7s ease-in-out;
763className="w-[512px] h-[512px] mx-auto relative"
764style={{
765backgroundImage: `url(${ASSETS.BACKGROUND})`,
766backgroundSize: "cover",
767backgroundPosition: "center",
768imageRendering: "pixelated",
769}}
770>
799{/* Stevens character */}
800<img
801src={stevensState.image}
802alt="Stevens"
803className={`pixel-character ${
PerspectivologyMVPindex.tsx4 matches
179</div>
180
181{/* Right Column - Image */}
182<div className="flex justify-center lg:justify-end">
183<div className="relative">
187className="w-80 lg:w-96 xl:w-[500px] h-auto object-contain filter drop-shadow-2xl"
188onError={(e) => {
189// Fallback to a CSS-based crystal if image fails
190e.target.style.display = 'none';
191e.target.nextElementSibling.style.display = 'block';
488</div>
489
490{/* Right Side - 40% width - 3D Image */}
491<div className="w-full lg:w-2/5 flex items-center justify-center">
492<div className="relative">
496className="w-full h-96 object-cover rounded-2xl opacity-80"
497onError={(e) => {
498// Fallback to CSS design if image fails
499e.target.style.display = 'none';
500e.target.nextElementSibling.style.display = 'block';
23<div class="user-card" style="border: 1px solid #ccc; padding: 20px; margin: 10px; border-radius: 8px;">
24<h2><a href="${user.url}" target="_blank">${user.username}</a></h2>
25<img src="${user.profileImageUrl}" alt="${user.username}" style="width: 100px; height: 100px; object-fit: cover; border-radius: 50%;" />
26<p>${user.bio || ""}</p>
27<!-- <pre>${JSON.stringify(user.vals.data, null, 2)}</pre> -->
MiniAppStarterindex.tsx3 matches
5import * as db from "./db.ts";
6import { embedMetadata, handleFarcasterEndpoints, name } from "./farcaster.ts";
7import { handleImageEndpoints } from "./image.tsx";
89const app = new Hono();
1011handleImageEndpoints(app);
12handleFarcasterEndpoints(app);
1344<meta name="fc:frame" content={JSON.stringify(embedMetadata(baseUrl, path))} />
45<link rel="icon" href={baseUrl + "/icon"} />
46<meta property="og:image" content={baseUrl + "/image"} />
47</head>
48<body class="bg-white text-black dark:bg-black dark:text-white">
MiniAppStarterimage.tsx12 matches
5import satori from 'npm:satori'
67export function handleImageEndpoints(app: Hono) {
8const headers = {
9'Content-Type': 'image/png',
10'cache-control': 'public, max-age=86400',
11}
12app.get('/image', async (c) => {
13return c.body(await homeImage(), 200, headers)
14})
15app.get('/icon', async (c) => {
16const rounded = !!c.req.query('rounded')
17return c.body(await iconImage(rounded), 200, headers)
18})
19}
2021export async function homeImage() {
22return await ogImage(
23<div tw="w-full h-full flex justify-start items-end text-[100px] bg-black text-white p-[50px]">
24<div tw="flex flex-col items-start">
32}
3334export async function iconImage(rounded = false) {
35const roundedClass = rounded ? 'rounded-[96px]' : ''
36return await ogImage(
37<div
38tw={`w-full h-full flex justify-center items-center text-[100px] bg-[#7c65c1] text-white p-[50px] ${roundedClass}`}
49//////////
5051export async function ogImage(body, options = {}) {
52const svg = await satori(body, {
53width: 945,
59if (code === 'emoji') {
60const unicode = segment.codePointAt(0).toString(16).toUpperCase()
61return `data:image/svg+xml;base64,` + btoa(await loadEmoji(unicode))
62}
63return ''
95const base64 = Buffer.from(svg).toString('base64')
96// console.log('getIconDataUrl', name, svg, base64)
97return `data:image/svg+xml;base64,${base64}`
98}
99
MiniAppStarterfarcaster.ts4 matches
5export const name = "Mini App Demo";
6// export const iconUrl = "https://imgur.com/TrJLlwp.png";
7// export const ogImageUrl = "https://imgur.com/xKVOVUE.png";
89export function embedMetadata(baseUrl: string, path: string = "/") {
10return {
11version: "next",
12imageUrl: baseUrl + "/image",
13button: {
14title: name,
17name: name,
18url: baseUrl + path,
19splashImageUrl: baseUrl + "/icon",
20splashBackgroundColor: "#111111",
21},
55"iconUrl": baseUrl + "/icon",
56"homeUrl": baseUrl,
57"splashImageUrl": baseUrl + "/icon?rounded=1",
58"splashBackgroundColor": "#111111",
59"primaryCategory": "developer-tools",
stevensDemoREADME.md1 match
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:
45
67For 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.
stevensDemoREADME.md1 match
21## `favicon.svg`
2223As 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/).
2425## `components/`
stevensDemoindex.ts15 matches
73});
7475// --- Blob Image Serving Routes ---
7677// GET /api/images/:filename - Serve images from blob storage
78app.get("/api/images/:filename", async (c) => {
79const filename = c.req.param("filename");
8081try {
82// Get image data from blob storage
83const imageData = await blob.get(filename);
8485if (!imageData) {
86return c.json({ error: "Image not found" }, 404);
87}
8890let contentType = "application/octet-stream"; // Default
91if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {
92contentType = "image/jpeg";
93} else if (filename.endsWith(".png")) {
94contentType = "image/png";
95} else if (filename.endsWith(".gif")) {
96contentType = "image/gif";
97} else if (filename.endsWith(".svg")) {
98contentType = "image/svg+xml";
99}
100101// Return the image with appropriate headers
102return new Response(imageData, {
103headers: {
104"Content-Type": contentType,
107});
108} catch (error) {
109console.error(`Error serving image ${filename}:`, error);
110return c.json(
111{ error: "Failed to load image", details: error.message },
112500,
113);