Skip to content
Merged
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
11 changes: 11 additions & 0 deletions website/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import tailwindcss from "@tailwindcss/vite";
import sitemap from "@astrojs/sitemap";
import react from "@astrojs/react";
import rehypeExternalLinks from "./src/utils/rehype-external-links.ts";
import playformCompress from "@playform/compress";

const SITE_BASE_URL = process.env.SITE_BASE_URL || "https://www.quantus.com";
const DEFAULT_LOCALE = "en-US";
Expand Down Expand Up @@ -32,14 +33,23 @@ const LOCALES_MAP = {

// https://astro.build/config
export default defineConfig({
build: {
inlineStylesheets: "always",
},
vite: {
// @ts-ignore
plugins: [tailwindcss()],
build: {
cssMinify: true,
},
},
site: SITE_BASE_URL,
markdown: {
rehypePlugins: [rehypeExternalLinks],
},
image: {
domains: ["i.ytimg.com"],
},
integrations: [
sitemap({
changefreq: "monthly",
Expand Down Expand Up @@ -71,5 +81,6 @@ export default defineConfig({
},
}),
react(),
playformCompress(),
],
});
87 changes: 77 additions & 10 deletions website/bun.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@fontsource/inter": "^5.2.6",
"@fontsource/prompt": "^5.2.6",
"@lucide/astro": "^0.541.0",
"@playform/compress": "^0.2.1",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.3",
"@tailwindcss/vite": "^4.1.12",
Expand Down
71 changes: 70 additions & 1 deletion website/public/_headers
Original file line number Diff line number Diff line change
@@ -1,2 +1,71 @@
/.well-known/*
Content-Type: application/json
Content-Type: application/json

# Cache static assets with long cache lifetimes
# Font files - cache for 1 year (immutable)
/_astro/*.woff2
Cache-Control: public, max-age=31536000, immutable
/_astro/*.woff
Cache-Control: public, max-age=31536000, immutable
/_astro/*.ttf
Cache-Control: public, max-age=31536000, immutable
/_astro/*.otf
Cache-Control: public, max-age=31536000, immutable
*.woff2
Cache-Control: public, max-age=31536000, immutable
*.woff
Cache-Control: public, max-age=31536000, immutable
*.ttf
Cache-Control: public, max-age=31536000, immutable
*.otf
Cache-Control: public, max-age=31536000, immutable

# CSS and JS files with hashes - cache for 1 year (immutable)
/_astro/*.css
Cache-Control: public, max-age=31536000, immutable
/_astro/*.js
Cache-Control: public, max-age=31536000, immutable

# Images - cache for 1 year (immutable)
/_astro/*.jpg
Cache-Control: public, max-age=31536000, immutable
/_astro/*.jpeg
Cache-Control: public, max-age=31536000, immutable
/_astro/*.png
Cache-Control: public, max-age=31536000, immutable
/_astro/*.webp
Cache-Control: public, max-age=31536000, immutable
/_astro/*.avif
Cache-Control: public, max-age=31536000, immutable
/_astro/*.svg
Cache-Control: public, max-age=31536000, immutable
/_astro/*.gif
Cache-Control: public, max-age=31536000, immutable

# Public folder images and assets - cache for 1 year
/*.jpg
Cache-Control: public, max-age=31536000, immutable
/*.jpeg
Cache-Control: public, max-age=31536000, immutable
/*.png
Cache-Control: public, max-age=31536000, immutable
/*.webp
Cache-Control: public, max-age=31536000, immutable
/*.avif
Cache-Control: public, max-age=31536000, immutable
/*.svg
Cache-Control: public, max-age=31536000, immutable
/*.gif
Cache-Control: public, max-age=31536000, immutable
/*.ico
Cache-Control: public, max-age=31536000, immutable

# Other static assets in _astro (catch-all for any other file types)
/_astro/*
Cache-Control: public, max-age=31536000, immutable

# HTML files - short cache with revalidation
/*.html
Cache-Control: public, max-age=0, must-revalidate
/index.html
Cache-Control: public, max-age=0, must-revalidate
10 changes: 10 additions & 0 deletions website/src/components/features/blog/BlogList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ export const BlogList: React.FC<Props> = ({
src={featuredPost.data.heroImage}
alt={featuredPost.data.heroAlt || featuredPost.data.title}
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
loading="eager"
decoding="async"
width="800"
height="450"
fetchPriority="high"
/>
</a>
)}
Expand Down Expand Up @@ -194,6 +199,11 @@ export const BlogList: React.FC<Props> = ({
src={post.data.heroImage}
alt={post.data.heroAlt || post.data.title}
className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
loading="lazy"
decoding="async"
width="800"
height="450"
fetchPriority="low"
/>
</div>
)}
Expand Down
3 changes: 3 additions & 0 deletions website/src/components/features/blog/BlogPost.astro
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ const articleSchema: WithContext<Article> = {
src={heroImage}
alt={heroAlt || title}
class="mb-8 w-full rounded-xl object-cover"
loading="eager"
decoding="async"
fetchpriority="high"
/>
)
}
Expand Down
9 changes: 7 additions & 2 deletions website/src/components/features/blog/Card.astro
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ const formattedDate = pubDate.toLocaleDateString(currentLocale, {
src={heroImage}
alt={heroAlt || title}
class="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
loading="lazy"
decoding="async"
width="800"
height="450"
fetchpriority="low"
/>
</div>
)
Expand All @@ -65,9 +70,9 @@ const formattedDate = pubDate.toLocaleDateString(currentLocale, {
)
}
</div>
<h3 class="group-hover:text-primary mb-2 text-xl font-bold text-white">
<h2 class="group-hover:text-primary mb-2 text-xl font-bold text-white">
{title}
</h3>
</h2>
<p class="text-gray-300">
{description}
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,46 @@
import SiteSocials from "@/components/ui/SiteSocials.astro";
import { PlayIcon } from "@lucide/astro";
import { createTranslator, getLocaleFromUrl } from "@/utils/i18n";
import { Image } from "astro:assets";

const locale = getLocaleFromUrl(Astro.url.pathname);
const t = await createTranslator(locale);

const VIDEO_ID = "ZoT5cdMoMPA";
const THUMBNAIL_URL = `https://i.ytimg.com/vi/${VIDEO_ID}/sddefault.jpg`;
---

<section
class="max-w-video-introduction mx-auto flex flex-col lg:flex-row lg:gap-7 lg:px-[114px] lg:pt-[120px] lg:pb-[80px]"
>
<div
class="lg:rounded-quantus relative flex aspect-video size-full flex-1 flex-col items-center justify-center overflow-hidden bg-(image:--color-video-player) lg:order-2"
id="lazy-video-container"
class="lg:rounded-quantus relative flex aspect-video size-full flex-1 flex-col items-center justify-center overflow-hidden bg-(image:--color-video-player) transition-opacity duration-1000 lg:order-2"
>
<button
aria-label="Play youtube video button"
class="bg-video-player-icon-body absolute -z-0 flex size-[95px] cursor-pointer items-center justify-center rounded-full hover:brightness-125"
>
<PlayIcon
width={33.25}
height={38}
class="text-video-player-icon fill-video-player-icon"
/>
</button>

<iframe
class="pointer-events-none relative z-[1]"
width="100%"
height="100%"
src="https://www.youtube.com/embed/ZoT5cdMoMPA?si=2j3M397Em6445nch&autoplay=1&mute=1&loop=1&playlist=ZoT5cdMoMPA&controls=0"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; modestbranding; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen
>
</iframe>
<Image
src={THUMBNAIL_URL}
width={640}
height={480}
alt="Video Loading..."
class="absolute inset-0 z-10 size-full object-cover transition-opacity duration-500"
id="video-placeholder"
loading="lazy"
decoding="async"
fetchpriority="low"
/>

<div id="video-loader" class="absolute z-20 flex flex-col items-center">
<button
aria-label="Loading video"
class="bg-video-player-icon-body pointer-events-none flex size-[95px] items-center justify-center rounded-full opacity-50"
>
<PlayIcon
width={33.25}
height={38}
class="text-video-player-icon fill-video-player-icon"
/>
</button>
</div>
</div>

<div
Expand All @@ -46,11 +52,84 @@ const t = await createTranslator(locale);
>
{t("video.title")}
</h2>

<p class="font-body-mobile md:font-body mb-[38px]">
{t("video.description")}
</p>

<SiteSocials />
</div>
</section>

<script define:vars={{ VIDEO_ID }}>
// Configuration
const DELAY_MS = 1000;

const container = document.getElementById("lazy-video-container");
const placeholder = document.getElementById("video-placeholder");
const loader = document.getElementById("video-loader");

const loadVideo = () => {
// Check if already loaded to prevent duplicates
if (container.querySelector("iframe")) return;

const iframe = document.createElement("iframe");
iframe.setAttribute("width", "100%");
iframe.setAttribute("height", "100%");
// CRITICAL: autoplay=1 AND mute=1 are required for auto-play
iframe.setAttribute(
"src",
`https://www.youtube-nocookie.com/embed/${VIDEO_ID}?si=2j3M397Em6445nch&autoplay=1&mute=1&loop=1&playlist=${VIDEO_ID}&controls=0`,
);
iframe.setAttribute("title", "YouTube video player");
iframe.setAttribute("frameborder", "0");
iframe.setAttribute(
"allow",
"accelerometer; autoplay; clipboard-write; modestbranding; encrypted-media; gyroscope; picture-in-picture; web-share",
);
iframe.setAttribute("allowfullscreen", "");
iframe.classList.add(
"absolute",
"inset-0",
"z-30",
"size-full",
"opacity-0",
"transition-opacity",
"duration-1000",
"pointer-events-none",
);

// Smooth fade-in effect
iframe.onload = () => {
iframe.classList.remove("opacity-0");
if (placeholder) placeholder.style.opacity = "0";
if (loader) loader.style.opacity = "0";
// Cleanup DOM after transition
setTimeout(() => {
if (placeholder) placeholder.remove();
if (loader) loader.remove();
}, 1000);
};

container.appendChild(iframe);
};

// The Observer: Only load when the user actually sees the video container
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// Wait a moment to ensure it's not just a quick scroll-past
// AND to let the main thread clear up
setTimeout(() => {
loadVideo();
}, DELAY_MS);

// Stop observing once we've triggered the load
observer.disconnect();
}
});
},
{ threshold: 0.25 },
); // Trigger when 25% of the video is visible

if (container) observer.observe(container);
</script>
1 change: 1 addition & 0 deletions website/src/components/features/home/teams/ExtraCard.astro
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const { name, title, subTitles, social } = Astro.props;
href={social.href}
target="_blank"
rel="noopener noreferrer"
aria-label={`${name}'s ${social.type} profile`}
class="text-button-icon bg-button-icon-body flex size-7 cursor-pointer items-center justify-center rounded-full hover:brightness-125 min-[360px]:size-8"
>
{social.type === "x" && <SocialX />}
Expand Down
2 changes: 2 additions & 0 deletions website/src/components/features/home/teams/Teams.astro
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const extraProfiles: ExtraData[] = [
href="https://x.com/yuvilightman"
target="_blank"
rel="noopener noreferrer"
aria-label="Christopher Smith's X profile"
class="text-button-icon bg-button-icon-body flex size-7 cursor-pointer items-center justify-center rounded-full hover:brightness-125 min-[360px]:size-8"
>
<SocialX />
Expand Down Expand Up @@ -171,6 +172,7 @@ const extraProfiles: ExtraData[] = [
href={data.social.href}
target="_blank"
rel="noopener noreferrer"
aria-label={`${data.name}'s ${data.social.type} profile`}
class="text-button-icon bg-button-icon-body flex size-7 cursor-pointer items-center justify-center rounded-full hover:brightness-125 min-[360px]:size-8"
>
{data.social.type === "x" && <SocialX />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const t = await createTranslator(locale);
width={689}
src={QQLogo}
alt="Headshot of quantus mascot of q-cat with text quantus quests beside it"
loading="eager"
fetchpriority="high"
/>

<p class="font-body-bold mt-5 max-w-[810px]">
Expand Down
Loading
Loading