data endpoint for entity 90008 (aka. a website)
0
fork

Configure Feed

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

feat: add donate links, make links collapsible, etc.

dusk 631a5c8d 0e615829

+189 -89
+1 -1
src/hooks.server.ts
··· 18 18 } from '$lib/visits'; 19 19 import { testUa } from '$lib/robots'; 20 20 import { error } from '@sveltejs/kit'; 21 - import { _fetchEntries } from './routes/guestbook/+page.server'; 21 + import { _fetchEntries } from './routes/(site)/guestbook/+page.server'; 22 22 23 23 const UPDATE_LAST_JOB_NAME = 'update steam game, lastfm track, bsky posts, git activity'; 24 24
+4
src/routes/(site)/copy/+page.server.ts
··· 1 + export const load = async ({ url }) => { 2 + const text = url.searchParams.get('text') ?? '<nothing>'; 3 + return { text }; 4 + };
+31
src/routes/(site)/copy/+page.svelte
··· 1 + <script lang="ts"> 2 + import Window from '$components/window.svelte'; 3 + 4 + interface Data { 5 + text: string; 6 + } 7 + interface Props { 8 + data: Data; 9 + } 10 + 11 + const { data }: Props = $props(); 12 + const { text }: Data = data; 13 + 14 + let copied = $state(false); 15 + </script> 16 + 17 + <div class="flex justify-center items-center w-[100vw] h-[100vh] px-[15%]"> 18 + <!-- svelte-ignore a11y_click_events_have_key_events --> 19 + <!-- svelte-ignore a11y_no_static_element_interactions --> 20 + <div 21 + onclick={() => { 22 + navigator.clipboard.writeText(text); 23 + copied = true; 24 + setTimeout(() => (copied = false), 1000); 25 + }} 26 + > 27 + <Window style="!max-w-full" title={copied ? 'copied!' : 'click to copy'}> 28 + <span class="text-4xl text-wrap break-all">{text}</span> 29 + </Window> 30 + </div> 31 + </div>
src/routes/+layout.server.ts src/routes/(site)/+layout.server.ts
+8 -8
src/routes/+layout.svelte src/routes/(site)/+layout.svelte
··· 1 1 <script lang="ts"> 2 2 import { browser } from '$app/environment'; 3 3 import getTitle from '$lib/getTitle'; 4 - import Eye from '../components/eye.svelte'; 5 - import NavButton from '../components/navButton.svelte'; 6 - import Pet, { localBounces, localDistanceTravelled } from '../components/pet.svelte'; 7 - import Tooltip from '../components/tooltip.svelte'; 8 - import '../styles/app.css'; 4 + import Eye from '$components/eye.svelte'; 5 + import NavButton from '$components/navButton.svelte'; 6 + import Pet, { localBounces, localDistanceTravelled } from '$components/pet.svelte'; 7 + import Tooltip from '$components/tooltip.svelte'; 8 + import '$styles/app.css'; 9 9 10 10 interface Props { 11 11 // eslint-disable-next-line @typescript-eslint/no-explicit-any ··· 80 80 image-rendering="optimizeSpeed" 81 81 > 82 82 <defs> 83 - {#each svgSquiggles as [scale], index} 83 + {#each svgSquiggles as [scale], index (index)} 84 84 <filter id="squiggly-{index}"> 85 85 <feTurbulence 86 86 id="turbulence" ··· 146 146 </svg> 147 147 148 148 {#if !isResumePage} 149 - {#each data.lastVisitors as [id, visitor], index} 149 + {#each data.lastVisitors as [id, visitor], index (id)} 150 150 {@const pos = eyePositions.at(index)} 151 151 {#if pos !== undefined} 152 152 <Eye visits={visitor.visits} {id} top={pos[0]} left={pos[1]} /> ··· 174 174 style="border-style: ridge hidden hidden hidden;" 175 175 > 176 176 <div class="flex flex-row flex-nowrap gap-2 justify-start overflow-x-auto"> 177 - {#each menuItems as item, menuIdx} 177 + {#each menuItems as item, menuIdx (item.href)} 178 178 {@const highlight = isRoute(item.href)} 179 179 <NavButton {highlight} {...item} /> 180 180 {#if isEntryPage && menuIdx === 1}
+1 -1
src/routes/+page.server.ts src/routes/(site)/+page.server.ts
··· 1 1 import { getLastPosts } from '$lib/bluesky.js'; 2 2 import { getNowPlaying } from '$lib/lastfm'; 3 3 import { getLastGame } from '$lib/steam'; 4 - import { noteFromBskyPost } from '../components/note.svelte'; 4 + import { noteFromBskyPost } from '$components/note.svelte'; 5 5 import { pushNotification } from '$lib/pushnotif'; 6 6 import { getLastActivity } from '$lib/activity.js'; 7 7 import type { RequestEvent } from '@sveltejs/kit';
+113 -55
src/routes/+page.svelte src/routes/(site)/+page.svelte
··· 1 1 <script lang="ts"> 2 2 import { PUBLIC_BASE_URL } from '$env/static/public'; 3 - import Note from '../components/note.svelte'; 4 - import Window from '../components/window.svelte'; 3 + import Note from '$components/note.svelte'; 4 + import Window from '$components/window.svelte'; 5 5 import { renderDate, renderRelativeDate } from '$lib/dateFmt'; 6 - import Tooltip from '../components/tooltip.svelte'; 6 + import Tooltip from '$components/tooltip.svelte'; 7 7 8 8 interface Props { 9 9 // eslint-disable-next-line @typescript-eslint/no-explicit-any 10 10 data: any; 11 11 } 12 + 13 + const trimStr = (str: string, maxLength: number = 32): string => { 14 + if (str.length <= maxLength) return str; 15 + return str.slice(0, maxLength - 3) + '…'; 16 + }; 17 + 18 + const wallets: Record<string, string> = { 19 + btc: 'bc1q7dgsgxj8jua50d3xjgg28v2c6uhpgpe79vr4ra', 20 + eth: '0xF5dC63d340556925Ae2a64e5F0c19e3c2471139F', 21 + xmr: '45TJMbHrdyTSPywExKbzL51uuJZGTrDzrLidFufeGU4LA13Un92LTZeWhy2ePCcVaZ64KJdUjSZgMPM9jXfjJcxEQJ8szvw' 22 + }; 12 23 13 24 const buttons = [ 14 25 { ··· 239 250 </Window> 240 251 </div> 241 252 <div class="flex flex-col gap-2 md:gap-3 md:mr-auto w-full md:w-fit place-items-start"> 242 - <Window title="links!" iconUri="/icons/contact.webp"> 243 - <div 244 - class="[width:40ch] prose prose-ralsei prose-ul:px-[0.9rem] prose-ul:leading-none prose-headings:leading-none" 245 - > 246 - <ul> 247 - <li>discord: 90.008</li> 248 - <li> 249 - e-mail: 250 - <a class="u-email" href="mailto:90008@gaze.systems" rel="me">90008@gaze.systems</a> 251 - </li> 252 - <li> 253 - bluesky: 254 - <a class="u-url" href="https://bsky.app/profile/poor.dog" rel="me">@poor.dog</a> 255 - </li> 256 - </ul> 257 - <h4>development</h4> 258 - <ul> 259 - <li> 260 - github: 261 - <a class="u-url" href="https://github.com/90-008" rel="me">@90-008</a> 262 - </li> 263 - <li> 264 - forgejo: 265 - <a class="u-url" href="https://git.gaze.systems/90008" rel="me">@90008</a> 266 - (<a href="https://git.gaze.systems/90008/website">website repo</a>) 267 - </li> 268 - <li> 269 - itch.io: 270 - <a class="u-url" href="https://90008.itch.io" rel="me">@90008</a> 271 - </li> 272 - </ul> 273 - <h4>services</h4> 274 - <ul> 275 - <li> 276 - <a href="https://gaze.systems/nsid-tracker">atproto lexicon tracker</a> 277 - </li> 278 - <li> 279 - <a href="https://pmart.gaze.systems">random project moon art</a> 280 - </li> 281 - </ul> 282 - <h4>88x31</h4> 283 - <div class="flex flex-row flex-wrap gap-1 prose-img:m-0"> 284 - <img src="/88x31.gif" alt="88x31 banner" title="midnight AND sunrise! woaw" /> 285 - <img 286 - src="/88x31_midnight.gif" 287 - alt="88x31 banner (midnight only)" 288 - title="it's midnight!" 289 - /> 290 - <img src="/88x31_sunrise.gif" alt="88x31 banner (sunrise only)" title="it's sunrise!" /> 291 - </div> 292 - </div> 293 - </Window> 294 253 <Window style="md:ml-2" title="readme?" iconUri="/icons/question.webp" removePadding> 295 254 <div class="flex flex-col p-1.5 gap-1.5 prose prose-ralsei prose-img:m-0 leading-none"> 296 255 <div class="flex flex-row gap-3 mx-auto bg-ralsei-black/20 overflow-hidden"> ··· 419 378 /> 420 379 </form> 421 380 </Window> 381 + <Window title="links!" iconUri="/icons/contact.webp"> 382 + <div 383 + class="[width:40ch] prose prose-ralsei prose-ul:px-[0.9rem] prose-ul:mt-2 prose-ul:leading-none prose-headings:leading-none" 384 + > 385 + <ul> 386 + <li>discord: 90.008</li> 387 + <li> 388 + e-mail: 389 + <a class="u-email" href="mailto:90008@gaze.systems" rel="me">90008@gaze.systems</a> 390 + </li> 391 + <li> 392 + bluesky: 393 + <a class="u-url" href="https://bsky.app/profile/poor.dog" rel="me">@poor.dog</a> 394 + </li> 395 + </ul> 396 + <details open> 397 + <summary>development</summary> 398 + <ul> 399 + <li> 400 + github: 401 + <a class="u-url" href="https://github.com/90-008" rel="me">@90-008</a> 402 + </li> 403 + <li> 404 + forgejo: 405 + <a class="u-url" href="https://git.gaze.systems/90008" rel="me">@90008</a> 406 + (<a href="https://git.gaze.systems/90008/website">website repo</a>) 407 + </li> 408 + <li> 409 + tangled: 410 + <a class="u-url" href="https://tangled.sh/@poor.dog" rel="me">@poor.dog</a> 411 + </li> 412 + <li> 413 + itch.io: 414 + <a class="u-url" href="https://90008.itch.io" rel="me">@90008</a> 415 + </li> 416 + </ul> 417 + </details> 418 + <details class="donate" open> 419 + <summary>donate</summary> 420 + <ul> 421 + {#each ['eth', 'btc', 'xmr'] as coin (coin)} 422 + <li> 423 + <span 424 + >{coin}: <a href="/copy?text={wallets[coin]}">{trimStr(wallets[coin])}</a></span 425 + > 426 + </li> 427 + {/each} 428 + <li> 429 + <span 430 + ><a href="https://patreon.com/_90008" rel="me">patreon</a>, 431 + <a href="https://github.com/sponsors/90-008" rel="me">github sponsors</a></span 432 + > 433 + </li> 434 + </ul> 435 + </details> 436 + <details> 437 + <summary>services</summary> 438 + <ul> 439 + <li> 440 + <a href="https://gaze.systems/nsid-tracker">atproto lexicon tracker</a> 441 + </li> 442 + <li> 443 + <a href="https://pmart.gaze.systems">random project moon art</a> 444 + </li> 445 + </ul> 446 + </details> 447 + <details> 448 + <summary>88x31</summary> 449 + <div class="mt-2 flex flex-row flex-wrap gap-1 prose-img:m-0"> 450 + <img src="/88x31.gif" alt="88x31 banner" title="midnight AND sunrise! woaw" /> 451 + <img 452 + src="/88x31_midnight.gif" 453 + alt="88x31 banner (midnight only)" 454 + title="it's midnight!" 455 + /> 456 + <img src="/88x31_sunrise.gif" alt="88x31 banner (sunrise only)" title="it's sunrise!" /> 457 + </div> 458 + </details> 459 + </div> 460 + </Window> 422 461 </div> 423 462 </div> 424 463 ··· 426 465 .entry { 427 466 @apply bg-ralsei-green-dark/70 border-ralsei-green-light/30 border-x-[4px] border-y-[5px]; 428 467 border-style: ridge; 468 + } 469 + 470 + details { 471 + @apply leading-none mt-2; 472 + summary { 473 + @apply text-shadow-pink text-ralsei-pink-neon; 474 + } 475 + summary::marker { 476 + content: '(+) '; 477 + } 478 + } 479 + details[open] summary::marker { 480 + content: '(*) '; 481 + } 482 + 483 + .donate ul { 484 + li span { 485 + @apply font-monospace overflow-hidden text-ellipsis text-nowrap; 486 + } 429 487 } 430 488 </style>
src/routes/about/+page.md src/routes/(site)/about/+page.md
+2 -2
src/routes/about/_layout.svelte src/routes/(site)/about/_layout.svelte
··· 1 1 <script lang="ts"> 2 - import Window from '../../components/window.svelte'; 2 + import Window from '$components/window.svelte'; 3 3 // @ts-expect-error "mdsvex include is broken" 4 4 import Stuff from './stuff.md'; 5 5 // @ts-expect-error "mdsvex include is broken" 6 6 import Media from './media.md'; 7 - import '../../styles/app.css'; 7 + import '$styles/app.css'; 8 8 9 9 interface Props { 10 10 title: string;
src/routes/about/media.md src/routes/(site)/about/media.md
src/routes/about/stuff.md src/routes/(site)/about/stuff.md
src/routes/entries/+layout.server.ts src/routes/(site)/entries/+layout.server.ts
src/routes/entries/+page.server.ts src/routes/(site)/entries/+page.server.ts
+3 -3
src/routes/entries/+page.svelte src/routes/(site)/entries/+page.svelte
··· 1 1 <script lang="ts"> 2 - import Window from '../../components/window.svelte'; 2 + import Window from '$components/window.svelte'; 3 3 import type { PostData } from './+layout.server.ts'; 4 4 import LogPage from '../log/+page.svelte'; 5 - import type { NoteData } from '../../components/note.svelte'; 5 + import type { NoteData } from '$components/note.svelte'; 6 6 7 7 interface Props { 8 8 data: { ··· 16 16 17 17 <div class="mx-auto md:max-w-fit flex flex-col-reverse md:flex-row gap-y-4 gap-x-16"> 18 18 <div class="flex flex-col gap-y-4"> 19 - {#each data.posts as post} 19 + {#each data.posts as post (post.path)} 20 20 <Window title={post.metadata.title} iconUri="/icons/entry.webp"> 21 21 <a 22 22 href="/entries/{post.path}"
+2 -2
src/routes/entries/_layout.svelte src/routes/(site)/entries/_layout.svelte
··· 1 1 <script lang="ts"> 2 2 import { PUBLIC_BASE_URL } from '$env/static/public'; 3 - import Window from '../../components/window.svelte'; 4 - import '../../styles/app.css'; 3 + import Window from '$components/window.svelte'; 4 + import '$styles/app.css'; 5 5 import { page } from '$app/state'; 6 6 7 7 interface Props {
src/routes/entries/_rss/+server.ts src/routes/(site)/entries/_rss/+server.ts
src/routes/entries/hello-world/+page.md src/routes/(site)/entries/hello-world/+page.md
src/routes/entries/japan-trip24/+page.md src/routes/(site)/entries/japan-trip24/+page.md
src/routes/entries/japan-trip24/+page.server.ts src/routes/(site)/entries/japan-trip24/+page.server.ts
src/routes/entries/japan-trip24/images.json src/routes/(site)/entries/japan-trip24/images.json
src/routes/entries/test/+page.md src/routes/(site)/entries/test/+page.md
+1 -1
src/routes/guestbook/+page.server.ts src/routes/(site)/guestbook/+page.server.ts
··· 5 5 import { getBskyClient, getUserPosts } from '$lib/bluesky.js'; 6 6 import { getVisitorId } from '$lib/visits'; 7 7 import { nanoid } from 'nanoid'; 8 - import { noteFromBskyPost, type NoteData } from '../../components/note.svelte'; 8 + import { noteFromBskyPost, type NoteData } from '$components/note.svelte'; 9 9 import { get, writable } from 'svelte/store'; 10 10 import type { Post } from '@skyware/bot'; 11 11 import { useToken as checkApiToken, newToken } from '$lib/apiToken.js';
+4 -4
src/routes/guestbook/+page.svelte src/routes/(site)/guestbook/+page.svelte
··· 1 1 <script lang="ts"> 2 - import Note, { type NoteData } from '../../components/note.svelte'; 3 - import Token from '../../components/token.svelte'; 4 - import Window from '../../components/window.svelte'; 2 + import Note, { type NoteData } from '$components/note.svelte'; 3 + import Token from '$components/token.svelte'; 4 + import Window from '$components/window.svelte'; 5 5 6 6 interface Props { 7 7 data: { ··· 126 126 /> 127 127 <br /> 128 128 <br /> 129 - {#each data.entries as note, index} 129 + {#each data.entries as note, index ([note.content, note.published])} 130 130 <Note 131 131 mapOutgoingNames={{ bsky: '', reply: 'src' }} 132 132 showOutgoing={true}
+1 -1
src/routes/log/+page.server.ts src/routes/(site)/log/+page.server.ts
··· 1 1 import { getLastPosts } from '$lib/bluesky.js'; 2 - import { noteFromBskyPost } from '../../components/note.svelte'; 2 + import { noteFromBskyPost } from '$components/note.svelte'; 3 3 4 4 export const load = async () => { 5 5 return _load();
+4 -4
src/routes/log/+page.svelte src/routes/(site)/log/+page.svelte
··· 1 1 <script lang="ts"> 2 - import Window from '../../components/window.svelte'; 3 - import Token from '../../components/token.svelte'; 4 - import Note, { type NoteData } from '../../components/note.svelte'; 2 + import Window from '$components/window.svelte'; 3 + import Token from '$components/token.svelte'; 4 + import Note, { type NoteData } from '$components/note.svelte'; 5 5 6 6 interface Props { 7 7 data: { ··· 52 52 /> 53 53 <br /> 54 54 <br /> 55 - {#each data.feedPosts as note, index} 55 + {#each data.feedPosts as note, index ([note.content, note.published])} 56 56 <Note rootNote={note} /> 57 57 {#if index < data.feedPosts.length - 1} 58 58 <div class="mt-3"></div>
src/routes/log/_rss/+server.ts src/routes/(site)/log/_rss/+server.ts
+7 -3
svelte.config.js
··· 34 34 backticks: false 35 35 }, 36 36 layout: { 37 - about: resolve('src/routes/about/_layout.svelte'), 38 - blogpost: resolve('src/routes/entries/_layout.svelte'), 37 + about: resolve('src/routes/(site)/about/_layout.svelte'), 38 + blogpost: resolve('src/routes/(site)/entries/_layout.svelte'), 39 39 simple: resolve('src/components/_window_layout.svelte') 40 40 } 41 41 }) ··· 50 50 }, 51 51 adapter: adapter({ 52 52 precompress: true 53 - }) 53 + }), 54 + alias: { 55 + $components: 'src/components', 56 + $styles: 'src/styles' 57 + } 54 58 } 55 59 }; 56 60
+1
tailwind.config.js
··· 30 30 }), 31 31 animation: { 32 32 'bounce-slow': 'bounce 3s infinite', 33 + 'bounce-fast': 'bounce 0.5s infinite', 33 34 'pulse-fast': 'pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite', 34 35 blink: 'blink 1s step-start infinite' 35 36 },
+6 -4
tsconfig.json
··· 11 11 "strict": true, 12 12 "moduleResolution": "bundler", 13 13 "allowImportingTsExtensions": true, 14 - "plugins": [{ 15 - "name": "typescript-svelte-plugin", 16 - "enabled": true 17 - }] 14 + "plugins": [ 15 + { 16 + "name": "typescript-svelte-plugin", 17 + "enabled": true 18 + } 19 + ] 18 20 } 19 21 // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 20 22 // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files