Compare commits

..

No commits in common. "862b11b9ef0a5ca9576255bbd311116c0d6d2681" and "110cb2a3e5621e7f5bfff1e1549550a897ec17a7" have entirely different histories.

35 changed files with 191 additions and 670 deletions

1
.gitignore vendored
View file

@ -12,4 +12,3 @@ node_modules/
vendor/
sync.sh
static/extra

View file

@ -42,9 +42,9 @@ nav li a {
}
nav li.selected a {
background-color: var(--theme-primary);
background-color: var(--theme-foreground);
color: var(--theme-background);
border-radius: var(--radius-lg);
border-radius: var(--radius-sm);
}
nav a {
@ -106,33 +106,21 @@ section::before {
}
}
.typewriting a::after,
section.typewriting a::after,
#donation a::after,
#links a::after,
#about a::after,
article a::after {
#links a::after {
display: inline-block;
width: 0.9em;
height: 0.9em;
margin-left: var(--space-1);
vertical-align: -0.1em;
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a7a0ff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6' /%3E%3Cpath d='M11 13l9 -9' /%3E%3Cpath d='M15 4h5v5' /%3E%3C/svg%3E");
}
@media (prefers-color-scheme: light) {
.typewriting a::after,
#donation a::after,
#links a::after,
#about a::after,
article a::after {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236f65f2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6' /%3E%3Cpath d='M11 13l9 -9' /%3E%3Cpath d='M15 4h5v5' /%3E%3C/svg%3E");
}
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23cac7ee' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6' /%3E%3Cpath d='M11 13l9 -9' /%3E%3Cpath d='M15 4h5v5' /%3E%3C/svg%3E");
}
section.typewriting a,
#donation a,
#links a {
color: var(--theme-primary);
color: var(--theme-foreground);
}
header {

View file

@ -17,31 +17,13 @@
background-color: var(--theme-background-alt);
border: 1px solid var(--theme-separator);
padding: var(--space-3) var(--space-4);
margin-bottom: var(--space-2);
margin-bottom: var(--space-3);
position: relative;
overflow: hidden;
border-radius: var(--radius-lg);
border-radius: var(--radius-md);
transition: all var(--transition-fast);
}
.project-card::before {
overflow: hidden;
display: flex;
position: absolute;
left: 0;
top: -7rem;
content: "</;^//";
color: transparent;
font-size: 32rem;
letter-spacing: -0.075em;
line-height: 1;
text-align: center;
align-items: center;
justify-content: center;
-webkit-text-stroke: 2px var(--theme-separator);
opacity: 0.16;
}
.project-card:hover {
background-color: rgba(255, 255, 255, 0.025);
border-color: rgba(255, 255, 255, 0.125);
@ -78,8 +60,8 @@
}
.project-card .author {
font-size: calc(var(--font-size-sm) * 1.25);
margin-bottom: var(--space-1);
font-size: var(--font-size-xs);
margin-bottom: var(--space-2);
}
.project-card .author strong {
@ -193,7 +175,6 @@
transition: opacity var(--transition-fast);
border-radius: var(--radius-music);
z-index: var(--z-base);
color: var(--theme-foreground);
}
.fm-more::before {
@ -318,31 +299,29 @@ u #friends::before {
top: 3rem;
}
#about h2::before,
#languages h2::before,
#trivia h2::before {
background-color: #9f99f0;
#about h2::before {
background-color: var(--theme-foreground);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}
#links h2::before {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='%239f99f0' %3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 2a3 3 0 0 1 2.995 2.824l.005 .176v1h3a2 2 0 0 1 1.995 1.85l.005 .15v3h1a3 3 0 0 1 .176 5.995l-.176 .005h-1v3a2 2 0 0 1 -1.85 1.995l-.15 .005h-3a2 2 0 0 1 -1.995 -1.85l-.005 -.15v-1a1 1 0 0 0 -1.993 -.117l-.007 .117v1a2 2 0 0 1 -1.85 1.995l-.15 .005h-3a2 2 0 0 1 -1.995 -1.85l-.005 -.15v-3a2 2 0 0 1 1.85 -1.995l.15 -.005h1a1 1 0 0 0 .117 -1.993l-.117 -.007h-1a2 2 0 0 1 -1.995 -1.85l-.005 -.15v-3a2 2 0 0 1 1.85 -1.995l.15 -.005h3v-1a3 3 0 0 1 3 -3z' /%3E%3C/svg%3E");
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='%23cac7ee' %3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 2a3 3 0 0 1 2.995 2.824l.005 .176v1h3a2 2 0 0 1 1.995 1.85l.005 .15v3h1a3 3 0 0 1 .176 5.995l-.176 .005h-1v3a2 2 0 0 1 -1.85 1.995l-.15 .005h-3a2 2 0 0 1 -1.995 -1.85l-.005 -.15v-1a1 1 0 0 0 -1.993 -.117l-.007 .117v1a2 2 0 0 1 -1.85 1.995l-.15 .005h-3a2 2 0 0 1 -1.995 -1.85l-.005 -.15v-3a2 2 0 0 1 1.85 -1.995l.15 -.005h1a1 1 0 0 0 .117 -1.993l-.117 -.007h-1a2 2 0 0 1 -1.995 -1.85l-.005 -.15v-3a2 2 0 0 1 1.85 -1.995l.15 -.005h3v-1a3 3 0 0 1 3 -3z' /%3E%3C/svg%3E");
}
#donation h2::before {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='%239f99f0'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M15.999 2a1 1 0 0 1 1.001 1v3.255l.026 .018a7 7 0 0 1 2.204 2.537l.092 .19h.676a2 2 0 0 1 1.995 1.85l.005 .15v2a2 2 0 0 1 -2 2h-.676l-.104 .213a7 7 0 0 1 -1.097 1.558l-.123 .125v1.604a2.5 2.5 0 0 1 -2.336 2.495l-.162 .005c-1.16 0 -2.135 -.79 -2.418 -1.86l-.032 -.141l-4.05 .001l-.05 -.002l-.032 .141a2.5 2.5 0 0 1 -2.254 1.856l-.164 .005a2.5 2.5 0 0 1 -2.5 -2.5v-1.602l-.056 -.055a7 7 0 0 1 -1.576 -7.085l.092 -.256a7 7 0 0 1 6.539 -4.502h2.196l4.25 -2.832a1 1 0 0 1 .436 -.161zm-.999 8a1 1 0 0 0 -.993 .883l-.007 .127a1 1 0 0 0 1.993 .117l.007 -.127a1 1 0 0 0 -1 -1'/%3E%3C/svg%3E");
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='%23cac7ee'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M15.999 2a1 1 0 0 1 1.001 1v3.255l.026 .018a7 7 0 0 1 2.204 2.537l.092 .19h.676a2 2 0 0 1 1.995 1.85l.005 .15v2a2 2 0 0 1 -2 2h-.676l-.104 .213a7 7 0 0 1 -1.097 1.558l-.123 .125v1.604a2.5 2.5 0 0 1 -2.336 2.495l-.162 .005c-1.16 0 -2.135 -.79 -2.418 -1.86l-.032 -.141l-4.05 .001l-.05 -.002l-.032 .141a2.5 2.5 0 0 1 -2.254 1.856l-.164 .005a2.5 2.5 0 0 1 -2.5 -2.5v-1.602l-.056 -.055a7 7 0 0 1 -1.576 -7.085l.092 -.256a7 7 0 0 1 6.539 -4.502h2.196l4.25 -2.832a1 1 0 0 1 .436 -.161zm-.999 8a1 1 0 0 0 -.993 .883l-.007 .127a1 1 0 0 0 1.993 .117l.007 -.127a1 1 0 0 0 -1 -1'/%3E%3C/svg%3E");
}
#projects h2::before {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='%239f99f0'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M17.108 22.085c-1.266 -.068 -2.924 -.859 -5.071 -2.355l-.04 -.027l-.037 .027c-2.147 1.497 -3.804 2.288 -5.072 2.356l-.178 .005c-2.747 0 -3.097 -2.64 -1.718 -7.244l.054 -.178l-.1 -.075c-6.056 -4.638 -5.046 -7.848 2.554 -8.066l.202 -.005l.115 -.326c1.184 -3.33 2.426 -5.085 4.027 -5.192l.156 -.005c1.674 0 2.957 1.76 4.182 5.197l.114 .326l.204 .005c7.6 .218 8.61 3.428 2.553 8.065l-.102 .075l.055 .178c1.35 4.512 1.04 7.137 -1.556 7.24l-.163 .003z' /%3E%3C/svg%3E");
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='%23cac7ee'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M17.108 22.085c-1.266 -.068 -2.924 -.859 -5.071 -2.355l-.04 -.027l-.037 .027c-2.147 1.497 -3.804 2.288 -5.072 2.356l-.178 .005c-2.747 0 -3.097 -2.64 -1.718 -7.244l.054 -.178l-.1 -.075c-6.056 -4.638 -5.046 -7.848 2.554 -8.066l.202 -.005l.115 -.326c1.184 -3.33 2.426 -5.085 4.027 -5.192l.156 -.005c1.674 0 2.957 1.76 4.182 5.197l.114 .326l.204 .005c7.6 .218 8.61 3.428 2.553 8.065l-.102 .075l.055 .178c1.35 4.512 1.04 7.137 -1.556 7.24l-.163 .003z' /%3E%3C/svg%3E");
}
#friends h2::before {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239f99f0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M9 7m-4 0a4 4 0 1 0 8 0a4 4 0 1 0 -8 0' /%3E%3Cpath d='M3 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2' /%3E%3Cpath d='M16 3.13a4 4 0 0 1 0 7.75' /%3E%3Cpath d='M21 21v-2a4 4 0 0 0 -3 -3.85' /%3E%3C/svg%3E");
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23cac7ee' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M9 7m-4 0a4 4 0 1 0 8 0a4 4 0 1 0 -8 0' /%3E%3Cpath d='M3 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2' /%3E%3Cpath d='M16 3.13a4 4 0 0 1 0 7.75' /%3E%3Cpath d='M21 21v-2a4 4 0 0 0 -3 -3.85' /%3E%3C/svg%3E");
}
#media h2::before {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239f99f0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 10v3'/%3E%3Cpath d='M6 6v11'/%3E%3Cpath d='M10 3v18'/%3E%3Cpath d='M14 8v7'/%3E%3Cpath d='M18 5v13'/%3E%3Cpath d='M22 10v3'/%3E%3C/svg%3E");
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23cac7ee' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 10v3'/%3E%3Cpath d='M6 6v11'/%3E%3Cpath d='M10 3v18'/%3E%3Cpath d='M14 8v7'/%3E%3Cpath d='M18 5v13'/%3E%3Cpath d='M22 10v3'/%3E%3C/svg%3E");
}
.typecycle {
@ -351,7 +330,7 @@ u #friends::before {
.typecycle::after {
content: "";
border-right: 0.15em solid var(--theme-primary);
border-right: 0.15em solid var(--theme-foreground);
animation: caret 2s ease-in-out infinite;
padding-left: 0.25ch;
}
@ -382,7 +361,7 @@ u #friends::before {
}
8.33%,
16.66% {
width: 4ch;
width: 6ch;
}
}
@ -444,7 +423,7 @@ u #friends::before {
font-size: var(--font-size-xs);
text-transform: uppercase;
letter-spacing: 0.08em;
margin-bottom: var(--space-0);
margin-bottom: var(--space-3);
font-weight: 600;
color: var(--theme-foreground-alt);
}
@ -454,10 +433,19 @@ u #friends::before {
padding-left: 0;
}
.griddy .column a::before {
content: "$ ";
color: var(--theme-foreground);
}
.griddy .column li {
font-style: italic;
font-size: 0.9em;
color: var(--theme-foreground-alt);
color: var(--theme-foreground-bruh);
}
.griddy .column a {
font-style: normal;
color: var(--theme-foreground);
}
.pfps {
@ -503,28 +491,3 @@ u #friends::before {
.pfps:has(a:hover) a:not(:hover) {
transform: scale(0.92);
}
footer {
border-top: 1px solid var(--theme-separator);
padding: var(--section-spacing) 0;
color: var(--theme-foreground-bruh);
text-align: center;
}
footer a,
.highlight {
color: var(--theme-primary);
}
#languages ul,
#trivia ul {
color: var(--theme-foreground-alt);
font-size: 0.9em;
padding-left: 2ch;
}
#languages li::marker,
#trivia li::marker {
color: var(--theme-foreground);
content: "# ";
}

