this repo has no description
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add developer resources page with Lottie downloads

Move the For developers section from the home page to /developer-resources,
link it from the footer as Developer resources (not in the nav), and add
downloads for the hero Lottie JSON and a ZIP of embedded animation images.

Include extract-lottie-assets script and deno task to regenerate assets when
atmosphere.json changes. Refine What is the Atmosphere copy (open social web,
big-tech framing).

Made-with: Cursor

+156 -42
+69
components/DeveloperResources.tsx
··· 1 + export default function DeveloperResources() { 2 + return ( 3 + <> 4 + <section class="section-sm reveal"> 5 + <div class="container-narrow text-center"> 6 + <h1 class="text-section">For developers.</h1> 7 + <div class="divider" /> 8 + <p class="text-body mt-2 mb-4"> 9 + Building an Atmosphere app? Let your users know they can sign in with 10 + their Atmosphere account. 11 + </p> 12 + <div class="badge-display"> 13 + <img 14 + src="/sign-in-box.svg" 15 + alt="Sign in with your Atmosphere Account" 16 + /> 17 + </div> 18 + <div class="badge-downloads"> 19 + <a 20 + href="/sign-in-box.svg" 21 + download="atmosphere-sign-in-badge.svg" 22 + class="badge-download-btn font-mono" 23 + > 24 + Download badge (SVG) 25 + </a> 26 + <a 27 + href="/union.svg" 28 + download="atmosphere-logo.svg" 29 + class="badge-download-btn font-mono" 30 + > 31 + Download logo (SVG) 32 + </a> 33 + </div> 34 + <p class="text-body-sm mt-3"> 35 + Add this badge to your sign-in page to help users understand the 36 + Atmosphere. 37 + </p> 38 + </div> 39 + </section> 40 + 41 + <section class="section-sm reveal"> 42 + <div class="container-narrow text-center"> 43 + <h2 class="text-subsection">Homepage hero animation</h2> 44 + <div class="divider" /> 45 + <p class="text-body mt-2 mb-3"> 46 + The Lottie animation and the image assets embedded inside it (logos 47 + and artwork used in the sequence). 48 + </p> 49 + <div class="badge-downloads"> 50 + <a 51 + href="/atmosphere.json" 52 + download="atmosphere-hero.lottie.json" 53 + class="badge-download-btn font-mono" 54 + > 55 + Download Lottie (JSON) 56 + </a> 57 + <a 58 + href="/lottie-icons.zip" 59 + download="atmosphere-lottie-icons.zip" 60 + class="badge-download-btn font-mono" 61 + > 62 + Download icons (ZIP) 63 + </a> 64 + </div> 65 + </div> 66 + </section> 67 + </> 68 + ); 69 + }
+1
components/Footer.tsx
··· 29 29 <span class="footer-coming-soon" title="Coming soon"> 30 30 Explore Apps 31 31 </span> 32 + <a href="/developer-resources">Developer resources</a> 32 33 </div> 33 34 <p class="footer-quote"> 34 35 "You never change things by fighting the existing reality. To change
-36
components/SignInBadge.tsx
··· 1 - export default function SignInBadge() { 2 - return ( 3 - <section class="section-sm reveal"> 4 - <div class="container-narrow text-center"> 5 - <h2 class="text-section">For developers.</h2> 6 - <div class="divider" /> 7 - <p class="text-body mt-2 mb-4"> 8 - Building an Atmosphere app? Let your users know they can sign in with 9 - their Atmosphere account. 10 - </p> 11 - <div class="badge-display"> 12 - <img src="/sign-in-box.svg" alt="Sign in with your Atmosphere Account" /> 13 - </div> 14 - <div class="badge-downloads"> 15 - <a 16 - href="/sign-in-box.svg" 17 - download="atmosphere-sign-in-badge.svg" 18 - class="badge-download-btn font-mono" 19 - > 20 - Download badge (SVG) 21 - </a> 22 - <a 23 - href="/union.svg" 24 - download="atmosphere-logo.svg" 25 - class="badge-download-btn font-mono" 26 - > 27 - Download logo (SVG) 28 - </a> 29 - </div> 30 - <p class="text-body-sm mt-3"> 31 - Add this badge to your sign-in page to help users understand the Atmosphere. 32 - </p> 33 - </div> 34 - </section> 35 - ); 36 - }
+8 -4
components/WhatIsAtmosphere.tsx
··· 10 10 > 11 11 <p class="text-body"> 12 12 The Atmosphere is a new open network of apps and services that all 13 - work together. Think of it like an{" "} 14 - <strong>open social web</strong>. Instead of every app being its own 15 - walled garden, Atmosphere apps share a common foundation — so you 16 - only need <strong>one account</strong> to use them all. 13 + work together. Instead of every app being its own walled garden, 14 + Atmosphere apps share a common foundation — so you only need{" "} 15 + <strong>one account</strong> to use them all. 17 16 </p> 18 17 <p class="text-body mt-3"> 19 18 Your <strong>Atmosphere Account</strong>{" "} 20 19 is your passport to this entire ecosystem. One account unlocks every 21 20 app — no more creating new logins, no more losing your stuff when 22 21 you switch. Sign in once, and you're home everywhere. 22 + </p> 23 + <p class="text-body mt-3"> 24 + The Atmosphere isn&apos;t owned or controlled by any single big-tech 25 + company. This isn&apos;t just another &quot;Sign in with Google&quot;, 26 + it&apos;s an <strong>open social web</strong>. 23 27 </p> 24 28 </div> 25 29 <p
+1
deno.json
··· 5 5 "dev": "vite", 6 6 "build": "vite build", 7 7 "gen:images": "deno run -A --node-modules-dir=auto scripts/generate-static-images.ts", 8 + "extract:lottie-assets": "deno run -A scripts/extract-lottie-assets.ts", 8 9 "start": "deno serve -A _fresh/server.js", 9 10 "update": "deno run -A -r jsr:@fresh/update ." 10 11 },
+20
routes/developer-resources.tsx
··· 1 + import { define } from "../utils.ts"; 2 + import Nav from "../components/Nav.tsx"; 3 + import GlassClouds from "../components/GlassClouds.tsx"; 4 + import DeveloperResources from "../components/DeveloperResources.tsx"; 5 + import Footer from "../components/Footer.tsx"; 6 + 7 + export default define.page(function DeveloperResourcesPage() { 8 + return ( 9 + <div id="page-top"> 10 + <GlassClouds /> 11 + <div class="content-layer"> 12 + <Nav /> 13 + <section style={{ paddingTop: "8rem" }}> 14 + <DeveloperResources /> 15 + </section> 16 + <Footer /> 17 + </div> 18 + </div> 19 + ); 20 + });
-2
routes/index.tsx
··· 8 8 import BlueskySection from "../components/BlueskySection.tsx"; 9 9 import CrossPollination from "../components/CrossPollination.tsx"; 10 10 import YourChoice from "../components/ModerationAndAlgorithms.tsx"; 11 - import SignInBadge from "../components/SignInBadge.tsx"; 12 11 import Footer from "../components/Footer.tsx"; 13 12 14 13 export default define.page(function Home() { ··· 24 23 <BlueskySection /> 25 24 <CrossPollination /> 26 25 <YourChoice /> 27 - <SignInBadge /> 28 26 <Footer /> 29 27 </div> 30 28 </div>
+57
scripts/extract-lottie-assets.ts
··· 1 + /** 2 + * Extracts embedded data-uri images from static/atmosphere.json into 3 + * static/lottie-assets/, then builds static/lottie-icons.zip for the 4 + * developer resources page. Re-run when the Lottie source changes. 5 + * Requires the `zip` CLI (macOS/Linux). 6 + */ 7 + import { fromFileUrl } from "jsr:@std/path@^1.1.4/from-file-url"; 8 + 9 + const jsonPath = new URL("../static/atmosphere.json", import.meta.url); 10 + const outDir = new URL("../static/lottie-assets/", import.meta.url); 11 + const zipPath = new URL("../static/lottie-icons.zip", import.meta.url); 12 + 13 + const text = await Deno.readTextFile(jsonPath); 14 + const data = JSON.parse(text) as { 15 + assets?: Array<{ id?: string; p?: string }>; 16 + }; 17 + 18 + await Deno.mkdir(outDir, { recursive: true }); 19 + 20 + const filenames: string[] = []; 21 + 22 + for (const asset of data.assets ?? []) { 23 + const p = asset.p; 24 + if (typeof p !== "string" || !p.startsWith("data:image/")) continue; 25 + const m = p.match(/^data:image\/(\w+);base64,(.+)$/); 26 + if (!m) continue; 27 + let ext = m[1]; 28 + if (ext === "jpeg") ext = "jpg"; 29 + const id = asset.id ?? "asset"; 30 + const filename = `${id}.${ext}`; 31 + const buf = Uint8Array.from(atob(m[2]), (c) => c.charCodeAt(0)); 32 + await Deno.writeFile(new URL(filename, outDir), buf); 33 + filenames.push(filename); 34 + } 35 + 36 + try { 37 + await Deno.remove(zipPath); 38 + } catch { 39 + /* ignore if missing */ 40 + } 41 + 42 + if (filenames.length > 0) { 43 + const zipFile = fromFileUrl(zipPath); 44 + const inputPaths = filenames.map((name) => fromFileUrl(new URL(name, outDir))); 45 + const { code, stderr } = await new Deno.Command("zip", { 46 + args: ["-j", "-q", zipFile, ...inputPaths], 47 + }).output(); 48 + if (code !== 0) { 49 + throw new Error( 50 + `zip failed (${code}): ${new TextDecoder().decode(stderr)}`, 51 + ); 52 + } 53 + } 54 + 55 + console.log( 56 + `Wrote ${filenames.length} files to static/lottie-assets/ and static/lottie-icons.zip`, 57 + );
static/lottie-assets/image_0.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_1.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_10.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_11.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_12.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_13.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_14.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_15.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_16.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_17.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_18.png

This is a binary file and will not be displayed.

static/lottie-assets/image_19.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_2.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_20.png

This is a binary file and will not be displayed.

static/lottie-assets/image_21.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_3.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_4.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_5.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_6.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_7.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_8.jpg

This is a binary file and will not be displayed.

static/lottie-assets/image_9.jpg

This is a binary file and will not be displayed.

static/lottie-icons.zip

This is a binary file and will not be displayed.