This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a Photography Weather Dashboard called "Kur saulytė?" - a dense, mobile-first weather website designed for photographers to quickly check upcoming weather conditions with focus on cloud cover, visibility, and lighting conditions. The app provides hourly weather data for 7 days with photography-specific scoring and golden hour detection.
- Runtime: Deno (Val Town platform)
- Backend: Hono web framework
- Frontend: React 19 with TypeScript
- Styling: CSS with responsive grid layouts
- Data Source: Open-Meteo KNMI API (no API key required)
├── backend/
│ └── index.ts # Hono server with Open-Meteo SDK integration
├── frontend/
│ ├── index.html # Main HTML page
│ ├── index.tsx # React app with weather dashboard UI
│ └── style.css # Mobile-optimized styles with responsive grid
├── deno.json # Deno configuration
└── README.md
- Hono server with error unwrapping for better debugging
- Static file serving using Val Town utilities (
serveFile
,readFile
) - Three main API endpoints:
/api/weather?lat={lat}&lon={lon}
- Weather data with photography insights/api/location
- Auto-detect location from IP with Amsterdam fallback/api/geocode?q={query}
- Search locations by city/area name
- Photography scoring algorithm that calculates 1-10 ratings based on:
- Cloud cover percentage (main factor)
- Visibility in kilometers
- Precipitation levels
- Golden hour timing (±1 hour from sunrise/sunset)
- React 18.2.0 with TypeScript interfaces
- Responsive grid layout: 6 → 8 → 12 → 24 columns based on screen size
- Key features:
- Auto-location detection with manual override
- Real-time city/area search with geocoding
- Past day minimization (auto-collapses with toggle)
- Golden hour highlighting with special visual indicators
- Cloud layer visualization (low/mid/high altitude)
- Photography score bars and condition emojis
- Location Detection: Auto-detect via IP or manual search/coordinates
- Weather Fetch: Query Open-Meteo KNMI API with comprehensive hourly data
- Photography Analysis: Generate insights with scoring algorithm
- UI Rendering: Display in responsive grid with day/night distinction
Since this is a Val Town project, there are no traditional build commands. Development happens directly on the platform.
When extending this project, you can use Val Town's hosted services:
import { blob } from "https://esm.town/v/std/blob";
await blob.setJSON("myKey", { hello: "world" });
let data = await blob.getJSON("myKey");
let keys = await blob.list("app_");
await blob.delete("myKey");
import { sqlite } from "https://esm.town/v/stevekrouse/sqlite";
const TABLE_NAME = 'weather_cache_1';
// Create table - change table name when modifying schema
await sqlite.execute(`CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
location TEXT NOT NULL,
data TEXT NOT NULL,
timestamp INTEGER
)`);
const result = await sqlite.execute(`SELECT * FROM ${TABLE_NAME} WHERE location = ?`, ["Amsterdam"]);
import { email } from "https://esm.town/v/std/email";
await email({
subject: "Weather Alert",
text: "Perfect photography conditions detected!",
html: "<h1>Perfect photography conditions detected!</h1>"
});
import { OpenAI } from "https://esm.town/v/std/openai";
const openai = new OpenAI();
const completion = await openai.chat.completions.create({
messages: [{ role: "user", content: "Describe this weather for photography" }],
model: "gpt-4o-mini",
max_tokens: 100,
});
- Use
https://esm.sh
for all imports to ensure browser/server compatibility - Pin React dependencies to version 19
- Always include
/** @jsxImportSource https://esm.sh/react@19 */
at top of React files - Use environment variables with
Deno.env.get()
for secrets (never bake into code)
- Golden Hour Detection: ±1 hour window around sunrise/sunset times
- Scoring Algorithm: 10-point scale with cloud cover as primary factor
- Day/Night Distinction: Only show detailed data and scores for daylight hours
- Condition Mapping:
- Excellent (☀️): <20% clouds
- Very Good (🌤️): 20-40% clouds
- Good (⛅): 40-60% clouds
- Fair (☁️): 60-80% clouds
- Poor (☁️): >80% clouds
- Golden Hour (🌅): Special case for optimal lighting
- Mobile-first design with responsive breakpoints
- Stable grid positioning - time always at top, cloud % prominent
- Toned-down color palette with colored left borders for scanning
- Progressive enhancement - works without JavaScript for basic weather
- Past day minimization - auto-collapse old data with expand option
- Text files only (no binary uploads)
- Serverless Deno environment
- No Node.js APIs available
- Cannot use
alert()
,prompt()
, orconfirm()
- Use
return new Response(null, { status: 302, headers: { Location: "/path" }})
for redirects - DO NOT use Deno KV module for storage
- Use
Response.redirect()
is broken - use manual redirect headers instead - Add
<script src="https://esm.town/v/std/catch"></script>
to HTML for client-side error debugging
- TypeScript required with strict interfaces
- Functional programming preferred over classes
- No external images - use emojis, Unicode symbols, or icon fonts
- Error handling: Let errors bubble up with context rather than catching/logging
- Never include secrets in code - always use environment variables
- Prefer official SDKs over writing API calls directly
- Comments: Only explain complex logic, avoid commenting obvious operations
- Complete solutions: Provide functional implementations, not skeleton code
- NEVER use
serveStatic
middleware - it doesn't work on Val Town - Always use Val Town utilities:
import { readFile, serveFile } from "https://esm.town/v/std/utils/index.ts"
- NEVER import CORS middleware - Val Town handles CORS automatically
- For cookies:
import { deleteCookie, getCookie, setCookie } from "npm:hono/cookie"
- Always add error unwrapping:
- Weather: Open-Meteo KNMI API (free, no API key)
- Geocoding: Open-Meteo Geocoding API (free, no API key)
- Location: ip-api.com for IP-based location detection
- Fallback: Amsterdam coordinates (52.3676, 4.9041) if detection fails
This project uses HTTP triggers, but Val Town supports multiple trigger types:
export default async function (email: Email) {
// Could process weather alert subscription emails
}
Always import with version pins:
import { readFile, serveFile, listFiles } from "https://esm.town/v/std/utils@85-main/index.ts";
Important: These utilities ONLY run on the server. Pass data to client via HTML injection or API calls.
This is a Val Town project that auto-deploys on save. No traditional CI/CD pipeline.
For local development testing:
- Test location detection with different IP ranges
- Verify geocoding search with various city names and coordinates
- Test responsive design across mobile/tablet/desktop breakpoints
- Validate photography scoring algorithm with edge cases (100% clouds, 0% clouds, etc.)
- SQLite Schema Changes: Change table names instead of using ALTER TABLE
- Shared Code: Code in
shared/
must work in both frontend and backend (noDeno
keyword) - File Handling: Only text files supported, use
readFile
helpers for project files - Images: Use AI image generation:
<img src="https://maxm-imggenurl.web.val.run/description" />
- Default Styling: Use TailwindCSS via
<script src="https://cdn.twind.style" crossorigin></script>