View file

@ -11,7 +11,7 @@
border: 1px solid var(--theme-separator);
padding: var(--space-4) var(--space-5);
margin-bottom: var(--space-3);
border-radius: var(--radius-lg);
border-radius: var(--radius-md);
transition: all var(--transition-fast);
opacity: 75%;
position: relative;
@ -31,11 +31,10 @@
line-height: 1;
text-align: center;
-webkit-text-stroke: 2px var(--theme-separator);
opacity: 0.16;
opacity: 0.5;
}
.reports li,
.report:hover {
.reports li, .report:hover {
opacity: 1;
filter: none;
}
@ -46,11 +45,6 @@
margin-bottom: var(--space-2);
}
.report .readingTime {
font-size: var(--font-size-sm);
color: var(--theme-foreground-bruh);
}
.report h3 {
font-size: var(--font-size-lg);
font-weight: 600;
@ -65,8 +59,7 @@
margin-bottom: var(--space-2);
}
.report .excerpt,
.report .title {
.report .excerpt, .report .title {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
@ -78,7 +71,6 @@
.report .tags {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-2);
margin-top: var(--space-3);
}
@ -88,7 +80,7 @@
padding: var(--space-0) var(--space-2);
background-color: var(--theme-background);
border: 1px solid var(--theme-separator);
border-radius: var(--radius-lg);
border-radius: var(--radius-sm);
color: var(--theme-foreground-alt);
}
@ -119,20 +111,13 @@ article header .meta {
align-items: center;
font-size: var(--font-size-md);
color: var(--theme-foreground-bruh);
margin-bottom: var(--space-2);
margin-bottom: var(--space-4);
gap: var(--space-4);
}
body > a[href="/reports"] {
color: var(--theme-foreground-alt);
font-size: 0.75em;
font-style: italic;
}
article header h1 {
font-size: var(--font-size-xl);
margin-top: var(--space-5);
margin-bottom: var(--space-3);
margin: var(--space-3) 0;
color: var(--theme-foreground);
}
@ -147,7 +132,7 @@ article header .tag {
padding: var(--space-1) var(--space-3);
background-color: var(--theme-background-alt);
border: 1px solid var(--theme-separator);
border-radius: var(--radius-lg);
border-radius: 2px;
color: var(--theme-foreground-alt);
}
@ -194,19 +179,3 @@ article footer {
color: var(--theme-foreground-alt);
font-size: var(--font-size-md);
}
#reports-header {
display: flex;
align-items: center;
gap: var(--space-3);
}
#reports-header > a {
font-size: 1rem;
display: flex;
align-items: center;
}
#reports-header > a > svg {
margin-left: var(--space-1);
}

