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.shfor all imports to ensure browser/server compatibility - Pin React dependencies to version 18.2.0
- 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
serveStaticmiddleware - 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 (noDenokeyword) - File Handling: Only text files supported, use
readFilehelpers 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>