A calm place to write long-form, and publish it to the open social web. skypress.blog/
0

Configure Feed

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

Add atmosphere-url helper for mu.social view-links

+63
+31
src/lib/social/atmosphere-url.test.ts
··· 1 + import { describe, expect, it } from 'vitest'; 2 + import { 3 + ATMOSPHERE_WEB_BASE, 4 + atmosphereProfileUrl, 5 + atmosphereHashtagUrl, 6 + atmospherePostWebUrl, 7 + } from './atmosphere-url'; 8 + 9 + describe( 'atmosphere-url', () => { 10 + it( 'builds a profile URL from a handle', () => { 11 + expect( atmosphereProfileUrl( 'alice.bsky.social' ) ).toBe( 12 + 'https://mu.social/profile/alice.bsky.social' 13 + ); 14 + } ); 15 + 16 + it( 'builds a hashtag URL from a bare tag', () => { 17 + expect( atmosphereHashtagUrl( 'design' ) ).toBe( 18 + 'https://mu.social/hashtag/design' 19 + ); 20 + } ); 21 + 22 + it( 'maps an at:// post uri to its profile/post URL', () => { 23 + expect( 24 + atmospherePostWebUrl( 'at://did:plc:writer/app.bsky.feed.post/3kpost' ) 25 + ).toBe( 'https://mu.social/profile/did:plc:writer/post/3kpost' ); 26 + } ); 27 + 28 + it( 'falls back to the AppView home for an unparseable uri', () => { 29 + expect( atmospherePostWebUrl( 'not-an-at-uri' ) ).toBe( ATMOSPHERE_WEB_BASE ); 30 + } ); 31 + } );
+32
src/lib/social/atmosphere-url.ts
··· 1 + /** 2 + * Web URLs for *viewing* AT Protocol records in an AppView client. 3 + * 4 + * SkyPress publishes to the Bluesky/atproto network, but links readers to mu.social 5 + * (a Bluesky AppView) to view profiles, posts, and hashtags. mu.social uses the same 6 + * path scheme as bsky.app. Keeping the host here means changing it again is a one-line 7 + * edit. This module is dependency-free so the reader path can import it (Decision 0003). 8 + */ 9 + export const ATMOSPHERE_WEB_BASE = 'https://mu.social'; 10 + 11 + /** Profile page for a handle (e.g. `alice.bsky.social`). */ 12 + export function atmosphereProfileUrl( handle: string ): string { 13 + return `${ ATMOSPHERE_WEB_BASE }/profile/${ encodeURIComponent( handle ) }`; 14 + } 15 + 16 + /** Hashtag page for a bare tag (no leading `#`). */ 17 + export function atmosphereHashtagUrl( tag: string ): string { 18 + return `${ ATMOSPHERE_WEB_BASE }/hashtag/${ encodeURIComponent( tag ) }`; 19 + } 20 + 21 + /** 22 + * Web URL for a post AT-URI, for "view on the ATmosphere" links. 23 + * `at://<did>/app.bsky.feed.post/<rkey>` → `<base>/profile/<did>/post/<rkey>`. 24 + * The DID is kept raw (not encoded) so the path matches the AppView's canonical form. 25 + * Falls back to the AppView home for an unparseable URI. 26 + */ 27 + export function atmospherePostWebUrl( postUri: string ): string { 28 + const match = postUri.match( /^at:\/\/([^/]+)\/app\.bsky\.feed\.post\/(.+)$/ ); 29 + return match 30 + ? `${ ATMOSPHERE_WEB_BASE }/profile/${ match[ 1 ] }/post/${ match[ 2 ] }` 31 + : ATMOSPHERE_WEB_BASE; 32 + }