View file

@ -1,5 +1,3 @@
@import url(/fonts/iosevka-custom/import.css);
*,
*::before,
*::after {
@ -59,16 +57,11 @@ button,
cursor: pointer;
}
html,
body {
html, body {
font-size: var(--font-size-base);
}
html,
body,
pre,
code,
button {
html, body, pre, code, button {
font-family:
"Iosevka Custom Web", "Iosevka Custom", "Iosevka", monospace, sans-serif;
line-height: 1.7;

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@ -7,8 +7,7 @@
--theme-background: #121317;
--theme-background-alt: #090a0d;
--theme-foreground: #cac7ee;
--theme-primary: #9f99f0;
--theme-foreground-alt: #9593b9;
--theme-foreground-alt: #a4a3bd;
--theme-foreground-bruh: #7d7d86;
--theme-separator: #232833;
@ -72,7 +71,6 @@
--theme-foreground: #1d1d1f;
--theme-foreground-alt: #515154;
--theme-foreground-bruh: #86868b;
--theme-separator: #b9b9bf;
--theme-primary: #6f65f2;
--theme-separator: #d2d2d7;
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@ -34,13 +34,11 @@ export function Fm() {
</span>
)
: (
track.loved && (
<span class="loved" title="Loved">
</span>
)
)}
: (track.loved && (
<span class="loved" title="Loved">
</span>
))}
</div>
</a>
</li>

View file

@ -1,29 +0,0 @@
/**
* Copyright (c) 2025 miwa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
export default function Footer() {
return (
<footer class="section typewriting">
<p class="alt alt-font">
Made with <span class="highlight"></span> · Source code available at
{" "}
<a href="https://kyu.re/~web">git.acpi.at</a> under the{" "}
<a href="https://spdx.org/licenses/AGPL-3.0-or-later.html">
GNU Affero General Public License v3.0
</a>
, with all site content licensed under{" "}
<a href="https://creativecommons.org/licenses/by-sa/4.0/">
CC BY-SA 4.0
</a>
.
</p>
<br />
<p class="alt alt-font">
© 2025 <span class="highlight">miwa</span>{" "}
Powered by FreeBSD and autism
</p>
</footer>
);
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@ -7,9 +7,10 @@ export function Header(props: any) {
return (
<header {...props}>
<h1 class="typecycle">
~<span>miwa</span>
~
<span>favewa</span>
<span>lívia</span>
<span>clara</span>
<span>laura</span>
</h1>
<h2>
she/her free software advocate linguistics enthusiast ˶ ˶ sა

View file

@ -1,26 +1,23 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
export default function Links(props: {
selected: "home" | "about" | "reports" | "misc";
}) {
export default function Links(
props: { selected: "home" | "reports" | "misc" },
) {
return (
<nav>
<ul>
<li class={props.selected === "home" ? "selected" : ""}>
<a href="/">home</a>
</li>{" "}
<li class={props.selected === "about" ? "selected" : ""}>
<a href="/about">about</a>
</li>
<li class={props.selected === "reports" ? "selected" : ""}>
<a href="/reports">reports</a>
</li>
{/* <li class={props.selected === "misc" ? "selected" : ""}> */}
{/* <a href="/misc">misc</a> */}
{/* </li> */}
<li class={props.selected === "misc" ? "selected" : ""}>
<a href="/misc">misc</a>
</li>
</ul>
</nav>
);

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,10 +1,9 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { Report } from "../utils/atproto.ts";
import { formatReadingTime } from "../utils/blog.ts";
export interface ReportsProps {
reports: Report[];
@ -14,28 +13,7 @@ export default function Reports({ reports }: ReportsProps) {
return (
<>
<header>
<h1 id="reports-header">
$reports
<a href="/rss.xml" class="rss">
[rss
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M4 11a9 9 0 0 1 9 9" />
<path d="M4 4a16 16 0 0 1 16 16" />
<circle cx="5" cy="19" r="1" />
</svg>
]
</a>
</h1>
<h1>$reports</h1>
<h2>thoughts, ramblings, and occasional coherence</h2>
</header>
@ -43,17 +21,13 @@ export default function Reports({ reports }: ReportsProps) {
{reports.map((report) => (
<li key={report.rkey}>
<a href={`/reports/${report.rkey}`} class="report">
<span class="date">
{report.createdAt} · {formatReadingTime(report.readingTime)}
</span>
<span class="date">{report.createdAt}</span>
<h3>{report.title}</h3>
<p class="excerpt">{report.excerpt}</p>
{report.tags && (
<div class="tags">
{report.tags.map((tag) => (
<span key={tag} class="tag">
{tag}
</span>
<span key={tag} class="tag">{tag}</span>
))}
</div>
)}

View file

@ -5,8 +5,7 @@
"dev": "vite",
"build": "vite build",
"start": "deno serve -A _fresh/server.js",
"update": "deno run -A -r jsr:@fresh/update .",
"rss": "deno run --allow-net --allow-write scripts/generate-rss.ts"
"update": "deno run -A -r jsr:@fresh/update ."
},
"fmt": {
"useTabs": true
@ -34,9 +33,9 @@
"@musicorum/lastfm": "npm:@musicorum/lastfm@^0.4.0",
"fresh": "jsr:@fresh/core@^2.1.4",
"preact": "npm:preact@^10.27.2",
"@preact/signals": "npm:@preact/signals@^2.5.0",
"@preact/signals": "npm:@preact/signals@^2.4.0",
"@fresh/plugin-vite": "jsr:@fresh/plugin-vite@^1.0.7",
"vite": "npm:vite@^7.2.2"
"vite": "npm:vite@^7.2.1"
},
"compilerOptions": {
"lib": [

132
deno.lock generated
View file

@ -30,15 +30,15 @@
"npm:@mjackson/node-fetch-server@0.7": "0.7.0",
"npm:@musicorum/lastfm@0.4": "0.4.0",
"npm:@opentelemetry/api@^1.9.0": "1.9.0",
"npm:@preact/signals@^2.2.1": "2.5.0_preact@10.27.2",
"npm:@preact/signals@^2.5.0": "2.5.0_preact@10.27.2",
"npm:@prefresh/vite@^2.4.8": "2.4.11_preact@10.27.2_vite@7.2.2__picomatch@4.0.3",
"npm:@preact/signals@^2.2.1": "2.4.0_preact@10.27.2",
"npm:@preact/signals@^2.4.0": "2.4.0_preact@10.27.2",
"npm:@prefresh/vite@^2.4.8": "2.4.11_preact@10.27.2_vite@7.2.1__picomatch@4.0.3",
"npm:esbuild-wasm@~0.25.11": "0.25.12",
"npm:esbuild@0.25.7": "0.25.7",
"npm:preact-render-to-string@^6.6.3": "6.6.3_preact@10.27.2",
"npm:preact@^10.27.0": "10.27.2",
"npm:preact@^10.27.2": "10.27.2",
"npm:vite@^7.2.2": "7.2.2_picomatch@4.0.3"
"npm:vite@^7.2.1": "7.2.1_picomatch@4.0.3"
},
"jsr": {
"@deno/esbuild-plugin@1.2.0": {
@ -671,8 +671,8 @@
"@preact/signals-core@1.12.1": {
"integrity": "sha512-BwbTXpj+9QutoZLQvbttRg5x3l5468qaV2kufh+51yha1c53ep5dY4kTuZR35+3pAZxpfQerGJiQqg34ZNZ6uA=="
},
"@preact/signals@2.5.0_preact@10.27.2": {
"integrity": "sha512-+9KrYvCtnssF4Q7e5xdX08aERL2th4w8kkzPAgI3mSEu2FsVeI93hInS2ifwNIzpEw8+9+e5FPtR7di1WvZiWg==",
"@preact/signals@2.4.0_preact@10.27.2": {
"integrity": "sha512-kVEih9Ty55O+6OKJ85beQJ0gaV++Xci2N2kaQc3LjSUtHKQqB47oMaW6OfwHwzWLRbYsms/326s2ITGiHL7paw==",
"dependencies": [
"@preact/signals-core",
"preact"
@ -681,8 +681,8 @@
"@prefresh/babel-plugin@0.5.2": {
"integrity": "sha512-AOl4HG6dAxWkJ5ndPHBgBa49oo/9bOiJuRDKHLSTyH+Fd9x00shTXpdiTj1W41l6oQIwUOAgJeHMn4QwIDpHkA=="
},
"@prefresh/core@1.5.9_preact@10.27.2": {
"integrity": "sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==",
"@prefresh/core@1.5.8_preact@10.27.2": {
"integrity": "sha512-T7HMpakS1iPVCFZvfDLMGyrWAcO3toUN9/RkJUqqoRr/vNhQrZgHjidfhq3awDzAQtw1emDWH8dsOeu0DWqtgA==",
"dependencies": [
"preact"
]
@ -690,7 +690,7 @@
"@prefresh/utils@1.2.1": {
"integrity": "sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw=="
},
"@prefresh/vite@2.4.11_preact@10.27.2_vite@7.2.2__picomatch@4.0.3": {
"@prefresh/vite@2.4.11_preact@10.27.2_vite@7.2.1__picomatch@4.0.3": {
"integrity": "sha512-/XjURQqdRiCG3NpMmWqE9kJwrg9IchIOWHzulCfqg2sRe/8oQ1g5De7xrk9lbqPIQLn7ntBkKdqWXIj4E9YXyg==",
"dependencies": [
"@babel/core",
@ -709,113 +709,113 @@
"picomatch@2.3.1"
]
},
"@rollup/rollup-android-arm-eabi@4.53.2": {
"integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==",
"@rollup/rollup-android-arm-eabi@4.52.5": {
"integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==",
"os": ["android"],
"cpu": ["arm"]
},
"@rollup/rollup-android-arm64@4.53.2": {
"integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==",
"@rollup/rollup-android-arm64@4.52.5": {
"integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==",
"os": ["android"],
"cpu": ["arm64"]
},
"@rollup/rollup-darwin-arm64@4.53.2": {
"integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==",
"@rollup/rollup-darwin-arm64@4.52.5": {
"integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==",
"os": ["darwin"],
"cpu": ["arm64"]
},
"@rollup/rollup-darwin-x64@4.53.2": {
"integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==",
"@rollup/rollup-darwin-x64@4.52.5": {
"integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==",
"os": ["darwin"],
"cpu": ["x64"]
},
"@rollup/rollup-freebsd-arm64@4.53.2": {
"integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==",
"@rollup/rollup-freebsd-arm64@4.52.5": {
"integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==",
"os": ["freebsd"],
"cpu": ["arm64"]
},
"@rollup/rollup-freebsd-x64@4.53.2": {
"integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==",
"@rollup/rollup-freebsd-x64@4.52.5": {
"integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==",
"os": ["freebsd"],
"cpu": ["x64"]
},
"@rollup/rollup-linux-arm-gnueabihf@4.53.2": {
"integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==",
"@rollup/rollup-linux-arm-gnueabihf@4.52.5": {
"integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==",
"os": ["linux"],
"cpu": ["arm"]
},
"@rollup/rollup-linux-arm-musleabihf@4.53.2": {
"integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==",
"@rollup/rollup-linux-arm-musleabihf@4.52.5": {
"integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==",
"os": ["linux"],
"cpu": ["arm"]
},
"@rollup/rollup-linux-arm64-gnu@4.53.2": {
"integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==",
"@rollup/rollup-linux-arm64-gnu@4.52.5": {
"integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==",
"os": ["linux"],
"cpu": ["arm64"]
},
"@rollup/rollup-linux-arm64-musl@4.53.2": {
"integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==",
"@rollup/rollup-linux-arm64-musl@4.52.5": {
"integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==",
"os": ["linux"],
"cpu": ["arm64"]
},
"@rollup/rollup-linux-loong64-gnu@4.53.2": {
"integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==",
"@rollup/rollup-linux-loong64-gnu@4.52.5": {
"integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==",
"os": ["linux"],
"cpu": ["loong64"]
},
"@rollup/rollup-linux-ppc64-gnu@4.53.2": {
"integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==",
"@rollup/rollup-linux-ppc64-gnu@4.52.5": {
"integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==",
"os": ["linux"],
"cpu": ["ppc64"]
},
"@rollup/rollup-linux-riscv64-gnu@4.53.2": {
"integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==",
"@rollup/rollup-linux-riscv64-gnu@4.52.5": {
"integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==",
"os": ["linux"],
"cpu": ["riscv64"]
},
"@rollup/rollup-linux-riscv64-musl@4.53.2": {
"integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==",
"@rollup/rollup-linux-riscv64-musl@4.52.5": {
"integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==",
"os": ["linux"],
"cpu": ["riscv64"]
},
"@rollup/rollup-linux-s390x-gnu@4.53.2": {
"integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==",
"@rollup/rollup-linux-s390x-gnu@4.52.5": {
"integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==",
"os": ["linux"],
"cpu": ["s390x"]
},
"@rollup/rollup-linux-x64-gnu@4.53.2": {
"integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==",
"@rollup/rollup-linux-x64-gnu@4.52.5": {
"integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==",
"os": ["linux"],
"cpu": ["x64"]
},
"@rollup/rollup-linux-x64-musl@4.53.2": {
"integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==",
"@rollup/rollup-linux-x64-musl@4.52.5": {
"integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==",
"os": ["linux"],
"cpu": ["x64"]
},
"@rollup/rollup-openharmony-arm64@4.53.2": {
"integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==",
"@rollup/rollup-openharmony-arm64@4.52.5": {
"integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==",
"os": ["openharmony"],
"cpu": ["arm64"]
},
"@rollup/rollup-win32-arm64-msvc@4.53.2": {
"integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==",
"@rollup/rollup-win32-arm64-msvc@4.52.5": {
"integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==",
"os": ["win32"],
"cpu": ["arm64"]
},
"@rollup/rollup-win32-ia32-msvc@4.53.2": {
"integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==",
"@rollup/rollup-win32-ia32-msvc@4.52.5": {
"integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==",
"os": ["win32"],
"cpu": ["ia32"]
},
"@rollup/rollup-win32-x64-gnu@4.53.2": {
"integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==",
"@rollup/rollup-win32-x64-gnu@4.52.5": {
"integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==",
"os": ["win32"],
"cpu": ["x64"]
},
"@rollup/rollup-win32-x64-msvc@4.53.2": {
"integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==",
"@rollup/rollup-win32-x64-msvc@4.52.5": {
"integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==",
"os": ["win32"],
"cpu": ["x64"]
},
@ -825,12 +825,12 @@
"await-lock@2.2.2": {
"integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw=="
},
"baseline-browser-mapping@2.8.27": {
"integrity": "sha512-2CXFpkjVnY2FT+B6GrSYxzYf65BJWEqz5tIRHCvNsZZ2F3CmsCB37h8SpYgKG7y9C4YAeTipIPWG7EmFmhAeXA==",
"baseline-browser-mapping@2.8.25": {
"integrity": "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==",
"bin": true
},
"browserslist@4.28.0": {
"integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==",
"browserslist@4.27.0": {
"integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==",
"dependencies": [
"baseline-browser-mapping",
"caniuse-lite",
@ -852,8 +852,8 @@
"ms"
]
},
"electron-to-chromium@1.5.250": {
"integrity": "sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw=="
"electron-to-chromium@1.5.246": {
"integrity": "sha512-CKp2enkTcw94o8p7P+nb3in3yILO7jAIoERSmkIhGazMuK2eLnPSVUH/dxUveGN8ulJJDjYUv0vV7y2e2AZ0nA=="
},
"esbuild-wasm@0.25.12": {
"integrity": "sha512-rZqkjL3Y6FwLpSHzLnaEy8Ps6veCNo1kZa9EOfJvmWtBq5dJH4iVjfmOO6Mlkv9B0tt9WFPFmb/VxlgJOnueNg==",
@ -1010,8 +1010,8 @@
"preact@10.27.2": {
"integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg=="
},
"rollup@4.53.2": {
"integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==",
"rollup@4.52.5": {
"integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==",
"dependencies": [
"@types/estree"
],
@ -1066,7 +1066,7 @@
"multiformats"
]
},
"update-browserslist-db@1.1.4_browserslist@4.28.0": {
"update-browserslist-db@1.1.4_browserslist@4.27.0": {
"integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==",
"dependencies": [
"browserslist",
@ -1075,8 +1075,8 @@
],
"bin": true
},
"vite@7.2.2_picomatch@4.0.3": {
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
"vite@7.2.1_picomatch@4.0.3": {
"integrity": "sha512-qTl3VF7BvOupTR85Zc561sPEgxyUSNSvTQ9fit7DEMP7yPgvvIGm5Zfa1dOM+kOwWGNviK9uFM9ra77+OjK7lQ==",
"dependencies": [
"esbuild@0.25.12",
"fdir",
@ -1530,9 +1530,9 @@
"jsr:@fresh/plugin-vite@^1.0.7",
"npm:@atproto/api@0.18",
"npm:@musicorum/lastfm@0.4",
"npm:@preact/signals@^2.5.0",
"npm:@preact/signals@^2.4.0",
"npm:preact@^10.27.2",
"npm:vite@^7.2.2"
"npm:vite@^7.2.1"
]
}
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@ -10,12 +10,12 @@ export default function Meow() {
id="muxiepuff"
onClick={() =>
navigator.clipboard.writeText(
'<a href="https://acpi.at"><img src="https://acpi.at/88x31.gif" title="miwa" alt="acpi.at" /></a>',
'<a href="https://acpi.at"><img src="https://acpi.at/88x31.gif" title="favewa" alt="acpi.at" /></a>',
)}
>
<img
src="/88x31.gif"
title="miwa (Click to copy to clipboard!)"
title="favewa (Click to copy to clipboard!)"
alt="acpi.at"
/>
</button>

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,77 +0,0 @@
/**
* Copyright (c) 2025 miwa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { Fm } from "@/components/Fm.tsx";
import { Header } from "@/components/Header.tsx";
import Links from "@/components/Links.tsx";
import ProjectCard from "@/components/ProjectCard.tsx";
import Code from "@/islands/Code.tsx";
import Meow from "@/islands/Meow.tsx";
import "@/assets/home.css";
import Footer from "../components/Footer.tsx";
export default function About() {
return (
<>
<Links selected="about" />
<section id="about">
<h2>About</h2>
<p>
I'm an aspiring electrical engineer with a keen interest in open
access to information and knowledge. My technical work centers on
functional programming, C99, and writing quirky TypeScript code that
explores its more obscure corners and unconventional patterns. I'm
drawn to atypical low-level technologies and have a particular
interest in the x86 and RISC-V ISAs.
</p>
<p>
<i>In a more personal tone...</i>{" "}
Hewwo! I'm Lívia, a 18-year-old girl from Brazil passionate about open
access to information, technology, linguistics, functional
programming, and pretty much anything that involves understanding
technology, human language, or philosophical frameworks. I hope you
find something interesting here, and don't hesitate to reach out if
you feel like it. <span class="highlight">:3</span>
</p>
<p>
When I'm not studying circuits or coding, it's likely that I'm either
exploring linguistics or listening to music. My tastes shift
constantly with my hyperfocus, ranging from indie, shoegaze, and J-Pop
to speedcore and various metal derivatives. I run a FreeBSD server
that hosts this site and various services, serving as my hands-on lab
for systems administration. <span class="highlight">^-^</span>
</p>
<p>
Beyond quirky technology, I <i>really</i>{" "}
like linguistics and philosophy enthusiast. I'm also autistic n' ADHD,
so I might struggle with humour once in a while. I really like
befriending new people and growing as a person every single day!!! If
you've read this far, thanks for stopping by!{" "}
</p>
</section>
<section id="languages">
<h2>languages</h2>
<ul style="text-align-last: left">
<li>
brazilian portuguese <span class="highlight">(native)</span>
</li>
<li>
«all over the place» english <span class="highlight">(C1)</span>
</li>
<li>
latin american spanish <span class="highlight">(A2)</span>
</li>
</ul>
</section>
<section id="trivia">
<h2>trivia</h2>
<ul>
<li>there are no easter eggs up here. go away</li>
</ul>
</section>
<Footer />
</>
);
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@ -10,7 +10,6 @@ import ProjectCard from "@/components/ProjectCard.tsx";
import Code from "@/islands/Code.tsx";
import Meow from "@/islands/Meow.tsx";
import "@/assets/home.css";
import Footer from "../components/Footer.tsx";
export default function Home() {
return (
@ -18,14 +17,16 @@ export default function Home() {
<Links selected="home" />
<Header class="home" />
<section id="about">
<h2>Summary</h2>
<h2>About</h2>
<p>
I'm an aspiring electrical engineer with a keen interest in open
access to information and knowledge. My technical work centers on
functional programming, C99, and writing quirky TypeScript code that
explores its more obscure corners and unconventional patterns. I'm
drawn to atypical low-level technologies and have a particular
interest in the x86 and RISC-V ISAs. <a href="/about">Read more</a>
Advocate for open access to information and knowledge and aspiring
electrical engineer with complementary interests in systems
programming and linguistics.
</p>
<p>
On the side, I maintain a modest FreeBSD server where I self-host this
website and various services. This is nothing particularly impressive,
just a growing curiosity about systems administration.
</p>
</section>
<section id="links">
@ -56,12 +57,12 @@ export default function Home() {
title="Discord"
href="https://discord.com/users/797566974024351745"
>
@rumiwa on Discord
@favewa on Discord
</a>
</li>
<li>
<a title="Telegram" href="https://t.me/lauwawa">
@lauwawa on Telegram
<a title="Telegram" href="https://t.me/favewa">
@favewa on Telegram
</a>
</li>
</ul>
@ -70,8 +71,8 @@ export default function Home() {
<h3>Code</h3>
<ul>
<li>
<a title="GitHub" href="https://github.com/fukkai">
fukkai on GitHub
<a title="GitHub" href="https://github.com/misties">
misties on GitHub
</a>
</li>
<li>
@ -99,10 +100,10 @@ export default function Home() {
<ul>
<li>
<ProjectCard
author="fukkai"
author="favewa"
name="cobweb"
description="a lightweight, tiny web framework for deno tailored for dynamic no-js applications"
url="http://github.com/fukkai/cobweb"
url="http://github.com/misties/cobweb"
languageColor="#3178c6"
languageName="TypeScript"
license="BSD-3-Clause"
@ -110,13 +111,13 @@ export default function Home() {
</li>
<li>
<ProjectCard
author="fukkai"
name="ratazana"
description="minimal implementation of logitech and razer mouse firmware, repurposing their onboard memory as a covert channel for arbitrary data"
url="http://github.com/fukkai/ratazana"
languageColor="#555"
languageName="C"
license="BSD-3-Clause"
author="w"
name="acpi.at"
description="personal website"
url="http://kyu.re/~web"
languageColor="#3178c6"
languageName="TypeScript"
license="AGPL-3.0-or-later"
/>
</li>
<li>
@ -146,7 +147,7 @@ export default function Home() {
<span class="key">WEB</span>
<code class="value">
<a href="https://ko-fi.com/west">west@ko-fi</a>
<a href="https://github.com/sponsors/fukkai">fukkai@github</a>
<a href="https://github.com/sponsors/misties">misties@github</a>
</code>
</div>
<div class="row">
@ -242,7 +243,6 @@ export default function Home() {
</a>
</div>
</section>
<Footer />
</>
);
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@ -7,13 +7,11 @@ import { PageProps } from "fresh";
import { getCachedReports } from "@/utils/atproto.ts";
import Empty from "@/components/Empty.tsx";
import "@/assets/report.css";
import { formatReadingTime } from "../../utils/blog.ts";
import { Head } from "fresh/runtime";
export default function PostPage(props: PageProps) {
const { rkey } = props.params;
const post = getCachedReports().find(
(rep) => rep.rkey === rkey.toLowerCase(),
const post = getCachedReports().find((rep) =>
rep.rkey === rkey.toLowerCase()
);
if (!post) {
@ -22,57 +20,17 @@ export default function PostPage(props: PageProps) {
return (
<>
<Head>
<title>{post.title} - acpi.at</title>
<meta name="title" content={`${post.title} - acpi.at`} />
<meta name="description" content={post.excerpt} />
<meta name="author" content="acpi.at" />
{post.tags && <meta name="keywords" content={post.tags.join(", ")} />}
<meta name="theme-color" content="#a0bdfc" />
<meta
name="theme-color"
media="(prefers-color-scheme: dark)"
content="#1a1a2e"
/>
<meta property="og:type" content="article" />
<link rel="canonical" href={`https://acpi.at/reports/${post.rkey}`} />
<meta name="robots" content="index, follow" />
<meta property="og:type" content="article" />
<meta property="og:site_name" content="acpi.at" />
<meta property="og:title" content={post.title} />
<meta property="og:description" content={post.excerpt} />
<meta property="og:image" content="" />
<meta
property="og:url"
content={`https://acpi.at/reports/${post.rkey}`}
/>
<meta property="article:published_time" content={post.createdAt} />
<meta property="article:author" content="acpi.at" />
{post.tags &&
post.tags.map((tag) => (
<meta key={tag} property="article:tag" content={tag} />
))}
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content={post.title} />
<meta name="twitter:description" content={post.excerpt} />
<meta name="twitter:image" content="" />
</Head>
<a href="/reports"> exit this report</a>
<br />
<article>
<header>
<h1>{post.title}</h1>
<div class="meta">
<time datetime={post.createdAt}>{post.createdAt}</time> ·{" "}
{formatReadingTime(post.readingTime)}
<time datetime={post?.createdAt}>{post?.createdAt}</time>
</div>
<h1>{post.title}</h1>
{post.tags && (
<div class="tags">
{post.tags.map((tag) => (
<span key={tag} class="tag">
{tag}
</span>
))}
{post.tags.map((tag) => <span key={tag} class="tag">{tag}</span>)}
</div>
)}
</header>
@ -80,13 +38,13 @@ export default function PostPage(props: PageProps) {
class="content typewriting"
dangerouslySetInnerHTML={{ __html: post.content }}
/>
<footer>
<a href="/">
You reached the end of the page. It is now safe to turn off your
computer.
</a>
</footer>
</article>
<footer>
<a href="/" style="color: var(--theme-foreground-alt)">
You reached the end of the page. It is now safe to turn off your
computer.
</a>
</footer>
</>
);
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@ -7,51 +7,10 @@ import Reports from "@/components/Reports.tsx";
import Links from "@/components/Links.tsx";
import { getCachedReports } from "@/utils/atproto.ts";
import "@/assets/report.css";
import { Head } from "fresh/runtime";
export default function Page() {
return (
<>
<Head>
<title>$reports - acpi.at</title>
<meta
name="description"
content="Thoughts, ramblings, and occasional coherence. A collection of personal essays on stuff that randomly come across my mind."
/>
<meta
name="keywords"
content="personal blog, essays, mental health, philosophy, linguistics, life writing, reflections"
/>
<meta property="og:type" content="website" />
<meta property="og:title" content="$reports - acpi.at" />
<meta
name="og:description"
content="Thoughts, ramblings, and occasional coherence. A collection of personal essays on stuff that randomly come across my mind."
/>
<meta
name="twitter:description"
content="Thoughts, ramblings, and occasional coherence. A collection of personal essays on stuff that randomly come across my mind."
/>
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="$reports - acpi.at" />
<meta property="og:image" content="https://acpi.at/bnuy.webp" />
<meta property="og:url" content="https://acpi.at/reports" />
<meta property="og:locale" content="en_US" />
<meta name="theme-color" content="#a0bdfc" />
<meta
name="theme-color"
media="(prefers-color-scheme: dark)"
content="#1a1a2e"
/>
<link rel="canonical" href="https://acpi.at/reports" />
<meta name="robots" content="index, follow" />
<link
rel="alternate"
type="application/rss+xml"
title="acpi.at - $reports"
href="https://acpi.at/rss.xml"
/>
</Head>
<Links selected="reports" />
<Reports reports={getCachedReports()} />
</>

View file

@ -1,13 +1,13 @@
#!/usr/bin/env -S deno run --allow-read --allow-write
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { walk } from "https://deno.land/std/fs/walk.ts";
const copyrightHeader = `/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
`;

View file

@ -1,66 +0,0 @@
/**
* Copyright (c) 2025 miwa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#!/usr/bin/env -S deno run --allow-net --allow-write
/**
* Copyright (c) 2025 miwa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { getPosts, type Report } from "../utils/atproto.ts";
function escapeXml(unsafe: string): string {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;");
}
function stripHtml(html: string): string {
return html
.replace(/<[^>]+>/g, " ")
.replace(/\s+/g, " ")
.trim();
}
function generateRSSItem(report: Report): string {
const link = `https://acpi.at/reports/${report.rkey}`;
const description = report.excerpt ||
stripHtml(report.content).substring(0, 200);
return [
` <item>`,
` <title>${escapeXml(report.title)}</title>`,
` <link>${link}</link>`,
` <guid>${link}</guid>`,
` <pubDate>${report.date.toUTCString()}</pubDate>`,
` <description>${escapeXml(description)}</description>`,
` </item>`,
].join("\n");
}
async function generateRSS() {
const reports = await getPosts();
const items = reports.map(generateRSSItem);
const xml = [
`<?xml version="1.0" encoding="UTF-8"?>`,
`<rss version="2.0">`,
` <channel>`,
` <title>$reports - acpi.at</title>`,
` <link>https://acpi.at/reports</link>`,
` <description>thoughts, ramblings, and occasional coherence</description>`,
items.join("\n"),
` </channel>`,
`</rss>`,
].join("\n");
await Deno.writeTextFile("./static/rss.xml", xml);
console.log("done");
}
if (import.meta.main) {
await generateRSS();
}

View file

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>$reports - acpi.at</title>
<link>https://acpi.at/reports</link>
<description>thoughts, ramblings, and occasional coherence</description>
<item>
<title>When awareness feels like a burden</title>
<link>https://acpi.at/reports/3m4yhdcgqr425</link>
<guid>https://acpi.at/reports/3m4yhdcgqr425</guid>
<pubDate>Thu, 06 Nov 2025 23:54:23 GMT</pubDate>
<description>The worst days of my life happen to be the ones where I am overly aware about my surroundings and problems.</description>
</item>
<item>
<title>Why Brazilian Portuguese speakers struggle to understand European Portuguese</title>
<link>https://acpi.at/reports/3m4yszxlivv25</link>
<guid>https://acpi.at/reports/3m4yszxlivv25</guid>
<pubDate>Sat, 16 Aug 2025 00:38:02 GMT</pubDate>
<description>EP speakers lowkey be like: &apos;ixtou a apnhr murangjs pah&apos;</description>
</item>
<item>
<title>Echoes of thought in a world wired to produce</title>
<link>https://acpi.at/reports/3m4yrn7md2k25</link>
<guid>https://acpi.at/reports/3m4yrn7md2k25</guid>
<pubDate>Tue, 20 May 2025 00:02:53 GMT</pubDate>
<description>For the first time in a few months, I had some time alone to process my thoughts.</description>
</item>
</channel>
</rss>

View file

@ -1,9 +1,8 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { calculateReadingTime, ReadingTimeResult } from "./blog.ts";
import { withInterval } from "./temp.ts";
export interface Report {
@ -15,7 +14,6 @@ export interface Report {
createdAt: string;
tags?: string[];
visibility: string;
readingTime: ReadingTimeResult;
date: Date;
}
@ -61,7 +59,6 @@ export async function getPosts(cursor?: string): Promise<Report[]> {
...value,
rkey: rkey(uri),
date: new Date(value.createdAt),
readingTime: value.content ? calculateReadingTime(value.content) : 1,
createdAt: new Date(value.createdAt).toISOString().slice(0, 10).replace(
/-/g,
".",
@ -85,9 +82,6 @@ export async function retrieveReport(rkey: string): Promise<Report | null> {
return {
...response.value,
readingTime: response.value.content
? calculateReadingTime(response.value.content)
: 1,
cid: response.cid,
rkey,
} as Report;

View file

@ -1,68 +0,0 @@
/**
* Copyright (c) 2025 miwa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
export interface ReadingTimeOptions {
wordsPerMinute?: number;
imageTime?: number;
codeBlockTime?: number;
chineseKoreanReadingSpeed?: number;
}
export interface ReadingTimeResult {
minutes: number;
words: number;
images: number;
codeBlocks: number;
}
export function formatReadingTime(input: ReadingTimeResult) {
return `${input.words} words · ${
input.images ? `${input.images} images · ` : ""
}${
input.codeBlocks ? `${input.codeBlocks} code blocks · ` : ""
}${input.minutes} minutes`;
}
export function calculateReadingTime(
input: string,
options: ReadingTimeOptions = {},
): ReadingTimeResult {
const {
wordsPerMinute = 200,
imageTime = 12,
codeBlockTime = 15,
chineseKoreanReadingSpeed = 260,
} = options;
let images = 0, preBlocks = 0, codeBlocks = 0;
const text = input
.replace(/<img[^>]*>/gi, () => (images++, ""))
.replace(/<pre[^>]*>[\s\S]*?<\/pre>/gi, () => (preBlocks++, ""))
.replace(/<code[^>]*>[\s\S]*?<\/code>/gi, () => (codeBlocks++, ""));
const cjkRegex = /[\u4E00-\u9FFF\u3040-\u309F\u30A0-\u30FF\uAC00-\uD7AF]/g;
const cjkMatches = text.match(cjkRegex);
const cjkCharacters = cjkMatches?.length ?? 0;
const textWithoutCJK = cjkCharacters ? text.replace(cjkRegex, " ") : text;
const words = textWithoutCJK.trim().split(/\s+/).reduce(
(n, w) => n + (w && /\w/.test(w) ? 1 : 0),
0,
);
const totalMinutes = Math.ceil(
words / wordsPerMinute +
cjkCharacters / chineseKoreanReadingSpeed +
(images * imageTime + (preBlocks + codeBlocks) * codeBlockTime) / 60,
);
return {
minutes: Math.max(totalMinutes || 2, 2),
words: words + cjkCharacters,
images,
codeBlocks: preBlocks + codeBlocks,
};
}

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -1,5 +1,5 @@
/**
* Copyright (c) 2025 miwa
* Copyright (c) 2025 favewa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/