···66- Data is stored in user's PDS under collection `app.blento.card`
67- **Important**: ATProto does not allow floating point numbers in records. All numeric values must be integers.
680000000000069**Data Loading (`src/lib/website/`):**
7071-- `load.ts` - Fetches user data from their PDS, with optional KV caching via `UserCache`
72- `data.ts` - Defines which collections/records to fetch
73- `context.ts` - Svelte contexts for passing DID, handle, and data down the component tree
74
···66- Data is stored in user's PDS under collection `app.blento.card`
67- **Important**: ATProto does not allow floating point numbers in records. All numeric values must be integers.
6869+**Caching (`src/lib/cache.ts`):**
70+71+- `CacheService` class wraps a single Cloudflare KV namespace (`USER_DATA_CACHE`) with namespaced keys
72+- Keys are stored as `namespace:key` (e.g. `user:did:plc:abc`, `github:someuser`, `lastfm:method:user:period:limit`)
73+- Per-namespace default TTLs via KV `expirationTtl`: `user` (24h), `identity` (7d), `github` (12h), `gh-contrib` (12h), `lastfm` (1h, overridable), `npmx` (12h), `meta` (no expiry)
74+- User data is keyed by DID with bidirectional handle↔DID identity mappings (`identity:h:{handle}` → DID, `identity:d:{did}` → handle)
75+- `getUser(identifier)` accepts either a handle or DID and resolves automatically
76+- `putUser(did, handle, data)` writes data + both identity mappings
77+- `createCache(platform)` factory function creates a `CacheService` from `platform.env`
78+- `CUSTOM_DOMAINS` KV namespace is separate and accessed directly for custom domain → DID resolution
79+80**Data Loading (`src/lib/website/`):**
8182+- `load.ts` - Fetches user data from their PDS, with optional caching via `CacheService`
83- `data.ts` - Defines which collections/records to fetch
84- `context.ts` - Svelte contexts for passing DID, handle, and data down the component tree
85
···1import type { Component } from 'svelte';
2-import type { Item, UserCache } from '$lib/types';
03import type { Did } from '@atcute/lexicons';
45export type CreationModalComponentProps = {
···36 loadData?: (
37 // all cards of that type
38 items: Item[],
39- { did, handle, cache }: { did: Did; handle: string; cache?: UserCache }
40 ) => Promise<unknown>;
4142 // show color selection popup
···1import type { Component } from 'svelte';
2+import type { Item } from '$lib/types';
3+import type { CacheService } from '$lib/cache';
4import type { Did } from '@atcute/lexicons';
56export type CreationModalComponentProps = {
···37 loadData?: (
38 // all cards of that type
39 items: Item[],
40+ { did, handle, cache }: { did: Did; handle: string; cache?: CacheService }
41 ) => Promise<unknown>;
4243 // show color selection popup