Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 161 additions & 13 deletions bun.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
"postinstall": "wrangler types"
},
"dependencies": {
"@astrojs/cloudflare": "13.7.0",
"@astrojs/cloudflare": "14.0.0",
"@astrojs/rss": "4.0.18",
"@astrojs/sitemap": "3.7.3",
"@astrojs/svelte": "8.1.2",
"@astrojs/svelte": "9.0.0",
"@fontsource/poppins": "5.2.7",
"@tailwindcss/vite": "4.3.1",
"astro": "6.4.8",
"astro": "7.0.1",
"astro-icon": "1.1.5",
"clsx": "2.1.1",
"remove-markdown": "0.6.4",
Expand All @@ -34,7 +34,7 @@
"typescript": "6.0.3"
},
"devDependencies": {
"@astrojs/mdx": "6.0.3",
"@astrojs/mdx": "7.0.0",
"@tailwindcss/typography": "0.5.20",
"@types/node": "25.9.3",
"@typescript-eslint/eslint-plugin": "8.61.1",
Expand Down
6 changes: 0 additions & 6 deletions src/assets/data/team.json
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,6 @@
"discord": "malfrador",
"github": "Malfrador"
},
{
"name": "Nacio",
"avatar": "https://avatars.githubusercontent.com/u/41339226?v=4",
"discord": "nacio.",
"github": "Nacioszeczek"
},
{
"name": "Ollie",
"avatar": "https://avatars.githubusercontent.com/u/69084614?v=4",
Expand Down
2 changes: 1 addition & 1 deletion src/components/data/RemoteImageWrapper.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { getImage, imageConfig, type LocalImageProps, type RemoteImageProps } from "astro:assets";
import type { HTMLAttributes } from "astro/types";

import fallbackImage from "@/assets/brand/paper.svg";
import fallbackImage from "@/assets/brand/paper.svg?url";
import { inferRemoteSize } from "astro/assets/utils";

type Props = LocalImageProps | RemoteImageProps;
Expand Down
95 changes: 76 additions & 19 deletions src/components/data/UserImage.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,124 @@
import RemoteResponsiveImageWrapper from "@/components/data/RemoteResponsiveImageWrapper.astro";

interface Props {
avatarUrl: string;
avatarUrl?: string | null;
name: string;
link?: string;
class?: string;
}

const { avatarUrl, name, link, class: extra } = Astro.props;
const Tag = link ? "a" : "div";
const initial = (name?.trim?.()[0] ?? "?").toUpperCase();
const hasAvatar = Boolean(avatarUrl?.trim());
---

<Tag
role={link ? "button" : undefined}
class={`user-image relative flex aspect-square items-center justify-center overflow-hidden rounded-full bg-gray-600 font-bold text-white uppercase transition-transform hover:scale-103 active:translate-y-[0.5px] shadow-md active:shadow-none ${extra ?? ""}`}
class={`not-prose user-image relative flex aspect-square items-center justify-center overflow-hidden rounded-full transition-transform hover:scale-103 active:translate-y-[0.5px] shadow-md active:shadow-none ${extra ?? ""}`}
href={link}
rel={link && "noreferrer"}
target={link && "_blank"}
rel={link ? "noreferrer" : undefined}
target={link ? "_blank" : undefined}
aria-label={name}
title={name}
>
<span class="initial pointer-events-none select-none">{initial}</span>
<span class={`initial pointer-events-none select-none ${hasAvatar ? "hidden" : ""}`}>
{initial}
</span>

{
avatarUrl && (
hasAvatar && (
<RemoteResponsiveImageWrapper
alt={`${name}'s avatar`}
src={avatarUrl}
src={avatarUrl!}
width={80}
height={80}
format="webp"
layout="none"
loading="lazy"
decoding="async"
class="pointer-events-none absolute h-full w-full object-cover"
class="pointer-events-none absolute inset-0 h-full w-full rounded-full object-cover"
/>
)
}
</Tag>

<style>
.user-image img.invalid,
.user-image img[data-fallback="true"] {
display: none !important;
}

.user-image {
will-change: transform;
transform: translateZ(0);
backface-visibility: hidden;
contain: paint;
}

.user-image .initial {

Check warning on line 55 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image .initial`

Check warning on line 55 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image .initial`
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 9999px;
background: #4b5563;
color: white;
font-weight: 700;
text-transform: uppercase;
}

.user-image .initial.hidden {

Check warning on line 68 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image .initial.hidden`

Check warning on line 68 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image .initial.hidden`
display: none;
}

.user-image img {

Check warning on line 72 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image img`

Check warning on line 72 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image img`
display: block;
border-radius: 9999px;
}

.user-image img.invalid,

Check warning on line 77 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image img[data-fallback="true"]`

Check warning on line 77 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image img.invalid`

Check warning on line 77 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image img[data-fallback="true"]`

Check warning on line 77 in src/components/data/UserImage.astro

View workflow job for this annotation

GitHub Actions / lint

Unused CSS selector `.user-image img.invalid`
.user-image img[data-fallback="true"] {
display: none !important;
}
</style>

<script>
const root = document.currentScript?.parentElement;
const img = root?.querySelector("img");
if (img) {
if (!img.complete || img.naturalWidth === 0) {
img.classList.add("invalid");
function showInitialFallback(root: Element): void {
const initial = root.querySelector(".initial");

if (initial instanceof HTMLElement) {
initial.classList.remove("hidden");
}
}

function hideInitialFallback(root: Element): void {
const initial = root.querySelector(".initial");

if (initial instanceof HTMLElement) {
initial.classList.add("hidden");
}
}

for (const root of document.querySelectorAll(".user-image")) {
const img = root.querySelector("img");

if (!(img instanceof HTMLImageElement)) {
continue;
}

const imageAlreadyFailed =
img.classList.contains("invalid") || img.dataset.fallback === "true" || (img.complete && img.naturalWidth === 0);

if (imageAlreadyFailed) {
showInitialFallback(root);
}
img.addEventListener("error", () => img.classList.add("invalid"));

img.addEventListener("load", () => {
if (!img.classList.contains("invalid") && img.dataset.fallback !== "true" && img.naturalWidth > 0) {
hideInitialFallback(root);
}
});

img.addEventListener("error", () => {
img.classList.add("invalid");
showInitialFallback(root);
});
}
</script>
18 changes: 8 additions & 10 deletions src/pages/contribute.astro
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
---
import { Image } from "astro:assets";

import Button from "@/components/input/Button.astro";
import Layout from "@/layouts/Layout.astro";

import ChattingIllustration from "@/assets/illustrations/undraw/chatting.svg";
import CodeReviewIllustration from "@/assets/illustrations/undraw/code-review.svg";
import KnowledgeIllustration from "@/assets/illustrations/undraw/knowledge.svg";
import SavingsIllustration from "@/assets/illustrations/undraw/savings.svg";
import ChattingIllustration from "@/assets/illustrations/undraw/chatting.svg?url";
import CodeReviewIllustration from "@/assets/illustrations/undraw/code-review.svg?url";
import KnowledgeIllustration from "@/assets/illustrations/undraw/knowledge.svg?url";
import SavingsIllustration from "@/assets/illustrations/undraw/savings.svg?url";
---

<Layout
Expand Down Expand Up @@ -40,7 +38,7 @@ import SavingsIllustration from "@/assets/illustrations/undraw/savings.svg";
</div>
</div>
<div class="flex w-full justify-start lg:flex-1 lg:justify-end">
<Image src={SavingsIllustration} alt={"Savings Illustration"} class="max-h-32 lg:max-h-none lg:max-w-[18rem]" />
<img src={SavingsIllustration} alt={"Savings Illustration"} class="max-h-32 lg:max-h-none lg:max-w-[18rem]" />
</div>
</section>
<section id="code" class="mx-auto mt-12 flex max-w-7xl flex-col-reverse items-center gap-8 px-4 py-4 lg:flex-row">
Expand All @@ -54,7 +52,7 @@ import SavingsIllustration from "@/assets/illustrations/undraw/savings.svg";
</div>
</div>
<div class="flex w-full justify-start lg:flex-1 lg:justify-end">
<Image src={CodeReviewIllustration} alt={"Code Review Illustration"} class="max-h-32 lg:max-h-none lg:max-w-[18rem]" />
<img src={CodeReviewIllustration} alt={"Code Review Illustration"} class="max-h-32 lg:max-h-none lg:max-w-[18rem]" />
</div>
</section>
<section id="support" class="mx-auto mt-12 flex max-w-7xl flex-col-reverse items-center gap-8 px-4 py-4 lg:flex-row">
Expand All @@ -69,7 +67,7 @@ import SavingsIllustration from "@/assets/illustrations/undraw/savings.svg";
</div>
</div>
<div class="flex w-full justify-start lg:flex-1 lg:justify-end">
<Image src={ChattingIllustration} alt={"Chatting Illustration"} class="max-h-32 lg:max-h-none lg:max-w-[18rem]" />
<img src={ChattingIllustration} alt={"Chatting Illustration"} class="max-h-32 lg:max-h-none lg:max-w-[18rem]" />
</div>
</section>
<section id="documentation" class="mx-auto mt-12 flex max-w-7xl flex-col-reverse items-center gap-8 px-4 py-4 lg:flex-row">
Expand All @@ -84,7 +82,7 @@ import SavingsIllustration from "@/assets/illustrations/undraw/savings.svg";
</div>
</div>
<div class="flex w-full justify-start lg:flex-1 lg:justify-end">
<Image src={KnowledgeIllustration} alt={"Knowledge Illustration"} class="max-h-32 lg:max-h-none lg:max-w-[18rem]" />
<img src={KnowledgeIllustration} alt={"Knowledge Illustration"} class="max-h-32 lg:max-h-none lg:max-w-[18rem]" />
</div>
</section>
</Layout>
6 changes: 0 additions & 6 deletions src/pages/news/[id].astro
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,3 @@ const excerpt = truncateForPreview(post.body ?? "", 120);
</article>
</section>
</Layout>

<style scoped>
@view-transition {
navigation: auto;
}
</style>
7 changes: 0 additions & 7 deletions src/pages/news/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { getCollection } from "astro:content";
import { formatDateLong } from "@/utils/time";
import { countWords, minutesToRead, truncateForPreview } from "@/utils/content";
import { Icon } from "astro-icon/components";
import IconButton from "@/components/IconButton.astro";

const posts = (await getCollection("posts")).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());

Expand Down Expand Up @@ -67,9 +66,3 @@ const postsWithMeta = posts.map((p) => {
</div>
</div>
</Layout>

<style scoped>
@view-transition {
navigation: auto;
}
</style>
3 changes: 2 additions & 1 deletion src/pages/team.astro
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ const contributors = await fetchContributors();
{team.members.map((member) => (
<article class="rounded-md border border-gray-300 p-4 transition-shadow hover:shadow-md dark:border-gray-700">
<div class="flex flex-row gap-6">
<div class="relative h-20 w-20 overflow-clip rounded-md bg-gray-600">
<div class="relative h-20 w-20 overflow-clip rounded-md">
{member.avatar && (
<RemoteResponsiveImageWrapper
alt={`${member.name}'s avatar`}
src={member.avatar}
width={80}
height={80}
format="webp"
class="object-cover"
/>
)}
Expand Down
6 changes: 4 additions & 2 deletions worker-configuration.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable */
// Generated by Wrangler by running `wrangler types` (hash: ad94e3d4f0b09e36a00ce199c5a61442)
// Runtime types generated with workerd@1.20260611.1 2025-10-17 nodejs_compat
// Runtime types generated with workerd@1.20260611.1 2026-02-19 disable_nodejs_process_v2,nodejs_compat
interface __BaseEnv_Env {
WEBSITE_CACHE: KVNamespace;
ASSETS: Fetcher;
Expand Down Expand Up @@ -433,6 +433,7 @@ interface TestController {
interface ExecutionContext<Props = unknown> {
waitUntil(promise: Promise<any>): void;
passThroughOnException(): void;
readonly exports: Cloudflare.Exports;
readonly props: Props;
cache?: CacheContext;
tracing?: Tracing;
Expand Down Expand Up @@ -534,6 +535,7 @@ interface DurableObjectClass<_T extends Rpc.DurableObjectBranded | undefined = u
}
interface DurableObjectState<Props = unknown> {
waitUntil(promise: Promise<any>): void;
readonly exports: Cloudflare.Exports;
readonly props: Props;
readonly id: DurableObjectId;
readonly storage: DurableObjectStorage;
Expand Down Expand Up @@ -1650,7 +1652,7 @@ declare class Headers {
value: string
]>;
}
type BodyInit = ReadableStream<Uint8Array> | string | ArrayBuffer | ArrayBufferView | Blob | URLSearchParams | FormData;
type BodyInit = ReadableStream<Uint8Array> | string | ArrayBuffer | ArrayBufferView | Blob | URLSearchParams | FormData | Iterable<ArrayBuffer | ArrayBufferView> | AsyncIterable<ArrayBuffer | ArrayBufferView>;
declare abstract class Body {
/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/body) */
get body(): ReadableStream | null;
Expand Down
4 changes: 2 additions & 2 deletions wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"$schema": "node_modules/wrangler/config-schema.json",
"name": "papermc-website",
"main": "./src/worker.ts",
"compatibility_date": "2025-10-17",
"compatibility_flags": ["nodejs_compat"],
"compatibility_date": "2026-02-19",
"compatibility_flags": ["nodejs_compat", "disable_nodejs_process_v2"],
"assets": {
"binding": "ASSETS",
"directory": "./dist",
Expand Down
Loading