enhanced lighthouse report

This commit is contained in:
2026-08-21 19:40:20 -07:00
parent acf97ae05d
commit 6e4074bf95
9 changed files with 103 additions and 50 deletions

View File

@@ -44,6 +44,7 @@
<link rel="dns-prefetch" href="https://videos.pexels.com"> <link rel="dns-prefetch" href="https://videos.pexels.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://discord.com" crossorigin>
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';"> <meta http-equiv="Content-Security-Policy" content="default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';">
<meta property="og:title" content="Vyla Home - Self-Hosted Desktop Media Center | Serverless Streaming"> <meta property="og:title" content="Vyla Home - Self-Hosted Desktop Media Center | Serverless Streaming">
@@ -84,34 +85,38 @@
<link rel="apple-touch-icon" href="assets/images/icon.png"> <link rel="apple-touch-icon" href="assets/images/icon.png">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&display=swap"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&display=swap">
<!-- Critical CSS - Load immediately for above-the-fold content -->
<link rel="stylesheet" href="src/styles/base/tokens.css"> <link rel="stylesheet" href="src/styles/base/tokens.css">
<link rel="stylesheet" href="src/styles/base/reset.css"> <link rel="stylesheet" href="src/styles/base/reset.css">
<link rel="stylesheet" href="src/styles/base/typography.css"> <link rel="stylesheet" href="src/styles/base/typography.css">
<link rel="stylesheet" href="src/styles/utilities/layout.css"> <link rel="stylesheet" href="src/styles/utilities/layout.css">
<link rel="stylesheet" href="src/styles/utilities/reveal.css"> <link rel="stylesheet" href="src/styles/utilities/reveal.css">
<link rel="stylesheet" href="src/styles/layout/nav.css"> <link rel="stylesheet" href="src/styles/layout/nav.css">
<link rel="stylesheet" href="src/styles/layout/footer.css">
<link rel="stylesheet" href="src/styles/components/buttons.css">
<link rel="stylesheet" href="src/styles/components/pills.css">
<link rel="stylesheet" href="src/styles/components/stats.css">
<link rel="stylesheet" href="src/styles/components/script-card.css">
<link rel="stylesheet" href="src/styles/components/marquee.css">
<link rel="stylesheet" href="src/styles/components/testimonial-card.css">
<link rel="stylesheet" href="src/styles/components/executors.css">
<link rel="stylesheet" href="src/styles/components/showcase.css">
<link rel="stylesheet" href="src/styles/components/modal.css">
<link rel="stylesheet" href="src/styles/components/partners.css">
<link rel="stylesheet" href="src/styles/components/faq.css">
<link rel="stylesheet" href="src/styles/sections/hero-atmosphere.css"> <link rel="stylesheet" href="src/styles/sections/hero-atmosphere.css">
<link rel="stylesheet" href="src/styles/sections/hero-content.css"> <link rel="stylesheet" href="src/styles/sections/hero-content.css">
<link rel="stylesheet" href="src/styles/sections/section-base.css">
<link rel="stylesheet" href="src/styles/sections/testimonials.css"> <!-- Non-critical CSS - Deferred loading for below-the-fold content -->
<link rel="stylesheet" href="src/styles/sections/executors.css"> <link rel="stylesheet" href="src/styles/layout/footer.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/features.css"> <link rel="stylesheet" href="src/styles/components/buttons.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/showcases.css"> <link rel="stylesheet" href="src/styles/components/pills.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/faq-section.css"> <link rel="stylesheet" href="src/styles/components/stats.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/cta-banner.css"> <link rel="stylesheet" href="src/styles/components/script-card.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/utilities/responsive.css"> <link rel="stylesheet" href="src/styles/components/marquee.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/components/testimonial-card.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/components/executors.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/components/showcase.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/components/modal.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/components/partners.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/components/faq.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/section-base.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/testimonials.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/executors.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/features.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/showcases.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/faq-section.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/sections/cta-banner.css" media="print" onload="this.media='all'">
<link rel="stylesheet" href="src/styles/utilities/responsive.css" media="print" onload="this.media='all'">
<script type="application/ld+json"> <script type="application/ld+json">
{ {
@@ -278,7 +283,8 @@
<div class="logo-image"> <div class="logo-image">
<img src="assets/images/header_logo.png" alt="Vyla Home Logo" width="100" height="100" <img src="assets/images/header_logo.png" alt="Vyla Home Logo" width="100" height="100"
fetchpriority="high"> fetchpriority="high"
srcset="assets/images/header_logo.png 100w, assets/images/header_logo.png 200w" sizes="100px">
</div> </div>
<h1 id="hero-title" class="hero-title">The Local-First Desktop Media Center</h1> <h1 id="hero-title" class="hero-title">The Local-First Desktop Media Center</h1>
@@ -392,7 +398,9 @@
<figure class="feature-media"> <figure class="feature-media">
<img src="assets/images/features/1.png" <img src="assets/images/features/1.png"
alt="Diagram showing datacenter IP throttling bypass with residential network connection" alt="Diagram showing datacenter IP throttling bypass with residential network connection"
width="800" height="450" loading="lazy" decoding="async"> width="800" height="450" loading="lazy" decoding="async"
srcset="assets/images/features/1.png 800w, assets/images/features/1.png 400w"
sizes="(max-width: 768px) 400px, 800px">
</figure> </figure>
<div class="feature-copy"> <div class="feature-copy">
<h3 class="section-title-lg feature-title">No Datacenter Throttling</h3> <h3 class="section-title-lg feature-title">No Datacenter Throttling</h3>
@@ -407,7 +415,9 @@
<figure class="feature-media"> <figure class="feature-media">
<img src="assets/images/features/2.png" <img src="assets/images/features/2.png"
alt="Diagram showing decentralized architecture eliminating single point of failure" alt="Diagram showing decentralized architecture eliminating single point of failure"
width="800" height="450" loading="lazy" decoding="async"> width="800" height="450" loading="lazy" decoding="async"
srcset="assets/images/features/2.png 800w, assets/images/features/2.png 400w"
sizes="(max-width: 768px) 400px, 800px">
</figure> </figure>
<div class="feature-copy"> <div class="feature-copy">
<h3 class="section-title-lg feature-title">No Single Point of Failure</h3> <h3 class="section-title-lg feature-title">No Single Point of Failure</h3>
@@ -422,7 +432,9 @@
<figure class="feature-media"> <figure class="feature-media">
<img src="assets/images/features/3.png" <img src="assets/images/features/3.png"
alt="Illustration of encrypted local vault with hardware profile key" width="800" alt="Illustration of encrypted local vault with hardware profile key" width="800"
height="450" loading="lazy" decoding="async"> height="450" loading="lazy" decoding="async"
srcset="assets/images/features/3.png 800w, assets/images/features/3.png 400w"
sizes="(max-width: 768px) 400px, 800px">
</figure> </figure>
<div class="feature-copy"> <div class="feature-copy">
<h3 class="section-title-lg feature-title">Encrypted Local Vault</h3> <h3 class="section-title-lg feature-title">Encrypted Local Vault</h3>
@@ -437,7 +449,9 @@
<figure class="feature-media"> <figure class="feature-media">
<img src="assets/images/features/4.png" <img src="assets/images/features/4.png"
alt="Interface showing automated over-the-air update process" width="800" height="450" alt="Interface showing automated over-the-air update process" width="800" height="450"
loading="lazy" decoding="async"> loading="lazy" decoding="async"
srcset="assets/images/features/4.png 800w, assets/images/features/4.png 400w"
sizes="(max-width: 768px) 400px, 800px">
</figure> </figure>
<div class="feature-copy"> <div class="feature-copy">
<h3 class="section-title-lg feature-title">Automated OTA Updates</h3> <h3 class="section-title-lg feature-title">Automated OTA Updates</h3>
@@ -452,7 +466,9 @@
<figure class="feature-media"> <figure class="feature-media">
<img src="assets/images/features/5.png" <img src="assets/images/features/5.png"
alt="Interface showing rich media discovery with curated collections and 4K content" alt="Interface showing rich media discovery with curated collections and 4K content"
width="800" height="450" loading="lazy" decoding="async"> width="800" height="450" loading="lazy" decoding="async"
srcset="assets/images/features/5.png 800w, assets/images/features/5.png 400w"
sizes="(max-width: 768px) 400px, 800px">
</figure> </figure>
<div class="feature-copy"> <div class="feature-copy">
<h3 class="section-title-lg feature-title">Rich Discovery & Curated Media</h3> <h3 class="section-title-lg feature-title">Rich Discovery & Curated Media</h3>
@@ -467,7 +483,9 @@
<figure class="feature-media"> <figure class="feature-media">
<img src="assets/images/features/6.png" <img src="assets/images/features/6.png"
alt="Interface showing customizable theme and layout options" width="800" height="450" alt="Interface showing customizable theme and layout options" width="800" height="450"
loading="lazy" decoding="async"> loading="lazy" decoding="async"
srcset="assets/images/features/6.png 800w, assets/images/features/6.png 400w"
sizes="(max-width: 768px) 400px, 800px">
</figure> </figure>
<div class="feature-copy"> <div class="feature-copy">
<h3 class="section-title-lg feature-title">Customizable Interface</h3> <h3 class="section-title-lg feature-title">Customizable Interface</h3>
@@ -545,12 +563,12 @@
<footer class="footer" role="contentinfo"> <footer class="footer" role="contentinfo">
<div class="footer-content"> <div class="footer-content">
<div class="footer-section"> <div class="footer-section">
<h4>Vyla Home</h4> <h3>Vyla Home</h3>
<p>A solo passion project built for resilient, serverless, personal entertainment playback. Run locally, <p>A solo passion project built for resilient, serverless, personal entertainment playback. Run locally,
own your experience.</p> own your experience.</p>
</div> </div>
<div class="footer-section"> <div class="footer-section">
<h4>Join our Discord</h4> <h3>Join our Discord</h3>
<nav class="social-links" aria-label="Social media links"> <nav class="social-links" aria-label="Social media links">
<a href="https://discord.gg/5eqRhKeywG" target="_blank" rel="noopener noreferrer" <a href="https://discord.gg/5eqRhKeywG" target="_blank" rel="noopener noreferrer"
aria-label="Join our Discord community"> aria-label="Join our Discord community">
@@ -559,7 +577,7 @@
</nav> </nav>
</div> </div>
<div class="footer-section"> <div class="footer-section">
<h4>Our Gitlab</h4> <h3>Our Gitlab</h3>
<p><a href="https://gitlab.com/vyla-entertainment/home" target="_blank" rel="noopener noreferrer">Vyla <p><a href="https://gitlab.com/vyla-entertainment/home" target="_blank" rel="noopener noreferrer">Vyla
Entertainment</a> Entertainment</a>
</p> </p>

View File

@@ -1,3 +1,5 @@
# Vyla Home
Vyla Home is a self-hosted desktop media center that bypasses datacenter blocking, ISP throttling, and cloud downtime. Experience self-hosted streaming, 4K movies, TV shows, and anime with complete privacy and zero server dependencies. Vyla Home is a self-hosted desktop media center that bypasses datacenter blocking, ISP throttling, and cloud downtime. Experience self-hosted streaming, 4K movies, TV shows, and anime with complete privacy and zero server dependencies.
[Home](https://vyla.cc/) [Home](https://vyla.cc/)

View File

@@ -2,11 +2,13 @@
{ {
"name": "FMHY", "name": "FMHY",
"logo": "assets/images/partners/fmhy.png", "logo": "assets/images/partners/fmhy.png",
"logoSmall": "assets/images/partners/fmhy.png",
"link": "https://fmhy.net" "link": "https://fmhy.net"
}, },
{ {
"name": "r/Piracy", "name": "r/Piracy",
"logo": "assets/images/partners/piracy.png", "logo": "assets/images/partners/piracy.png",
"logoSmall": "assets/images/partners/piracy.png",
"link": "https://reddit.com/r/Piracy" "link": "https://reddit.com/r/Piracy"
} }
] ]

View File

@@ -3,36 +3,42 @@
"name": "ZENITH The Great (Ash Fan)", "name": "ZENITH The Great (Ash Fan)",
"handle": "@zenithrifle", "handle": "@zenithrifle",
"text": "oh god the ui is so goood", "text": "oh god the ui is so goood",
"avatar": "/assets/images/testimonials/zenithrifle.png" "avatar": "/assets/images/testimonials/zenithrifle.png",
"avatarSmall": "/assets/images/testimonials/zenithrifle.png"
}, },
{ {
"name": "Light", "name": "Light",
"handle": "@acideetdeforme", "handle": "@acideetdeforme",
"text": "Youre highk a goat for doing ts without ads", "text": "Youre highk a goat for doing ts without ads",
"avatar": "/assets/images/testimonials/acideetdeforme.png" "avatar": "/assets/images/testimonials/acideetdeforme.png",
"avatarSmall": "/assets/images/testimonials/acideetdeforme.png"
}, },
{ {
"name": "char", "name": "char",
"handle": "@chariachtus", "handle": "@chariachtus",
"text": "I find Vyla as the best by far", "text": "I find Vyla as the best by far",
"avatar": "/assets/images/testimonials/chariachtus.png" "avatar": "/assets/images/testimonials/chariachtus.png",
"avatarSmall": "/assets/images/testimonials/chariachtus.png"
}, },
{ {
"name": "amri", "name": "amri",
"handle": "@snorer", "handle": "@snorer",
"text": "who is the owner of such greatness", "text": "who is the owner of such greatness",
"avatar": "/assets/images/testimonials/snorer.png" "avatar": "/assets/images/testimonials/snorer.png",
"avatarSmall": "/assets/images/testimonials/snorer.png"
}, },
{ {
"name": "Bee", "name": "Bee",
"handle": "@block.tale.adict", "handle": "@block.tale.adict",
"text": "this is sickk", "text": "this is sickk",
"avatar": "/assets/images/testimonials/block.tale.adict.png" "avatar": "/assets/images/testimonials/block.tale.adict.png",
"avatarSmall": "/assets/images/testimonials/block.tale.adict.png"
}, },
{ {
"name": "lucky-mucky", "name": "lucky-mucky",
"handle": "@lucky_mucky_", "handle": "@lucky_mucky_",
"text": "ur like the best owner ever❤️", "text": "ur like the best owner ever❤️",
"avatar": "/assets/images/testimonials/lucky_mucky_.png" "avatar": "/assets/images/testimonials/lucky_mucky_.png",
"avatarSmall": "/assets/images/testimonials/lucky_mucky_.png"
} }
] ]

