Improve frontpage performance (#929)

* initial commit

* merge with origin/main

* fix package-lock.json

* fix tiptap mentions

* remove flutter

* update package-lock.json

* disable tailwindcss/typography until https://github.com/tailwindlabs/tailwindcss/issues/19946 is fixed

* reactivate tailwind/typography after fix

---------

Co-authored-by: Christian Beutel <>
Co-authored-by: slothful-vassal <89943360+slothful-vassal@users.noreply.github.com>
This commit is contained in:
Flomp
2026-04-22 09:04:53 +02:00
committed by GitHub
parent c9256aeb29
commit 345452e720
19 changed files with 4133 additions and 959 deletions

View File

@@ -0,0 +1,59 @@
<!--
Auto-generated by: https://github.com/threlte/threlte/tree/main/packages/gltf
Command: npx @threlte/gltf@3.0.7 ../../../../static/models/marker.glb -T
-->
<script lang="ts">
import { T } from "@threlte/core";
import { useGltf, useDraco } from "@threlte/extras";
import type { Snippet } from "svelte";
interface Props {
fallback?: Snippet;
error?: Snippet<[any]>;
children?: Snippet<[any]>;
[key: string]: any;
}
let {
fallback,
error,
children,
ref = $bindable(),
...props
}: Props = $props();
const gltf = useGltf("/models/marker.glb", { dracoLoader: useDraco() });
</script>
<T.Group bind:ref dispose={false} {...props}>
{#await gltf}
{@render fallback?.()}
{:then gltf}
<T.Group>
<T.Mesh
geometry={gltf.nodes["Node-Mesh003"].geometry}
material={gltf.materials.mat8}
/>
<T.Mesh
geometry={gltf.nodes["Node-Mesh003_1"].geometry}
material={gltf.materials.mat23}
>
<T.PointLight
position={[-1, 0.8, 0]}
color="#ffffff"
intensity={3}
></T.PointLight>
<T.PointLight
position={[1, 0.8, 0]}
color="#ffffff"
intensity={3}
></T.PointLight></T.Mesh
>
</T.Group>
{:catch err}
{@render error?.({ error: err })}
{/await}
{@render children?.({ ref })}
</T.Group>

View File

@@ -0,0 +1,42 @@
<!--
Auto-generated by: https://github.com/threlte/threlte/tree/main/packages/gltf
Command: npx @threlte/gltf@3.0.7 ../../../../static/models/moon.glb -T
-->
<script lang="ts">
import { T } from "@threlte/core";
import { useGltf, useDraco } from "@threlte/extras";
import type { Snippet } from "svelte";
interface Props {
fallback?: Snippet;
error?: Snippet<[any]>;
children?: Snippet<[any]>;
[key: string]: any;
}
let {
fallback,
error,
children,
ref = $bindable(),
...props
}: Props = $props();
const gltf = useGltf("/models/moon.glb", { dracoLoader: useDraco() });
</script>
<T.Group bind:ref dispose={false} {...props}>
{#await gltf}
{@render fallback?.()}
{:then gltf}
<T.Mesh geometry={gltf.nodes.Moon.geometry} material={gltf.materials.DD9944}
><T.PointLight position={[0.5, 5, 0.5]} color="#a2cbf5" intensity={7}
></T.PointLight>
</T.Mesh>
{:catch err}
{@render error?.({ error: err })}
{/await}
{@render children?.({ ref })}
</T.Group>

View File

@@ -0,0 +1,117 @@
<script lang="ts">
import { theme } from "$lib/stores/theme_store";
import { T, useTask } from "@threlte/core";
import { backInOut } from "svelte/easing";
import { Tween } from "svelte/motion";
import Marker from "./marker.svelte";
import Moon from "./moon.svelte";
import Sun from "./sun.svelte";
import { useViewport } from "@threlte/extras";
import { innerHeight, innerWidth } from "svelte/reactivity/window";
const viewport = useViewport();
const canvasHeight = $derived((innerHeight.current ?? 0) - 112);
const canvasWidth = $derived((innerWidth.current ?? 0) * 0.6);
const dioramaImageMaxHeight = 0.75;
const imgWidth = $derived(
Math.min(
((dioramaImageMaxHeight * canvasHeight) / 9) * 16,
canvasWidth,
),
);
const imgHeight = $derived((imgWidth / 16) * 9);
const imgWorldWidth = $derived((imgWidth / canvasWidth) * $viewport.width);
const imgWorldHeight = $derived(
(imgHeight / canvasHeight) * $viewport.height,
);
const peak1PositionRelativeToImage = [-0.195, 0.7];
const peak1Position = $derived([
peak1PositionRelativeToImage[0] * (imgWorldWidth / 2),
peak1PositionRelativeToImage[1] * (imgWorldHeight / 2),
20,
]);
const peak2PositionRelativeToImage = [0.05, 1];
const peak2Position = $derived([
peak2PositionRelativeToImage[0] * (imgWorldWidth / 2),
peak2PositionRelativeToImage[1] * (imgWorldHeight / 2),
20,
]);
const peak3PositionRelativeToImage = [0.55, 0.37];
const peak3Position = $derived([
peak3PositionRelativeToImage[0] * (imgWorldWidth / 2),
peak3PositionRelativeToImage[1] * (imgWorldHeight / 2),
20,
]);
const sunUpPosition = $derived(($viewport.height / 2) * 0.6);
let rotation = $state(0);
useTask((delta) => {
rotation += delta / 2;
});
const sunZPosition = new Tween($theme == "light" ? sunUpPosition : 0, {
duration: 1000,
easing: backInOut,
});
$effect(() => {
sunZPosition.set($theme == "light" ? sunUpPosition : 0);
});
const sunLightIntensity = new Tween($theme == "light" ? 4 : 0, {
duration: 400,
});
$effect(() => {
sunLightIntensity.set($theme == "light" ? 4 : 0);
});
const moonZPosition = new Tween($theme == "dark" ? sunUpPosition : 0, {
duration: 1000,
easing: backInOut,
});
$effect(() => {
moonZPosition.set($theme == "dark" ? sunUpPosition : 0);
});
</script>
<T.OrthographicCamera
makeDefault
zoom={14}
position={[0, 0, 30]}
oncreate={(c) => {
c.lookAt(0, 0, 0);
}}
/>
<!-- <Earth {rotation}></Earth> -->
<!-- <Mountain {rotation}></Mountain> -->
<Sun
position={[7.5, sunZPosition.current, 0]}
rotation={[0, 0, 0]}
scale={0.11}
lightIntesity={sunLightIntensity.current}
/>
<Moon
position={[-5, moonZPosition.current, 0]}
rotation={[0, -Math.PI / 2, 0]}
scale={0.53}
></Moon>
<Marker position={peak1Position} rotation={[0, rotation, 0]} scale={1}></Marker>
<Marker position={peak2Position} rotation={[0, rotation - 1, 0]} scale={1}
></Marker>
<Marker
position={peak3Position}
rotation={[0, rotation + 1, 0]}
scale={1}
></Marker>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
<script lang="ts">
import starLayers from "./star_postions.json";
</script>
<div class="stars-wrapper">
{#each starLayers as layer, i}
<svg
class="stars layer-{i}"
width="100%"
height="100%"
preserveAspectRatio="none"
>
{#each layer as star}
<circle cx="{star.x}%" cy="{star.y}%" r={star.r} fill="white" />
{/each}
</svg>
{/each}
<svg class="extras" width="100%" height="100%" preserveAspectRatio="none">
<defs>
<radialGradient id="comet-gradient" cx="0" cy=".5" r="0.5">
<stop offset="0%" stop-color="rgba(255,255,255,.8)" />
<stop offset="100%" stop-color="rgba(255,255,255,0)" />
</radialGradient>
</defs>
<g transform="rotate(-135)">
<ellipse
class="comet comet-a"
fill="url(#comet-gradient)"
cx="0"
cy="0"
rx="150"
ry="2"
/>
</g>
<g transform="rotate(20)">
<ellipse
class="comet comet-b"
fill="url(#comet-gradient)"
cx="100%"
cy="0"
rx="150"
ry="2"
/>
</g>
<g transform="rotate(300)">
<ellipse
class="comet comet-c"
fill="url(#comet-gradient)"
cx="40%"
cy="100%"
rx="150"
ry="2"
/>
</g>
</svg>
</div>
<style>
.stars-wrapper {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 0;
transition:
opacity 1.5s ease-in-out,
visibility 1.5s;
will-change: opacity;
}
.visible {
opacity: 1;
visibility: visible;
}
.hidden {
opacity: 0;
visibility: hidden;
}
.stars {
position: absolute;
inset: 0;
/* Force GPU to handle the transparency fade */
transform: translateZ(0);
}
/* Your working twinkle animation from before */
.layer-0 {
animation: twinkle 4s infinite -0s;
}
.layer-1 {
animation: twinkle 4s infinite -1.3s;
}
.layer-2 {
animation: twinkle 4s infinite -2.6s;
}
@keyframes twinkle {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
.comet {
animation: comet 10s linear infinite;
}
@keyframes comet {
0% {
transform: translateX(0);
opacity: 0;
}
1% {
opacity: 1;
}
20% {
transform: translateX(-2000px);
opacity: 0;
}
100% {
transform: translateX(-2000px);
opacity: 0;
}
}
.comet-b {
animation-delay: -3.3s;
}
.comet-c {
animation-delay: -5s;
}
</style>

View File

@@ -0,0 +1,72 @@
<!--
Auto-generated by: https://github.com/threlte/threlte/tree/main/packages/gltf
Command: npx @threlte/gltf@3.0.7 ../../../../static/models/sun.glb -T
-->
<script lang="ts">
import { T } from "@threlte/core";
import { useDraco, useGltf } from "@threlte/extras";
import type { Snippet } from "svelte";
interface Props {
lightIntesity?: number;
fallback?: Snippet;
error?: Snippet<[any]>;
children?: Snippet<[any]>;
[key: string]: any;
}
let {
lightIntesity = 7,
fallback,
error,
children,
ref = $bindable(),
...props
}: Props = $props();
const gltf = useGltf("/models/sun.glb", { dracoLoader: useDraco() });
</script>
<T.Group bind:ref dispose={false} {...props}>
{#await gltf}
{@render fallback?.()}
{:then gltf}
<T.Mesh
geometry={gltf.nodes.GeoSphere003_1.geometry}
material={gltf.materials._Sol02___Default}
/>
<T.Mesh
geometry={gltf.nodes.GeoSphere003_1_1.geometry}
material={gltf.materials._Sol01___Default}
></T.Mesh>
<T.SpotLight
decay={0}
position={[20, 45, 80]}
target={ref}
intensity={lightIntesity}
></T.SpotLight>
<T.SpotLight
decay={0}
position={[0, 65, 80]}
target={ref}
intensity={lightIntesity}
></T.SpotLight>
<T.SpotLight
decay={0}
position={[-20, 45, 80]}
target={ref}
intensity={lightIntesity}
></T.SpotLight>
<T.SpotLight
decay={0}
position={[0, 25, 80]}
target={ref}
intensity={lightIntesity}
></T.SpotLight>
{:catch err}
{@render error?.({ error: err })}
{/await}
{@render children?.({ ref })}
</T.Group>

View File

@@ -91,6 +91,7 @@
options.HTMLAttributes,
),
options.renderText?.({
suggestion: {...options.suggestion, editor: editor!},
options: options,
node,
}),

View File

@@ -1,61 +0,0 @@
<script lang="ts">
import { theme } from "$lib/stores/theme_store";
import { T, useTask } from "@threlte/core";
import { onMount } from "svelte";
import { Tween } from "svelte/motion";
import * as THREE from "three";
import Mountain from "./mountain.svelte";
let rotation = $state(0);
useTask((delta) => {
rotation += delta / 2;
});
const ambientIntensity = new Tween($theme == "light" ? 3 : 0, {
duration: 500,
});
let ambientColor = $derived($theme == "light" ? "#ffffff" : "#4c7fe6");
$effect(() => {
ambientIntensity.set($theme == "light" ? 3 : 0.1);
});
let starsGeometry: THREE.BufferGeometry | undefined = $state();
let starsMaterial: THREE.PointsMaterial | undefined = $state();
onMount(() => {
const stars = new Array(0);
for (var i = 0; i < 500; i++) {
let x = THREE.MathUtils.randFloatSpread(500);
let y = THREE.MathUtils.randFloatSpread(500);
let z = THREE.MathUtils.randFloatSpread(500);
stars.push(x, y, z);
}
starsGeometry = new THREE.BufferGeometry();
starsGeometry.setAttribute(
"position",
new THREE.Float32BufferAttribute(stars, 3),
);
starsMaterial = new THREE.PointsMaterial({ color: 0xffffff });
});
</script>
<T.PerspectiveCamera
makeDefault
position={[35.5, 28, 35.5]}
oncreate={(c) => {
c.lookAt(-17, 0, 12);
}}
/>
{#if starsGeometry && starsMaterial}
<T.Points geometry={starsGeometry} material={starsMaterial}></T.Points>
{/if}
<!-- <Earth {rotation}></Earth> -->
<Mountain {rotation}></Mountain>
<T.HemisphereLight
skyColor={ambientColor}
groundColor="#242734"
intensity={ambientIntensity.current}
/>