pds dash for shimaenaga.veryroundbird.house (based off of pds.witchcraft.systems)

Compare changes

Choose any two refs to compare.

+61
.tangled/workflows/build.yml
···
+
when:
+
- event: ["push", "manual"]
+
branch: ["main"]
+
+
engine: "nixery"
+
+
dependencies:
+
nixpkgs:
+
- deno
+
- openssh
+
- su
+
+
steps:
+
- name: "Pretend we have a real local user"
+
command: |
+
echo "🪶 pretend root is a real user"
+
echo "root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash" >> /etc/passwd
+
+
- name: "Copy config to server"
+
command: |
+
echo "🪶 copying config from secrets"
+
echo "${CONFIG}" > config.ts
+
+
- name: "Set up Deno"
+
command: |
+
echo "🪶 installing deno packages"
+
deno install
+
+
- name: "Build static files"
+
command: |
+
echo "🪶 building static files"
+
deno run build
+
+
- name: "SSH setup"
+
command: |
+
echo "🪶 setting up ssh connection"
+
mkdir ~/.ssh
+
echo "${SSH_KEY}" > ~/.ssh/id_tangledsh
+
chmod 600 ~/.ssh/id_tangledsh
+
cat > /etc/ssh/ssh_config << EOF
+
Host deploy
+
HostName ${SERVER_HOST}
+
User ${SERVER_USER}
+
IdentityFile ~/.ssh/id_tangledsh
+
StrictHostKeyChecking no
+
UserKnownHostsFile /dev/null
+
BatchMode yes
+
PasswordAuthentication no
+
PubkeyAuthentication yes
+
EOF
+
chmod 600 /etc/ssh/ssh_config
+
ssh-keyscan -H $SERVER_HOST >> ~/.ssh/known_hosts
+
+
- name: "Deploy via SCP"
+
command: |
+
echo "🪶 deploying files via scp"
+
scp -r ./dist/* deploy:/pds/caddy/etc/caddy/static
+
+
- name: "Done!"
+
command: |
+
echo "🪶 all done!
-32
.tangled/workflows/pipeline.yml
···
-
when:
-
- event: ["push", "manual"]
-
branch: ["main"]
-
engine: "nixery"
-
dependencies:
-
nixpkgs:
-
- deno
-
steps:
-
- name: "Build static files"
-
command: "deno run build"
-
- name: "SSH setup"
-
command: |
-
mkdir ~/.ssh
-
echo "${{secrets.SSH_KEY}}" > ~/.ssh/id_tangledsh
-
chmod 600 ~/.ssh/id_tangledsh
-
cat > ~/.ssh/config << EOF
-
Host deploy
-
HostName ${{ secrets.SERVER_HOST }}
-
User ${{ secrets.SERVER_USER }}
-
IdentityFile ~/.ssh/id_tangledsh
-
StrictHostKeyChecking accept-new
-
BatchMode yes
-
PasswordAuthentication no
-
PubkeyAuthentication yes
-
EOF
-
chmod 600 ~/.ssh/config
-
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
-
echo "🪶 deploying to shimaenaga pds"
-
- name: "Deploy via SCP"
-
run: scp -r ./dist/* deploy:/pds/caddy/webroot
-
- name: "Done!"
-
command: "echo \"🪶 all done!\""
+3 -1
README.md
···
* Replaced favicon
* Ported in guestbook functionality from another PDS frontpage (see new config options)
* Secret unique easter egg :)
-
* Wrote deploy pipeline for tangled.sh
+
* Wrote deploy pipeline for tangled.sh (WORK IN PROGRESS help try #5 - changing ssh perms?)
+
+
you can see it running at [my pds!](https://shimaenaga.veryroundbird.house)
# original readme below this line
public/fonts/spacemono-bold-webfont.woff2

This is a binary file and will not be displayed.

public/fonts/spacemono-bolditalic-webfont.woff2

This is a binary file and will not be displayed.

public/fonts/spacemono-italic-webfont.woff2

This is a binary file and will not be displayed.

public/fonts/spacemono-regular-webfont.woff2

This is a binary file and will not be displayed.

+71 -2
src/App.svelte
···
<script lang="ts">
import PostComponent from "./lib/PostComponent.svelte";
+
import GuestbookPostComponent from "./lib/GuestbookPostComponent.svelte";
import AccountComponent from "./lib/AccountComponent.svelte";
import InfiniteLoading from "svelte-infinite-loading";
import { getNextPosts, Post, getAllMetadataFromPds, fetchGuestbookPosts } from "./lib/pdsfetch";
···
<main>
<div id="content">
{#await accountsPromise}
-
<p>Loading...</p>
+
<div id="loadingbirds">
+
<div class="small">
+
<pre>
+
█▓░░░░░░░░░▒
+
█▓▒ ░▒
+
▓▒▒▒░ ▒
+
▓▒░░░░ ░▓
+
█▒ ░░ ░ ░ ▓▒ ░█
+
▓░ ░░ ▒▓░░▒▒░ ▒
+
███████ ██▓▒░▒▒░ ░░░░ ░░░ ▒
+
█▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▒▒▓▒▒▒▓░ ▓
+
███▓▒░░▒░░░░▓▓█▓▓▒░ ░
+
▓ ░
+
█ ░ ▒
+
█░ ▒█
+
▒ ▒
+
█▒ █
+
▓ ░█
+
▓▒ ░░ ░▒
+
▓▒▒░░▒▓░ ░░░▒▒▓▓▒▓▓
+
█▓█▓▓█ ███▓█
+
████ ████
+
</pre>
+
</div>
+
<div class="large">
+
<pre>
+
████▓▒░░░░░░░▒▓██
+
█▓░ ▒█
+
██▓░ ▒█
+
██▒ ▒█
+
███▓▒░ ▓█
+
█▓░ ░ █
+
██░ ░ ░█
+
█░ ▓
+
█▒ ▓
+
██▒ ▒▓▓ █
+
█▒ ▓█ ░▒ ▒▓ ▓█
+
██▒ ▒▓░ ░▒░░ ▓█
+
███▒░ ░▒▒▒▒▒░ ▓█
+
█████ ██▓░ ░░░░ █
+
█▓▒░░░░░░▒▒▒▓▓██████████▓▓▒░ ░▒▒▒▒▒▒▓▒▒░ ░▒▒░ ░█
+
██████▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒▒▒▒▓▒▒▓▓▓▓▒▒▒▒▒▒▓▒░░░▒▒▒░ ▒█
+
███▓▓▒▒░░░░ ░░░▒▓▓▓▒▒▓▓▓▓▓▒░░▒▒▒▒░ █
+
███▓▓▒ ▒▓▓▓▓▓▓▓█▓▒░░ █
+
█▓ ░▒▒▓▒░ ▓
+
█▓ ▓
+
█ █
+
█ ░█
+
█ ▓█
+
█░ ▒█
+
▒ ▓█
+
▓ █
+
█▒ ▒█
+
█▒ ▒█
+
█▓ ▒█
+
██ ██
+
█▒ ▓█
+
██░ ▒█
+
█░ ░▓█
+
█▓░ ▓▓▓░ ░▓▓▒ ░██
+
███▓▒░ ▒▓▓▓ ▒▓▓▓▓▓▓▓████▓▓▓▓▒█
+
█▓██▓▓▓▓██ ████▓▓▓██
+
██▓▓██ ██▓▓██
+
███▓██ █▓▓▓██
+
██████ ███████
+
</pre>
+
</div>
+
<p id="loadingText" data-text="pds is landing..." title="pds is landing...">pds is landing...</p>
+
</div>
{:then accountsData}
<div id="account">
<pre id="asciiart">
···
<div id="guestbookPosts">
{#if guestbookPosts.length > 0}
{#each guestbookPosts as postObject}
-
<PostComponent post={postObject as Post} />
+
<GuestbookPostComponent post={postObject.post} />
{/each}
{:else}
<p class="noGuestbookPosts">No guestbook posts yet!</p>
+1 -1
src/lib/AccountComponent.svelte
···
/>
{/if}
</div>
-
<div class="accountTooltip" popover id="{account.handle.replace('.')}">
+
<div class="accountTooltip" popover id="{account.handle.replace('.', '')}">
<div class="banner">
<img class="bannerImg" src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={account.did}&cid={account.bannerCid}" alt="{account.displayName}'s banner" width="300" height="100" />
<img class="avatarInsetImg" src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={account.did}&cid={account.avatarCid}" alt="{account.displayName}'s avatar" width="50" height="50" />
+92
src/lib/GuestbookPostComponent.svelte
···
+
<script lang="ts">
+
import { Post } from "./pdsfetch";
+
import { Config } from "../../config";
+
import { onMount } from "svelte";
+
import moment from "moment";
+
+
let { post }: { post: Post } = $props();
+
console.log(post);
+
</script>
+
+
<div class="postContainer">
+
<div class="postHeader">
+
{#if post.author.avatar}
+
<img
+
class="avatar"
+
src="{post.author.avatar}"
+
alt="avatar of {post.author.displayName}"
+
/>
+
{/if}
+
<div class="headerText">
+
<a class="displayName" href="{Config.FRONTEND_URL}/profile/{post.author.did}">{post.author.displayName}</a>
+
<p class="handle">
+
<a href="{Config.FRONTEND_URL}/profile/{post.author.handle}"
+
>@{post.author.handle}</a
+
>
+
<a
+
class="postLink" href="{Config.FRONTEND_URL}/profile/{post.author.did}/post/{post.record.id}"
+
>{moment(post.record.createdAt).isBefore(moment().subtract(1, "month"))
+
? moment(post.record.createdAt).format("MMM D, YYYY")
+
: moment(post.record.createdAt).fromNow()}</a>
+
</p>
+
</div>
+
</div>
+
<div class="postContent">
+
{#if post.record.quote}
+
<a
+
class="quotingText"
+
href="{Config.FRONTEND_URL}/profile/{post.record.quote.uri}/post/{post
+
.quotingUri.rkey}">quoting {post.quotingUri.repo}</a
+
>
+
{/if}
+
<div class="postText">{post.record.text}</div>
+
{#if post.record.imagesCid && post.record.imagesCid.length > 0}
+
<div id="carouselContainer">
+
<img
+
class="embedImages"
+
alt="Post Image {currentImageIndex + 1} of {post.record.imagesCid.length}"
+
src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.record.author.did}&cid={post.record
+
.imagesCid[currentImageIndex]}"
+
/>
+
+
{#if post.imagesCid.length > 1}
+
<div class="carouselControls">
+
<button
+
id="prevBtn"
+
onclick={prevImage}
+
disabled={currentImageIndex === 0}>←</button
+
>
+
<div class="carouselIndicators">
+
{#each post.record.imagesCid as _, i}
+
<div
+
class="indicator {i === currentImageIndex ? 'active' : ''}"
+
></div>
+
{/each}
+
</div>
+
<button
+
class="nextBtn"
+
onclick={nextImage}
+
disabled={currentImageIndex === post.imagesCid.length - 1}
+
>→</button
+
>
+
</div>
+
{/if}
+
</div>
+
{/if}
+
{#if post.record.videosLinkCid}
+
<!-- svelte-ignore a11y_media_has_caption -->
+
<video
+
class="embedVideo"
+
src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post.videosLinkCid}"
+
controls
+
></video>
+
{/if}
+
{#if post.gifLink}
+
<img
+
class="embedVideo"
+
src="{post.record.gifLink}"
+
alt="Post GIF"
+
/>
+
{/if}
+
</div>
+
</div>
+72 -4
themes/birdrights/theme.css
···
@font-face {
font-family: "Recursive Variable";
font-weight: 100 700;
-
font-style: -5deg 5deg;
src: url(/fonts/Recursive_VF_1.085.woff2) format('woff2');
}
+
@font-face {
+
font-family: "Space Mono";
+
font-weight: normal;
+
font-style: normal;
+
src: url(/fonts/spacemono-regular-webfont.woff2) format('woff2');
+
}
+
+
@font-face {
+
font-family: "Space Mono";
+
font-weight: bold;
+
font-style: normal;
+
src: url(/fonts/spacemono-bold-webfont.woff2) format('woff2');
+
}
+
+
@font-face {
+
font-family: "Space Mono";
+
font-weight: normal;
+
font-style: italic;
+
src: url(/fonts/spacemono-italic-webfont.woff2) format('woff2');
+
}
+
+
@font-face {
+
font-family: "Space Mono";
+
font-weight: bold;
+
font-style: italic;
+
src: url(/fonts/spacemono-bolditalic-webfont.woff2) format('woff2');
+
}
+
:root {
/* Color overrides, edit to whatever you want */
--primary-h: 260; /* Hue */
···
min-width: 320px;
min-height: 100vh;
background-color: var(--background-color);
-
font-family: "Recursive Variable";
+
font-family: "Recursive Variable", monospace;
font-size: var(--base-font-size);
color: var(--text-color);
border-color: var(--border-color);
···
}
h1 {
+
font-family: "Space Mono", monospace;
font-size: 2em;
line-height: 1.1;
margin-bottom: 0;
···
background-color: transparent;
padding: 0;
position: relative;
+
cursor: pointer;
}
.accountContainer {
···
white-space: nowrap;
}
-
.accountTooltip {
+
.accountTooltip[popover] {
border: 1px var(--border-color) solid;
color: var(--text-color);
background-color: var(--content-background-color);
···
padding: 10px;
gap: 10px;
z-index: 10;
+
grid-template-rows: auto 1fr;
}
#guestbookContents:popover-open {
···
/* Source Link */
#footer {
-
position: absolute;
+
position: fixed;
bottom: 5px;
right: 5px;
z-index: 99;
···
#footer:hover {
opacity: 1;
+
}
+
+
#loadingbirds {
+
line-height: 1;
+
text-align: center;
+
width: 100%;
+
}
+
+
#loadingbirds pre {
+
display: inline-block;
+
margin: 0 auto;
+
text-align: left;
+
}
+
+
#loadingbirds .small {
+
display: none;
+
}
+
+
#loadingbirds #loadingText {
+
font-family: "Space Mono", monospace;
+
text-align: center;
+
font-style: oblique 5deg;
+
font-size: 2em;
+
min-height: 1em;
+
}
+
+
@media screen and (max-width: 780px) {
+
#loadingbirds .small {
+
display: block;
+
}
+
+
#loadingbirds .large {
+
display: none;
+
}
+
+
#loadingbirds #loadingText {
+
font-size: 1.25em;
+
}
}
/* Responsive Styling */