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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,6 @@ lighthouse-report.json
# Temporary folders
tmp/
temp/

# Local design references / saved web pages
docs/preview/
129 changes: 70 additions & 59 deletions bun.lock

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,30 @@
"test:unit": "vitest run"
},
"devDependencies": {
"@iconify-json/ph": "^1.2.2",
"@playwright/test": "^1.59.1",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/enhanced-img": "^0.10.4",
"@sveltejs/kit": "^2.56.1",
"@sveltejs/kit": "^2.59.0",
"@sveltejs/vite-plugin-svelte": "^7.0.0",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/svelte": "^5.3.1",
"eslint": "^9.39.4",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-svelte": "^3.17.0",
"jsdom": "^29.0.1",
"eslint-plugin-svelte": "^3.17.1",
"jsdom": "^29.1.1",
"mdsvex": "^0.12.7",
"prettier": "^3.8.1",
"prettier": "^3.8.3",
"sass": "^1.99.0",
"svelte": "^5.55.1",
"svelte": "^5.55.5",
"unplugin-icons": "^23.0.1",
"vite": "^8.0.3",
"vitest": "^4.1.2"
"vite": "^8.0.10",
"vitest": "^4.1.5"
},
"type": "module",
"dependencies": {
"@vitest/coverage-v8": "^4.1.2",
"dompurify": "^3.3.3",
"@vitest/coverage-v8": "^4.1.5",
"dompurify": "^3.4.2",
"embla-carousel-svelte": "^8.6.0",
"iconify-icon": "^3.0.2",
"lottie-web": "^5.13.0",
Expand Down
12 changes: 6 additions & 6 deletions src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@
<link rel="icon" href="%sveltekit.assets%/favicon.ico" sizes="any" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" type="image/png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
document.documentElement.setAttribute(
'color-scheme',
window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'
);
</script>
<script defer src="https://code.iconify.design/iconify-icon/1.0.8/iconify-icon.min.js"></script>
<script
defer
src="https://analytics.techquests.dev/umami"
data-website-id="c8dd6e51-7182-472b-9637-01955cdec219"
data-auto-track="false"
></script>
<script>
const theme = localStorage.getItem('color-scheme');
theme
? document.documentElement.setAttribute('color-scheme', theme)
: localStorage.setItem('color-scheme', 'dark');
</script>
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
Expand Down
29 changes: 25 additions & 4 deletions src/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ html {
--yellow-light: hsl(32, 77%, 52%);

font-family: $font-family-base;
font-weight: 300;
font-weight: 400;
}

:root {
Expand All @@ -65,7 +65,7 @@ html {
--yellow: var(--yellow-dark);

font-family: $font-family-base;
font-weight: 300;
font-weight: 400;
}

@media (prefers-color-scheme: light) {
Expand Down Expand Up @@ -289,11 +289,11 @@ div.description {

.pfp {
border-radius: 50%;
transition: transform 1.5s;
background: none;
padding: 0;

&:hover {
cursor: pointer;
transform: rotate(540deg);
}
}

Expand Down Expand Up @@ -390,6 +390,27 @@ a.link {
}
}

// Back link (used on detail pages to return to section index)
a.back {
display: inline-block;
font-family: $font-family-mono;
font-size: $font-base;
font-weight: 400;
color: var(--txt);
text-decoration: none;
margin: $spacing-xl 0 $spacing-lg 0;

.arrow {
display: inline-block;
margin-right: 0.4ch;
transition: transform $transition-fast;
}

&:hover .arrow {
transform: translateX(-0.3em);
}
}

blockquote {
border-left: 2px solid var(--txt-2);
padding-left: $spacing-xl;
Expand Down
11 changes: 11 additions & 0 deletions src/content/videos/welcome/+welcome.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
published: true
name: 'Welcome to Tech Quests'
icon: 'ph:video'
description: 'Kicking off the Tech Quests video channel β€” what to expect, how often, and what topics are coming.'
date: 2026-05-03
youtubeId: 'dQw4w9WgXcQ'
duration: '3:33'
---

This is a placeholder for the channel's intro video. The actual video will replace this once published.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* fira-code-latin-wght-normal */
/* inter-latin-wght-normal */
@font-face {
font-family: 'Fira Code Variable';
font-family: 'Inter Variable';
font-style: normal;
font-display: swap;
font-weight: 300 700;
src: url(https://cdn.jsdelivr.net/fontsource/fonts/fira-code:vf@latest/latin-wght-normal.woff2)
font-weight: 100 900;
src: url(https://cdn.jsdelivr.net/fontsource/fonts/inter:vf@latest/latin-wght-normal.woff2)
format('woff2-variations');
unicode-range:
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
Expand Down
9 changes: 7 additions & 2 deletions src/lib/components/PageHead.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
$: canonicalUrl = `${hostname}${$page.url.pathname}`;
$: hasImage = Boolean(image?.img?.src);
$: twitterCard = hasImage ? 'summary_large_image' : 'summary';
$: imageUrl = hasImage
? /^https?:\/\//.test(image.img.src)
? image.img.src
: hostname + image.img.src
: '';
$: jsonLdString = jsonLd ? JSON.stringify(jsonLd).replace(/</g, '\\u003c') : '';
$: jsonLdScriptTag = jsonLdString
? '<' + 'script type="application/ld+json">' + jsonLdString + '</' + 'script>'
Expand Down Expand Up @@ -44,13 +49,13 @@
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
{#if hasImage}
<meta property="og:image" content={hostname + image.img.src} />
<meta property="og:image" content={imageUrl} />
{#if image.img.w && image.img.h}
<meta property="og:image:width" content={image.img.w} />
<meta property="og:image:height" content={image.img.h} />
{/if}
<meta property="og:image:alt" content={title} />
<meta name="twitter:image" content={hostname + image.img.src} />
<meta name="twitter:image" content={imageUrl} />
<meta name="twitter:image:alt" content={title} />
{:else}
<meta property="og:image" content={`${hostname}/blog.png`} />
Expand Down
34 changes: 34 additions & 0 deletions src/lib/utils/structured-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,40 @@ export function buildProjectJsonLd(metadata, images) {
};
}

export function buildVideoJsonLd(metadata) {
const url = `${hostname}/videos/${metadata.slug}`;
const datePublished = metadata.date ? new Date(metadata.date).toISOString() : undefined;
const thumbnailUrl = `https://i.ytimg.com/vi/${metadata.youtubeId}/maxresdefault.jpg`;
const embedUrl = `https://www.youtube-nocookie.com/embed/${metadata.youtubeId}`;
const contentUrl = `https://youtube.com/watch?v=${metadata.youtubeId}`;

return {
'@context': 'https://schema.org',
'@type': 'VideoObject',
name: metadata.name,
description: metadata.description,
thumbnailUrl,
...(datePublished ? { uploadDate: datePublished } : {}),
...(metadata.duration ? { duration: metadata.duration } : {}),
contentUrl,
embedUrl,
url,
publisher: {
'@type': 'Organization',
name: siteName,
logo: {
'@type': 'ImageObject',
url: logoUrl
}
},
author: {
'@type': 'Person',
name: authorName,
url: authorUrl
}
};
}

export function buildImageObject(image) {
return normalizeImage(image);
}
16 changes: 8 additions & 8 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
<script>
import '../app.scss';
import '$lib/assets/fonts/fira-mono.css';
import '$lib/assets/fonts/fira-code-variable.css';
import '$lib/assets/fonts/inter.css';
import { page } from '$app/stores';
import PageHead from '$lib/components/PageHead.svelte';
import Toggle from '$lib/components/Toggle.svelte';
import NavLogo from '$lib/components/NavLogo.svelte';
import Analytics from '$lib/components/Analytics.svelte';
import { toggleTheme } from '$lib/js/theme.js';
import { fly } from 'svelte/transition';

export let data;

const pages = [
{ name: 'Projects', path: '/projects' },
{ name: 'Blog', path: '/blog' },
{ name: 'Videos', path: '/videos' },
{ name: 'About', path: '/about' },
{ name: 'Contact', path: '/contact' }
];
Expand Down Expand Up @@ -87,9 +88,9 @@
<header>
<div class="row">
<a href="/"><h1>Tech Quests</h1></a>
<a class="pfp" href="/" aria-label="homepage">
<NavLogo size="2rem" />
</a>
<button class="pfp" on:click={toggleTheme} aria-label="Toggle theme">
<NavLogo size="2.5rem" />
</button>
</div>
<nav>
{#each pages as { name, path } (path)}
Expand All @@ -98,7 +99,6 @@
</a>
{/each}
</nav>
<Toggle />
</header>
{/if}

Expand Down Expand Up @@ -173,7 +173,7 @@
left: $spacing-md;
top: $spacing-md;
padding: $spacing-xs $spacing-md;
background: var(--bg-1);
background: var(--bg-2);
color: var(--txt);
border: 1px solid var(--bg-3);
z-index: $z-index-sticky;
Expand All @@ -198,7 +198,7 @@

@media (max-width: $breakpoint-tablet) {
header {
padding: 0 $spacing-md;
padding: 0 $spacing-xl;
gap: $spacing-md;

nav {
Expand Down
42 changes: 28 additions & 14 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<script>
import Toggle from '$lib/components/Toggle.svelte';
import pfpinDark from '$lib/assets/pfpin-dark.json?raw';
import pfpinLight from '$lib/assets/pfpin-light.json?raw';
import { theme } from '$lib/js/theme';
import { theme, toggleTheme } from '$lib/js/theme';
import { onMount } from 'svelte';

let lottie;
Expand Down Expand Up @@ -46,8 +45,8 @@
<main>
<div class="container">
<div class="row">
<h1>Tech Quests</h1>
<div class="pfpstart"></div>
<a href="/"><h1>Tech Quests</h1></a>
<button class="pfpstart" on:click={toggleTheme} aria-label="Toggle theme"></button>
</div>
<p>The saga of a SRE sharing his technological adventures.</p>
<nav>
Expand All @@ -57,13 +56,15 @@
<a class="nav" href="/blog">
<span class="arrow">&nbsp;></span><span class="slash">/</span>Blog
</a>
<a class="nav" href="/videos">
<span class="arrow">&nbsp;></span><span class="slash">/</span>Videos
</a>
<a class="nav" href="/about">
<span class="arrow">&nbsp;></span><span class="slash">/</span>About
</a>
<a class="nav" href="/contact">
<span class="arrow">&nbsp;></span><span class="slash">/</span>Contact
</a>
<Toggle />
</nav>
</div>
</main>
Expand All @@ -83,10 +84,16 @@
}

.pfpstart {
width: $spacing-6xl;
height: $spacing-6xl;
margin-top: $spacing-xs;
margin-left: $spacing-base;
display: inline-flex;
height: $font-3xl;
aspect-ratio: 800 / 410;
background: none;
padding: 0;

:global(svg) {
width: 100% !important;
height: 100% !important;
}
}

h1 {
Expand All @@ -112,15 +119,22 @@
@media (max-width: $breakpoint-mobile) {
nav {
flex-direction: column;
gap: $spacing-sm;
gap: $spacing-md;
}
.row {
flex-direction: column-reverse;
gap: $spacing-sm;
align-items: flex-start;
gap: $spacing-lg;
align-items: center;
}
h1 {
font-size: $font-2xl;
}
.pfpstart {
visibility: hidden;
width: auto;
height: $font-2xl;
aspect-ratio: 800 / 410;
margin: 0;
flex-shrink: 0;
visibility: visible;
}
}
</style>
2 changes: 1 addition & 1 deletion src/routes/about/+page.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export function load() {
meta: {
title: 'About Andre Nogueira | Tech Quests',
description:
'Learn more about Andre Nogueira, the Site Reliability Engineer behind Tech Quests, and the purpose of this blog.',
'About Andre Nogueira and Tech Quests β€” long-form posts, projects, and videos on Site Reliability Engineering and platform work.',
type: 'blog-about',
jsonLd: buildPersonJsonLd()
}
Expand Down
Loading
Loading