uk.ewancroft.site.info
Samples
1 randomly sampled records from the AT Protocol firehose
uk.ewancroft.site.info (1 sample)
{
"$type": "uk.ewancroft.site.info",
"credits": [
{
"url": "https://github.com/rsms/inter",
"name": "Inter",
"type": "font",
"author": "Rasmus Andersson",
"license": {
"url": "https://scripts.sil.org/OFL",
"name": "SIL Open Font License"
},
"section": "Typography",
"description": "Variable font family used for the website UI (headings and body text)"
},
{
"url": "https://svelte.dev",
"name": "Svelte",
"type": "framework",
"section": "Core Framework",
"description": "Reactive JavaScript framework with Svelte 5 runes support for modern reactive programming"
},
{
"url": "https://kit.svelte.dev",
"name": "SvelteKit",
"type": "framework",
"section": "Core Framework",
"description": "Application framework for Svelte with server-side rendering, routing, and API endpoints"
},
{
"url": "https://tailwindcss.com",
"name": "Tailwind CSS",
"type": "library",
"section": "Styling",
"description": "Utility-first CSS framework for rapid UI development with Tailwind 4 native CSS support"
},
{
"url": "https://github.com/tailwindlabs/tailwindcss-typography",
"name": "@tailwindcss/typography",
"type": "library",
"section": "Styling",
"description": "Typography plugin for Tailwind CSS providing beautiful typographic defaults for prose content"
},
{
"url": "https://vitejs.dev",
"name": "Vite",
"type": "tool",
"section": "Build Tools",
"description": "Next generation frontend build tool with fast HMR and optimised production builds"
},
{
"url": "https://www.typescriptlang.org",
"name": "TypeScript",
"type": "language",
"section": "Development",
"description": "Typed superset of JavaScript adding optional static types for better development experience"
},
{
"url": "https://prettier.io",
"name": "Prettier",
"type": "tool",
"section": "Development Tools",
"description": "Opinionated code formatter supporting multiple languages for consistent code style"
},
{
"url": "https://github.com/sveltejs/prettier-plugin-svelte",
"name": "prettier-plugin-svelte",
"type": "library",
"section": "Development Tools",
"description": "Prettier plugin for formatting Svelte components with proper syntax handling"
},
{
"url": "https://github.com/tailwindlabs/prettier-plugin-tailwindcss",
"name": "prettier-plugin-tailwindcss",
"type": "library",
"section": "Development Tools",
"description": "Prettier plugin for automatic and consistent Tailwind CSS class ordering"
},
{
"url": "https://lucide.dev",
"name": "Lucide Icons",
"type": "library",
"section": "UI Components",
"description": "Icon library providing consistent, customisable SVG icons for the website interface"
},
{
"url": "https://github.com/video-dev/hls.js",
"name": "hls.js",
"type": "library",
"section": "Media",
"description": "JavaScript library for HTTP Live Streaming client supporting video playback"
},
{
"url": "https://atproto.com/docs/api",
"name": "@atproto/api",
"type": "library",
"license": {
"url": "https://github.com/bluesky-social/atproto/blob/main/LICENSE",
"name": "MIT License"
},
"section": "Backend Integration",
"description": "Official type-safe TypeScript client library for interacting with AT Protocol services, personal data servers, and distributed repositories"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/atproto",
"name": "@ewanc26/atproto",
"type": "library",
"license": {
"url": "https://www.gnu.org/licenses/agpl-3.0.en.html",
"name": "AGPL 3.0"
},
"section": "Backend Integration",
"description": "Personal AT Protocol abstraction library providing typed wrappers for profile, site info, links, music status, Kibun status, Tangled repos, engagement data, media utilities, and artwork lookup"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/supporters",
"name": "@ewanc26/supporters",
"type": "library",
"license": {
"url": "https://www.gnu.org/licenses/agpl-3.0.en.html",
"name": "AGPL 3.0"
},
"section": "Backend Integration",
"description": "Personal library for fetching Ko-fi supporter events stored as AT Protocol records"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/tid",
"name": "@ewanc26/tid",
"type": "library",
"license": {
"url": "https://www.gnu.org/licenses/agpl-3.0.en.html",
"name": "AGPL 3.0"
},
"section": "Backend Integration",
"description": "Personal utility library for working with AT Protocol TID (timestamp-based identifier) formats"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/ui",
"name": "@ewanc26/ui",
"type": "library",
"license": {
"url": "https://www.gnu.org/licenses/agpl-3.0.en.html",
"name": "AGPL 3.0"
},
"section": "UI Components",
"description": "Personal Svelte component library providing shared UI primitives including navigation types and feed card components"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/utils",
"name": "@ewanc26/utils",
"type": "library",
"license": {
"url": "https://www.gnu.org/licenses/agpl-3.0.en.html",
"name": "AGPL 3.0"
},
"section": "Development",
"description": "Personal utility library providing slug normalisation, TID format detection, and other shared helpers"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/noise-avatar",
"name": "@ewanc26/noise-avatar",
"type": "library",
"license": {
"url": "https://www.gnu.org/licenses/agpl-3.0.en.html",
"name": "AGPL 3.0"
},
"section": "UI Components",
"description": "Personal library generating deterministic noise-based images used as media fallbacks across the site"
},
{
"url": "https://umami.is/",
"name": "Umami",
"type": "library",
"license": {
"url": "https://github.com/umami-software/umami/blob/master/LICENSE",
"name": "MIT License"
},
"section": "Analytics",
"description": "Self-hosted, GDPR-compliant, cookie-free web analytics with minimal data collection hosted at analytics.ewancroft.uk"
},
{
"url": "https://cspell.org/",
"name": "cspell",
"type": "tool",
"section": "Development Tools",
"description": "Spell checking tool for code and documentation with custom dictionary support"
},
{
"url": "https://code.visualstudio.com/",
"name": "VS Code",
"type": "tool",
"section": "Development Tools",
"description": "Code editor with workspace configuration and Svelte language support"
},
{
"url": "https://commons.wikimedia.org/wiki/File:Happy_Mac.svg",
"name": "Happy Mac SVG",
"type": "asset",
"author": "NiloGlock",
"license": {
"url": "https://creativecommons.org/licenses/by-sa/4.0/",
"name": "CC BY-SA 4.0"
},
"section": "UI Components",
"description": "Iconic 1984 Macintosh startup icon used for the website easter egg, celebrating the Mac's announcement on 24 January, 1984"
}
],
"additionalInfo": {
"purpose": "This is Ewan's personal website (ewancroft.uk) serving as a creative outlet, digital garden, and demonstration of AT Protocol's potential for personal publishing. The site showcases custom lexicons, distributed data fetching with intelligent fallbacks, and full user control over content and presentation. It includes blog posts via Standard.site, music scrobbling via teal.fm, code repositories via Tangled, and dynamic link aggregation via Linkat—all powered entirely by AT Protocol data stored in a personal data server.",
"features": [
{
"name": "Cascading Fallback System",
"description": "Intelligent multi-endpoint fallback ensuring reliability when services are temporarily unavailable, abstracted through the @ewanc26/atproto library"
},
{
"name": "Smart Caching",
"description": "In-memory cache with granular per-type TTLs (10 minutes for music status up to 24 hours for identity resolution in production) and environment-variable overrides, reducing external API calls whilst maintaining data freshness"
},
{
"name": "Multi-Publication Blog Support",
"description": "Unified interface for Standard.site publications with automatic draft filtering, friendly slug routing, and intelligent RSS and Atom feed generation across multiple publication rkeys"
},
{
"name": "Music Integration",
"description": "Real-time music scrobbling display via teal.fm with cascading artwork search (MusicBrainz → iTunes → Deezer → Last.fm → AT Protocol blobs)"
},
{
"name": "Kibun Status",
"description": "Real-time mood and status display fetched from a personal AT Protocol record, surfaced on the home page alongside music status"
},
{
"name": "Supporters",
"description": "Ko-fi supporter event display powered by AT Protocol records fetched via the @ewanc26/supporters library"
},
{
"name": "Repository Display",
"description": "Code repository integration via Tangled lexicon (sh.tangled.repo) with descriptions, labels, and automatic sorting by creation date"
},
{
"name": "Link Board",
"description": "Dynamic link aggregation using Linkat lexicon (blue.linkat.board) with emoji icons"
},
{
"name": "Rich Post Display",
"description": "Full Bluesky post rendering with images, videos, quoted posts, external link cards, threaded replies, and real-time engagement counts"
},
{
"name": "Archive",
"description": "Browsable archive of all posts across publications, accessible via the site navigation"
},
{
"name": "ActivityPub WebFinger Bridge",
"description": "Optional integration activated by PUBLIC_AP_INSTANCE_URL and PUBLIC_AP_USERNAME environment variables. Serves /.well-known/webfinger by proxying the canonical response from the configured ActivityPub instance and injecting the site domain as an alias, so the account is resolvable as @user@ewancroft.uk across the Fediverse without self-hosting a full AP server"
},
{
"name": "Wolf Mode",
"description": "Playful text transformation feature converting page content to wolf sounds whilst preserving navigation, numbers, and formatting—demonstrating creative UI experimentation"
},
{
"name": "Dark Mode",
"description": "System-aware theme switching with manual override, persisted via localStorage"
},
{
"name": "Server-Side Artwork API",
"description": "Custom /api/artwork endpoint solving CORS issues by proxying requests through the server, with intelligent caching and HTTP cache headers"
},
{
"name": "Publication Slug Mapping",
"description": "Friendly URL routing system mapping slugs (e.g., /blog, /creativity) to Standard.site publication rkeys with automatic base_path resolution"
},
{
"name": "Custom Lexicons",
"description": "Site metadata (uk.ewancroft.site.info) storing tech stack, privacy statement, credits, and related services as structured AT Protocol records"
},
{
"name": "Noise Image Fallbacks",
"description": "Deterministic noise-based images generated via @ewanc26/noise-avatar used as graceful fallbacks for all media surfaces when remote images are unavailable"
}
],
"analytics": {
"services": [
{
"url": "https://analytics.ewancroft.uk",
"name": "Umami",
"description": "Self-hosted web analytics collecting only basic pageview data (URL, referrer, browser, OS, country) without cookies or personally identifiable information",
"privacyFeatures": [
"No cookies",
"GDPR compliant",
"Self-hosted",
"No cross-site tracking",
"Anonymised IP addresses"
]
}
],
"cookiePolicy": "This website (ewancroft.uk) uses localStorage (not traditional cookies) solely to remember your theme preference and wolf mode state, enhancing your browsing experience. This storage is strictly necessary for the site to function as intended and does not track or profile you in any way. Web analytics are provided by Umami, a self-hosted, cookie-free, GDPR-compliant solution that collects only anonymised, aggregated data—no personal information, no cross-site tracking, and no data shared with third parties. You can view the analytics dashboard publicly at analytics.ewancroft.uk. Since the localStorage data is kept locally under your control and Umami uses no cookies, explicit consent is not required under UK GDPR. You can clear or disable this storage via your browser settings at any time."
},
"deployment": {
"features": [
"Serverless Functions",
"Edge Network",
"Automatic HTTPS",
"Git Integration"
],
"platform": "Vercel",
"customDomain": true
},
"sectionLicense": [
{
"url": "https://creativecommons.org/licenses/by/4.0/",
"name": "CC-BY 4.0",
"section": "blog"
}
],
"websiteBirthYear": 2023
},
"openSourceInfo": {
"license": {
"url": "https://www.gnu.org/licenses/agpl-3.0.en.html",
"name": "AGPL 3.0"
},
"description": "This website is designed for the AT Protocol ecosystem, demonstrating distributed data fetching, custom lexicon implementation, and user-owned publishing. The entire codebase is open source and available for inspection, modification, and learning. There is no hidden tracking or data collection—the transparent nature of the code allows anyone to verify this commitment to privacy. Contributions, forks, and adaptations are welcome under the AGPL 3.0 license.",
"repositories": [
{
"url": "https://github.com/ewanc26/website",
"type": "primary",
"platform": "GitHub",
"description": "Primary development repository with issue tracking and collaborative features"
},
{
"url": "https://tangled.org/did:plc:ofrbh253gwicbkc5nktqepol/website",
"type": "mirror",
"platform": "Tangled",
"description": "Decentralised mirror on AT Protocol infrastructure using sh.tangled.repo lexicon"
}
],
"relatedServices": [
{
"url": "https://atproto.com/",
"name": "AT Protocol",
"section": "Protocol",
"description": "Federated protocol for large-scale distributed social applications providing cryptographic identity (DIDs), content-addressing, and lexicon-based federation",
"relationship": "underlying protocol"
},
{
"url": "https://bsky.app/",
"name": "Bluesky",
"section": "Social Platform",
"description": "Social platform built on AT Protocol for content sharing, discovery, and the primary AppView for post indexing",
"relationship": "content distribution"
},
{
"url": "https://standard.site/",
"name": "Standard.site",
"section": "Publishing Platform",
"description": "AT Protocol powered publishing platform used as the primary blog backend, supporting multiple named publications mapped to friendly URL slugs",
"relationship": "primary blog backend"
},
{
"url": "https://teal.fm/",
"name": "Teal",
"section": "Music Scrobbling",
"description": "Decentralised music scrobbling service using fm.teal.alpha.actor.status and fm.teal.alpha.feed.play lexicons, distributed alternative to Last.fm",
"relationship": "music tracking backend"
},
{
"url": "https://tangled.org/",
"name": "Tangled",
"section": "Code Hosting",
"description": "Git development platform with AT Protocol as the social layer, using sh.tangled.repo lexicon for repository metadata",
"relationship": "code repository backend"
},
{
"url": "https://linkat.blue/",
"name": "Linkat",
"section": "Link Management",
"description": "Link aggregation service using blue.linkat.board lexicon for curated link collections with emoji icons",
"relationship": "link board backend"
},
{
"url": "https://constellation.microcosm.blue/",
"name": "Microcosm Constellation",
"section": "Indexing Service",
"description": "AT Protocol indexing service providing aggregated engagement data (likes, reposts) with paginated API for efficient count queries",
"relationship": "engagement data provider"
},
{
"url": "https://slingshot.microcosm.blue/",
"name": "Microcosm Slingshot",
"section": "Identity Resolution",
"description": "Identity resolution service for finding PDS endpoints from DIDs using com.bad-example.identity.resolveMiniDoc XRPC method",
"relationship": "identity resolver"
},
{
"url": "https://www.w3.org/TR/activitypub/",
"name": "ActivityPub",
"section": "Fediverse Integration",
"description": "W3C federated social protocol. Optionally bridged via the site's WebFinger endpoint, which proxies identity resolution from a configured AP instance and injects the site domain as an alias, enabling @ewan@ewancroft.uk to resolve on Fediverse servers. Activated by PUBLIC_AP_INSTANCE_URL and PUBLIC_AP_USERNAME environment variables.",
"relationship": "optional identity bridge"
},
{
"url": "https://musicbrainz.org/",
"name": "MusicBrainz",
"section": "Music Metadata",
"description": "Open music encyclopaedia providing release IDs and Cover Art Archive integration for album artwork—no API key required",
"relationship": "music metadata provider"
},
{
"url": "https://www.apple.com/itunes/",
"name": "iTunes Search API",
"section": "Music Metadata",
"description": "Apple's music search API providing album artwork as fallback source when MusicBrainz data is unavailable",
"relationship": "artwork fallback"
},
{
"url": "https://www.deezer.com/",
"name": "Deezer API",
"section": "Music Metadata",
"description": "Music streaming service API providing album artwork as additional fallback option (server-side only due to CORS)",
"relationship": "artwork fallback"
},
{
"url": "https://www.last.fm/",
"name": "Last.fm API",
"section": "Music Metadata",
"description": "Music scrobbling service API providing album information and artwork as final external fallback before AT Protocol blobs",
"relationship": "artwork fallback"
}
]
},
"technologyStack": [
{
"url": "https://svelte.dev/docs/svelte/overview",
"name": "Svelte 5",
"description": "Modern reactive framework with runes for building efficient web applications using fine-grained reactivity"
},
{
"url": "https://svelte.dev/docs/kit/introduction",
"name": "SvelteKit 2",
"description": "Full-stack web framework for building fast, efficient web applications with Svelte, featuring server-side rendering, API routes, and file-based routing"
},
{
"url": "https://tailwindcss.com/",
"name": "Tailwind CSS 4",
"description": "Next-generation utility-first CSS framework with native CSS support, improved performance, and enhanced developer experience"
},
{
"url": "https://tailwindcss.com/docs/typography-plugin",
"name": "@tailwindcss/typography",
"description": "Official Tailwind CSS plugin providing beautiful typographic defaults for prose content and blog posts"
},
{
"url": "https://vite.dev/",
"name": "Vite",
"description": "Fast build tool and development server with native ES modules, hot module replacement, and optimised production builds"
},
{
"url": "https://www.typescriptlang.org/",
"name": "TypeScript",
"description": "Typed superset of JavaScript providing static type checking for better development experience, code quality, and refactoring confidence"
},
{
"url": "https://atproto.com/",
"name": "AT Protocol",
"description": "Federated protocol for large-scale distributed social applications, providing cryptographic identity (DIDs), content-addressing via CIDs, lexicon-based federation, and personal data server infrastructure"
},
{
"url": "https://www.npmjs.com/package/@atproto/api",
"name": "@atproto/api",
"description": "Official TypeScript client library for AT Protocol providing type-safe access to XRPC methods, record operations, and PDS interactions"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/atproto",
"name": "@ewanc26/atproto",
"description": "Personal AT Protocol abstraction library centralising all data-fetching, engagement, media, and artwork logic used by the website"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/supporters",
"name": "@ewanc26/supporters",
"description": "Personal library for fetching and typing Ko-fi supporter events stored as AT Protocol records"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/tid",
"name": "@ewanc26/tid",
"description": "Personal utility library for parsing and working with AT Protocol TID (timestamp-based identifier) formats"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/ui",
"name": "@ewanc26/ui",
"description": "Personal Svelte component library providing shared UI primitives, navigation types, and feed card components used across the site"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/utils",
"name": "@ewanc26/utils",
"description": "Personal utility library providing slug normalisation, TID format detection, and other shared helpers consumed by routing and config logic"
},
{
"url": "https://www.npmjs.com/package/@ewanc26/noise-avatar",
"name": "@ewanc26/noise-avatar",
"description": "Personal library for generating deterministic noise-based images used as graceful media fallbacks across all content surfaces"
},
{
"url": "https://nodejs.org/",
"name": "Node.js",
"description": "JavaScript runtime for server-side development powering SvelteKit's server-side rendering and API endpoints"
},
{
"url": "https://prettier.io/",
"name": "Prettier",
"description": "Opinionated code formatting tool ensuring consistent style across the entire codebase with automatic formatting"
},
{
"url": "https://www.npmjs.com/package/prettier-plugin-svelte",
"name": "prettier-plugin-svelte",
"description": "Prettier plugin for formatting Svelte components with proper syntax handling and script/style block formatting"
},
{
"url": "https://www.npmjs.com/package/prettier-plugin-tailwindcss",
"name": "prettier-plugin-tailwindcss",
"description": "Prettier plugin for automatically sorting Tailwind CSS classes according to recommended order for consistency"
},
{
"url": "https://lucide.dev/",
"name": "Lucide Icons (Svelte)",
"description": "Beautiful and consistent icon library for Svelte applications providing customisable SVG icons with tree-shaking support"
},
{
"url": "https://github.com/video-dev/hls.js",
"name": "hls.js",
"description": "JavaScript library implementing HTTP Live Streaming protocol for video playback in browsers without native HLS support"
},
{
"url": "https://umami.is/",
"name": "Umami",
"description": "Self-hosted, open-source web analytics solution providing GDPR-compliant, cookie-free tracking with anonymised data collection"
},
{
"url": "https://webfinger.net/",
"name": "WebFinger",
"description": "Resource discovery protocol (RFC 7033) served at /.well-known/webfinger. When ActivityPub is configured, the endpoint proxies the upstream AP instance response and injects a site-domain alias, bridging Fediverse identity resolution to the custom domain."
}
],
"privacyStatement": "This website (ewancroft.uk) respects your privacy and operates with complete transparency. Storage: Only localStorage is used to enhance your experience by remembering theme preferences and wolf mode state—this data never leaves your device and is not accessible to me or any third parties. Analytics: Web analytics are provided by Umami, a self-hosted, cookie-free solution that collects only anonymised, aggregated data—page URLs, referrers, browser type, and country. No personally identifiable information is collected, no cross-site tracking occurs, and no data is shared with third parties. The analytics dashboard is publicly viewable at analytics.ewancroft.uk. Third-party content: Embedded content (videos, music widgets, external links) may load resources from their respective services, potentially setting cookies outside my control. Data collection: Minimal and anonymised—just enough to understand which pages are popular. No tracking pixels, no fingerprinting, no data mining, no telemetry beyond basic pageviews. Everything else is client-side or fetched from your own AT Protocol data. Verification: The entire website source code is open and available for inspection at github.com/ewanc26/website. You can verify exactly what data is collected and how it's processed. Control: You can clear localStorage via browser settings at any time, disable JavaScript entirely (though some features won't work), use privacy-focused browsers and extensions, or opt out of analytics via browser Do Not Track settings (which Umami respects). AT Protocol data: All blog posts, profile information, and other content come from AT Protocol records in personal data servers—data you own and control, not data I collect from you."
}
did:plc:ofrbh253gwicbkc5nktqepol | at://did:plc:ofrbh253gwicbkc5nktqepol/uk.ewancroft.site.info/self