View File

@@ -11,14 +11,23 @@ function initials(name) {
export function createTestimonialCard(testimonial) { export function createTestimonialCard(testimonial) {
const card = createElement('div', 'testimonial-card'); const card = createElement('div', 'testimonial-card');
const avatar = testimonial.avatar let avatarHTML;
? `<img src="${testimonial.avatar}" alt="" width="34" height="34" loading="lazy" decoding="async">`
: initials(testimonial.name || '?'); if (testimonial.avatar) {
if (testimonial.avatarSmall) {
avatarHTML = `<img src="${testimonial.avatarSmall}" alt="" width="34" height="34" loading="lazy" decoding="async"
srcset="${testimonial.avatarSmall} 60w, ${testimonial.avatar} 120w" sizes="60px">`;
} else {
avatarHTML = `<img src="${testimonial.avatar}" alt="" width="34" height="34" loading="lazy" decoding="async">`;
}
} else {
avatarHTML = initials(testimonial.name || '?');
}
card.innerHTML = ` card.innerHTML = `
<div class="testimonial-top"> <div class="testimonial-top">
<div class="testimonial-user"> <div class="testimonial-user">
<div class="testimonial-avatar">${avatar}</div> <div class="testimonial-avatar">${avatarHTML}</div>
<div class="testimonial-names"> <div class="testimonial-names">
<span class="testimonial-name">${testimonial.name}</span> <span class="testimonial-name">${testimonial.name}</span>
<span class="testimonial-handle">${testimonial.handle || ''}</span> <span class="testimonial-handle">${testimonial.handle || ''}</span>

View File

@@ -4,9 +4,22 @@ import { observeReveals } from '../animations/reveal-observer.js';
function createPartnerItem(partner) { function createPartnerItem(partner) {
const item = createElement('div', 'partner-item reveal'); const item = createElement('div', 'partner-item reveal');
let imgHTML;
if (partner.logo) {
if (partner.logoSmall) {
imgHTML = `<img src="${partner.logoSmall}" alt="${partner.name}" width="128" height="128" loading="lazy" decoding="async"
srcset="${partner.logoSmall} 64w, ${partner.logo} 128w" sizes="64px">`;
} else {
imgHTML = `<img src="${partner.logo}" alt="${partner.name}" width="128" height="128" loading="lazy" decoding="async">`;
}
} else {
imgHTML = '';
}
const inner = partner.link const inner = partner.link
? `<a href="${partner.link}" target="_blank" rel="noopener noreferrer"><img src="${partner.logo}" alt="${partner.name}" width="128" height="128" loading="lazy" decoding="async"></a>` ? `<a href="${partner.link}" target="_blank" rel="noopener noreferrer">${imgHTML}</a>`
: `<img src="${partner.logo}" alt="${partner.name}" width="128" height="128" loading="lazy" decoding="async">`; : imgHTML;
item.innerHTML = inner; item.innerHTML = inner;
return item; return item;
} }

View File

@@ -22,15 +22,14 @@ body {
line-height: 1.5; line-height: 1.5;
overflow-x: hidden; overflow-x: hidden;
position: relative; position: relative;
scrollbar-width: none;
-ms-overflow-style: none;
min-height: 100%; min-height: 100%;
min-height: 100dvh; min-height: 100dvh;
background: var(--color-bg); background: var(--color-bg);
} }
body::-webkit-scrollbar { body::-webkit-scrollbar {
display: none; width: 0;
background: transparent;
} }
a { a {
@@ -66,4 +65,4 @@ ol {
::selection { ::selection {
background: var(--color-fg); background: var(--color-fg);
color: var(--color-bg); color: var(--color-bg);
} }

View File

@@ -51,6 +51,10 @@
touch-action: manipulation; touch-action: manipulation;
} }
.hero-cta:hover {
transform: scale(0.97);
}
.hero-cta:active { .hero-cta:active {
transform: scale(0.97); transform: scale(0.97);
} }

View File

@@ -20,8 +20,7 @@
} }
.hero-title { .hero-title {
font-size: clamp(2rem, calc(2rem + 2 * ((100vw - 23.4375rem) / 66.5625)), 4rem); font-size: 2.3rem;
line-height: clamp(2.28rem, calc(2.28rem + 1.72 * ((100vw - 23.4375rem) / 66.5625)), 4rem);
letter-spacing: -.03em; letter-spacing: -.03em;
font-weight: 500; font-weight: 500;
text-wrap: balance; text-wrap: balance;
@@ -41,7 +40,7 @@
font-size: 0.8rem; font-size: 0.8rem;
margin: 1rem auto 0; margin: 1rem auto 0;
line-height: 1.5; line-height: 1.5;
width: 80%; width: 50%;
} }
.hero-description a { .hero-description a {
@@ -66,13 +65,14 @@
@media (max-width: 768px) { @media (max-width: 768px) {
.hero-description { .hero-description {
margin-top: 0rem; margin-top: 0rem;
width: 80%;
} }
} }
@media (orientation: landscape) and (max-height: 600px) { @media (orientation: landscape) and (max-height: 600px) {
.hero-title { .hero-title {
margin-bottom: 0rem; margin-bottom: 0rem;
font-size: 2.7rem; font-size: 2rem;
} }
.hero-container { .hero-container {