the statusphere demo reworked into a vite/react app in a monorepo

Compare changes

Choose any two refs to compare.

Changed files
+43 -8
.tangled
workflows
packages
appview
client
src
components
+27
.tangled/workflows/deploy.yml
··· 1 + # Set the following secrets in your repo's pipeline settings: 2 + # RAILWAY_TOKEN 3 + # RAILWAY_SERVICE_ID 4 + 5 + when: 6 + - event: ["push"] 7 + branch: ["main"] 8 + 9 + engine: "nixery" 10 + 11 + dependencies: 12 + nixpkgs: 13 + - rustup 14 + - gcc 15 + 16 + steps: 17 + - name: Install Rust toolchain 18 + command: rustup default stable 19 + 20 + - name: Install Railway CLI 21 + command: cargo install railwayapp --locked 22 + 23 + - name: Link `railway` executable 24 + command: ln -s /tangled/home/.cargo/bin/railway /bin/railway 25 + 26 + - name: Deploy to Railway 27 + command: railway up --ci --service=$RAILWAY_SERVICE_ID
+1 -1
packages/appview/README.md
··· 55 55 56 56 ## API Endpoints 57 57 58 - - `GET /client-metadata.json` - OAuth client metadata 58 + - `GET /oauth-client-metadata.json` - OAuth client metadata 59 59 - `GET /oauth/callback` - OAuth callback endpoint 60 60 - `POST /login` - Login with handle 61 61 - `POST /logout` - Logout current user
+1 -1
packages/appview/src/api/oauth.ts
··· 9 9 const router = express.Router() 10 10 11 11 // OAuth metadata 12 - router.get('/client-metadata.json', (_req, res) => { 12 + router.get('/oauth-client-metadata.json', (_req, res) => { 13 13 res.json(ctx.oauthClient.clientMetadata) 14 14 }) 15 15
+1 -1
packages/appview/src/auth/client.ts
··· 17 17 clientMetadata: { 18 18 client_name: 'Statusphere React App', 19 19 client_id: publicUrl 20 - ? `${url}/client-metadata.json` 20 + ? `${url}/oauth-client-metadata.json` 21 21 : `http://localhost?redirect_uri=${enc(`${url}/oauth/callback`)}&scope=${enc('atproto transition:generic')}`, 22 22 client_uri: url, 23 23 redirect_uris: [`${url}/oauth/callback`],
+1 -1
packages/appview/src/lib/env.ts
··· 15 15 COOKIE_SECRET: str({ devDefault: '0'.repeat(32) }), 16 16 SERVICE_DID: str({ default: undefined }), 17 17 PUBLIC_URL: str({ devDefault: '' }), 18 - JETSTREAM_INSTANCE: str({ default: 'wss://jetstream.mozzius.dev' }), 18 + JETSTREAM_INSTANCE: str({ default: 'wss://jetstream2.us-east.bsky.network' }), 19 19 })
+4 -1
packages/appview/src/lib/hydrate.ts
··· 7 7 import { AppContext } from '#/context' 8 8 import { Status } from '#/db' 9 9 10 + const INVALID_HANDLE = 'handle.invalid' 11 + 10 12 export async function statusToStatusView( 11 13 status: Status, 12 14 ctx: AppContext, ··· 19 21 did: status.authorDid, 20 22 handle: await ctx.resolver 21 23 .resolveDidToHandle(status.authorDid) 22 - .catch(() => 'invalid.handle'), 24 + .then((handle) => (handle.startsWith('did:') ? INVALID_HANDLE : handle)) 25 + .catch(() => INVALID_HANDLE), 23 26 }, 24 27 } 25 28 }
+7 -2
packages/client/index.html
··· 1 - <!DOCTYPE html> 1 + <!doctype html> 2 2 <html lang="en"> 3 3 <head> 4 4 <meta charset="UTF-8" /> 5 5 <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> 6 6 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 7 <title>Statusphere React</title> 8 + <script 9 + defer 10 + data-domain="statusphere.mozzius.dev" 11 + src="https://plausible.mozzius.dev/js/script.js" 12 + ></script> 8 13 </head> 9 14 <body> 10 15 <div id="root"></div> 11 16 <script type="module" src="/src/main.tsx"></script> 12 17 </body> 13 - </html> 18 + </html>
+1 -1
packages/client/src/components/Header.tsx
··· 31 31 <img 32 32 src={user.profile.avatar} 33 33 alt={user.profile.displayName || user.profile.handle} 34 - className="w-8 h-8 rounded-full" 34 + className="w-8 h-8 rounded-full text-transparent" 35 35 /> 36 36 ) : ( 37 37 <div className="w-8 h-8 bg-gray-200 dark:bg-gray-700 rounded-full"></div>