Merge pull request #82 from bartvdbraak/feat/workflows

Add new workflows
This commit is contained in:
Bart van der Braak 2023-08-02 02:24:02 +02:00 committed by GitHub
commit 909919f90d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 559 additions and 353 deletions

View file

@ -1,8 +1,8 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: "github-actions" - package-ecosystem: 'github-actions'
directory: "/" directory: '/'
schedule: schedule:
interval: "weekly" interval: 'weekly'
reviewers: reviewers:
- "bartvdbraak" - 'bartvdbraak'

View file

@ -1,4 +1,5 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"] "extends": ["config:base"],
"reviewers": ["bartvdbraak"]
} }

38
.github/workflows/linting.yaml vendored Normal file
View file

@ -0,0 +1,38 @@
name: Linting
on: [pull_request]
permissions:
checks: write
contents: write
jobs:
run-checks:
name: Run checks
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18]
steps:
- name: Checkout Git repository
uses: actions/checkout@v3.5.3
- name: Setup pnpm
uses: pnpm/action-setup@v2.4.0
with:
version: latest
- name: Setup Node.js
uses: actions/setup-node@v3.7.0
with:
node-version: ${{ matrix.node-version }}
cache: pnpm
- name: Install Node.js dependencies
run: pnpm install --frozen-lockfile
- name: Run linters
uses: wearerequired/lint-action@v2.3.0
with:
eslint: true
prettier: true

135
.github/workflows/unlighthouse.yaml vendored Normal file
View file

@ -0,0 +1,135 @@
name: Unlighthouse
on: [pull_request]
permissions:
pull-requests: write
jobs:
unlighthouse:
runs-on: ubuntu-latest
env:
COMMENT_ID: unlighthouse-node${{matrix.node-version}}
PORT: 8000
CLOUDFLARE_PROJECT: hellobart-unlighthouse
CLOUDFLARE_BRANCH: pull-${{ github.event.pull_request.number }}
strategy:
matrix:
node-version: [18]
steps:
- name: Create initial comment
uses: marocchino/sticky-pull-request-comment@v2.7.0
with:
header: ${{ env.COMMENT_ID }}
message: |
⚡️ Lighthouse report
![loading](https://github.com/bartvdbraak/hellob.art/assets/3996360/0e00b3fc-d5f9-490b-9aa7-07cb4b59f85f)
- name: Checkout repository
uses: actions/checkout@v3.5.3
- name: Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: latest
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3.7.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build production
run: pnpm run build
- name: Start Preview and Get Preview URL
run: |
pnpm run preview --port ${{ env.PORT }} & echo $! > preview_pid
- name: Install Dependencies
run: pnpm add -g @unlighthouse/cli puppeteer
- name: Run Unlighthouse
run: |
unlighthouse-ci \
--site "http://localhost:${{ env.PORT }}" \
--reporter jsonExpanded \
--build-static
- name: Upload report to Cloudflare pages
uses: cloudflare/wrangler-action@2.0.0
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: pages deploy .unlighthouse --project-name="${{ env.CLOUDFLARE_PROJECT }}" --branch=${{ env.CLOUDFLARE_BRANCH }}
- name: Create result content
id: create_result_content
uses: actions/github-script@v6.4.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const result = JSON.parse(fs.readFileSync('.unlighthouse/ci-result.json', 'utf8'));
const formatScore = score => `${Math.round(score * 100)} (${score})`;
const getEmoji = score => score >= 0.9 ? '🟢' : score >= 0.5 ? '🟠' : '🔴';
const score = res => `${getEmoji(res)} ${formatScore(res)}`;
const reportUrl = `https://${{ env.CLOUDFLARE_BRANCH }}.${{ env.CLOUDFLARE_PROJECT }}.pages.dev`;
const comment = [
`⚡️ Lighthouse report for the changes in this PR:`,
'| Category | Score |',
'| --- | --- |',
`| Performance | ${score(result.summary.categories.performance.averageScore)} |`,
`| Accessibility | ${score(result.summary.categories.accessibility.averageScore)} |`,
`| Best practices | ${score(result.summary.categories['best-practices'].averageScore)} |`,
`| SEO | ${score(result.summary.categories.seo.averageScore)} |`,
`| *Overall* | ${score(result.summary.score)} |`,
'',
'*Lighthouse scores for individual routes:*',
'',
'| Path | Performance | Accessibility | Best practices | SEO | Overall |',
'| --- | --- | --- | --- | --- | --- |',
`${result.routes.map(route => `| ${route.path} | ${score(route.categories.performance.score)} | ${score(route.categories.accessibility.score)} | ${score(route.categories['best-practices'].score)} | ${score(route.categories.seo.score)} | ${score(route.score)} |`).join('\n')}`,
'',
'*Lighthouse metrics:*',
'',
'| Metric | Average Value |',
'| --- | --- |',
`${Object.entries(result.summary.metrics).map(([metric, { averageNumericValue }]) => `| ${metric} | ${averageNumericValue} |`).join('\n')}`,
'',
`View the full Lighthouse report [here](${reportUrl}).`,
].join('\n');
core.setOutput("comment", comment);
- name: Update comment with result
uses: marocchino/sticky-pull-request-comment@v2.7.0
with:
header: ${{ env.COMMENT_ID }}
message: ${{ steps.create_result_content.outputs.comment }}
- name: Update comment on failure
uses: marocchino/sticky-pull-request-comment@v2.7.0
if: ${{ failure() }}
with:
header: ${{ env.COMMENT_ID }}
message: |
⚡️ Lighthouse report failed
See deployment for any errors
- name: Update comment on cancel
uses: marocchino/sticky-pull-request-comment@v2.7.0
if: ${{ cancelled() }}
with:
header: ${{ env.COMMENT_ID }}
message: |
⚡️ Lighthouse report cancelled

1
.gitignore vendored
View file

@ -8,3 +8,4 @@ node_modules
!.env.example !.env.example
vite.config.js.timestamp-* vite.config.js.timestamp-*
vite.config.ts.timestamp-* vite.config.ts.timestamp-*
.unlighthouse

View file

@ -1,6 +1,6 @@
<div align="center"> <div align="center">
<h1 align="center">hellob.art</h1> <h1 align="center">hellob.art</h1>
<h5>a simple portfolio</h5> <h5>personal website built with Svelte</h5>
</div> </div>
<div align="center"> <div align="center">
@ -8,11 +8,6 @@
<a href="https://github.com/bartvdbraak/hellob.art/deployments/activity_log?environment=Production"><img src="https://img.shields.io/github/deployments/bartvdbraak/hellob.art/production?label=vercel&logo=vercel" /></a> <a href="https://github.com/bartvdbraak/hellob.art/deployments/activity_log?environment=Production"><img src="https://img.shields.io/github/deployments/bartvdbraak/hellob.art/production?label=vercel&logo=vercel" /></a>
</div> </div>
<div align="center">
<a href="https://hellob.art?ref=github">hellob.art</a>
</div>
<br/>
## Installation ## Installation
To install the project and its dependencies, follow these steps: To install the project and its dependencies, follow these steps:
@ -52,10 +47,7 @@ pnpm run dev -- --open
- **SvelteKit:** The tooling and routing framework for Svelte projects. - **SvelteKit:** The tooling and routing framework for Svelte projects.
- **Tailwind CSS:** A utility-first CSS framework packed with classes. - **Tailwind CSS:** A utility-first CSS framework packed with classes.
- **Skeleton:** UI Toolkit for Svelte + Tailwind. - **Skeleton:** UI Toolkit for Svelte + Tailwind.
- **Threlte:** Declarative Three.js for Svelte.
## Deployment
The portfolio is hosted using [Vercel](https://vercel.com). You can access it at [https://hellob.art](https://hellob.art).
## Contributing ## Contributing
@ -65,12 +57,15 @@ I'm open to contributions! If you find any bugs, have suggestions, or want to ad
This project is licensed under the GPLv3 License. Feel free to explore, learn, and have fun! This project is licensed under the GPLv3 License. Feel free to explore, learn, and have fun!
## Get in Touch Some dependencies may hold different licenses but are in compliance with GPLv3:
Let's connect! You can find me on: - `MIT`: Compatible with GPLv3.
- `Apache 2.0`: Compatible with GPLv3.
- Website: [hellob.art](https://hellob.art) - `BSD-3-Clause`: Compatible with GPLv3.
- GitHub: [github.com/bartvdbraak](https://github.com/bartvdbraak) - `BSD-2-Clause`: Compatible with GPLv3.
- Email: bart@vanderbraak.nl - `ISC`: Compatible with GPLv3.
- `Python-2.0`: Compatible with GPLv3. (Note: Python has its own license, and version 2.0 is compatible with GPLv3).
Looking forward to hearing from you! 😊 - `CC-BY-4.0`: This is a Creative Commons license, which is not a software license. It's generally not recommended to include CC licenses in software projects due to potential compatibility issues. This might cause complications if you choose GPLv3.
- `CC0-1.0`: Not a software license, but it is explicitly designed to waive all copyrights, making it effectively compatible with GPLv3.
- `0BSD`: Compatible with GPLv3.
- `(MIT OR CC0-1.0)`: MIT is compatible with GPLv3, and CC0-1.0 is effectively compatible with GPLv3.

View file

@ -3,10 +3,7 @@ const tailwindcss = require('tailwindcss');
const autoprefixer = require('autoprefixer'); const autoprefixer = require('autoprefixer');
const config = { const config = {
plugins: [ plugins: [tailwindcss(), autoprefixer]
tailwindcss(),
autoprefixer
]
}; };
module.exports = config; module.exports = config;

View file

@ -1,20 +1,20 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.ico" /> <link rel="icon" href="%sveltekit.assets%/favicon.ico" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<link rel="apple-touch-icon" sizes="180x180" href="%sveltekit.assets%/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="%sveltekit.assets%/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="%sveltekit.assets%/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="%sveltekit.assets%/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="%sveltekit.assets%/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="%sveltekit.assets%/favicon-16x16.png" />
<link rel="manifest" href="%sveltekit.assets%/site.webmanifest"> <link rel="manifest" href="%sveltekit.assets%/site.webmanifest" />
<link rel="mask-icon" href="%sveltekit.assets%/safari-pinned-tab.svg" color="#5bbad5"> <link rel="mask-icon" href="%sveltekit.assets%/safari-pinned-tab.svg" color="#5bbad5" />
<meta name="msapplication-TileColor" content="#da532c"> <meta name="msapplication-TileColor" content="#da532c" />
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff" />
<title></title> <title></title>
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover"> <body data-sveltekit-preload-data="hover">
<div style="display: contents" class="h-full overflow-hidden">%sveltekit.body%</div> <div style="display: contents" class="h-full overflow-hidden">%sveltekit.body%</div>
</body> </body>
</html> </html>

View file

@ -1,4 +1,20 @@
html, html,
body { body {
@apply h-full overflow-hidden @apply h-full overflow-hidden;
}
.dark .logo-text-gradient-dark {
@apply from-logo-blue-start-dark to-logo-blue-stop-dark;
}
.logo-text-gradient-light {
@apply from-logo-blue-start-light to-logo-blue-stop-light;
}
.logo-text-gradient {
@apply bg-clip-text text-transparent box-decoration-clone;
/* Direction */
@apply bg-gradient-to-br;
/* Color Stops */
@apply logo-text-gradient-light logo-text-gradient-dark;
} }

View file

@ -1,13 +1,13 @@
export function calculateAge(birthdate: string): number { export function calculateAge(birthdate: string): number {
const birthDate = new Date(birthdate); const birthDate = new Date(birthdate);
const currentDate = new Date(); const currentDate = new Date();
let age = currentDate.getFullYear() - birthDate.getFullYear(); let age = currentDate.getFullYear() - birthDate.getFullYear();
const monthDiff = currentDate.getMonth() - birthDate.getMonth(); const monthDiff = currentDate.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && currentDate.getDate() < birthDate.getDate())) { if (monthDiff < 0 || (monthDiff === 0 && currentDate.getDate() < birthDate.getDate())) {
age--; age--;
} }
return age; return age;
} }

View file

@ -13,29 +13,47 @@
<AppBar> <AppBar>
<svelte:fragment slot="lead"> <svelte:fragment slot="lead">
<button aria-label="Toggle navigation menu" class="md:hidden btn btn-sm mr-4" on:click={drawerOpen}> <button
aria-label="Toggle navigation menu"
class="md:hidden btn btn-sm mr-4"
on:click={drawerOpen}
>
<span> <span>
<Hamburger /> <Hamburger />
</span> </span>
</button> </button>
<img src="./icon.svg" alt="Logo" srcset="" class="pr-2" /> <img width="32" height="24" src="./icon.svg" alt="Logo" srcset="" class="" />
<h2 class="code">hellob.art</h2> <h1 class="h6">
<span
class="bg-gradient-to-br logo-text-gradient bg-clip-text text-transparent box-decoration-clone font-mono font-bold tracking-tighter pl-3"
>hellob.art</span
>
</h1>
</svelte:fragment> </svelte:fragment>
<svelte:fragment slot="trail"> <svelte:fragment slot="trail">
<a <a
href="https://linkedin.com/in/bartvdbraak" href="https://linkedin.com/in/bartvdbraak"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="btn-icon btn-icon-sm hover:variant-soft-primary"><LinkedIn /><span class="sr-only">LinkedIn Profile of Bart van der Braak</span></a class="btn-icon btn-icon-sm hover:variant-soft-primary"
><LinkedIn /><span class="sr-only">LinkedIn Profile of Bart van der Braak</span></a
> >
<a <a
href="https://github.com/bartvdbraak" href="https://github.com/bartvdbraak"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="btn-icon btn-icon-sm hover:variant-soft-primary"><GitHub /><span class="sr-only">GitHub Profile of Bart van der Braak</span></a class="btn-icon btn-icon-sm hover:variant-soft-primary"
><GitHub /><span class="sr-only">GitHub Profile of Bart van der Braak</span></a
> >
<LightSwitch /> <LightSwitch />
</svelte:fragment> </svelte:fragment>
</AppBar> </AppBar>
<ProgressBar label="Progress Bar" value={progress} max={100} rounded="" /> <span id="progress-bar-label" class="sr-only">Loading Progress</span>
<ProgressBar
label="Progress Bar"
labelledby="progress-bar-label"
value={progress}
max={100}
rounded=""
/>

View file

@ -14,7 +14,8 @@
<ul> <ul>
{#each routes as route} {#each routes as route}
<li class="pb-2"> <li class="pb-2">
<a class="{classesActive(route.url)}" href={route.url} on:click={drawerClose}>{route.label}</a> <a class={classesActive(route.url)} href={route.url} on:click={drawerClose}>{route.label}</a
>
</li> </li>
{/each} {/each}
</ul> </ul>

View file

@ -16,11 +16,15 @@
<a class="card bg-initial card-hover overflow-hidden" href={link}> <a class="card bg-initial card-hover overflow-hidden" href={link}>
<header> <header>
<img src={headerImage} class="bg-black/50 w-full aspect-[21/9] object-cover object-top" alt="Post" /> <img
src={headerImage}
class="bg-black/50 w-full aspect-[21/9] object-cover object-top"
alt="Post"
/>
</header> </header>
<div class="p-4 space-y-4"> <div class="p-4 space-y-4">
<h6 class="h6">{headerSubTitle}</h6> <header class="h6">{headerSubTitle}</header>
<h3 class="h3" data-toc-ignore>{title}</h3> <span class="h3" data-toc-ignore>{title}</span>
<article> <article>
<p> <p>
{description} {description}

View file

@ -1 +1,15 @@
<svg class="inline-svg" stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg> <svg
class="inline-svg"
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
><path
d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"
/></svg
>

Before

Width:  |  Height:  |  Size: 517 B

After

Width:  |  Height:  |  Size: 529 B

View file

@ -1 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-menu"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg> <svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-menu"
><line x1="4" x2="20" y1="12" y2="12" /><line x1="4" x2="20" y1="6" y2="6" /><line
x1="4"
x2="20"
y1="18"
y2="18"
/></svg
>

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 352 B

View file

@ -1 +1,12 @@
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zM349.3 793.7H230.6V411.9h118.7v381.8zm-59.3-434a68.8 68.8 0 1 1 68.8-68.8c-.1 38-30.9 68.8-68.8 68.8zm503.7 434H675.1V608c0-44.3-.8-101.2-61.7-101.2-61.7 0-71.2 48.2-71.2 98v188.9H423.7V411.9h113.8v52.2h1.6c15.8-30 54.5-61.7 112.3-61.7 120.2 0 142.3 79.1 142.3 181.9v209.4z"></path></svg> <svg
stroke="currentColor"
fill="currentColor"
stroke-width="0"
viewBox="0 0 1024 1024"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
><path
d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zM349.3 793.7H230.6V411.9h118.7v381.8zm-59.3-434a68.8 68.8 0 1 1 68.8-68.8c-.1 38-30.9 68.8-68.8 68.8zm503.7 434H675.1V608c0-44.3-.8-101.2-61.7-101.2-61.7 0-71.2 48.2-71.2 98v188.9H423.7V411.9h113.8v52.2h1.6c15.8-30 54.5-61.7 112.3-61.7 120.2 0 142.3 79.1 142.3 181.9v209.4z"
/></svg
>

Before

Width:  |  Height:  |  Size: 555 B

After

Width:  |  Height:  |  Size: 564 B

View file

@ -1 +1,14 @@
<svg class="inline-svg" stroke="currentColor" fill="currentColor" stroke-width="0" role="img" viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><title></title><path d="M10.354 21.125a4.44 4.44 0 0 1-4.765-1.767 4.109 4.109 0 0 1-.703-3.107 3.898 3.898 0 0 1 .134-.522l.105-.321.287.21a7.21 7.21 0 0 0 2.186 1.092l.208.063-.02.208a1.253 1.253 0 0 0 .226.83 1.337 1.337 0 0 0 1.435.533 1.231 1.231 0 0 0 .343-.15l5.59-3.562a1.164 1.164 0 0 0 .524-.778 1.242 1.242 0 0 0-.211-.937 1.338 1.338 0 0 0-1.435-.533 1.23 1.23 0 0 0-.343.15l-2.133 1.36a4.078 4.078 0 0 1-1.135.499 4.44 4.44 0 0 1-4.765-1.766 4.108 4.108 0 0 1-.702-3.108 3.855 3.855 0 0 1 1.742-2.582l5.589-3.563a4.072 4.072 0 0 1 1.135-.499 4.44 4.44 0 0 1 4.765 1.767 4.109 4.109 0 0 1 .703 3.107 3.943 3.943 0 0 1-.134.522l-.105.321-.286-.21a7.204 7.204 0 0 0-2.187-1.093l-.208-.063.02-.207a1.255 1.255 0 0 0-.226-.831 1.337 1.337 0 0 0-1.435-.532 1.231 1.231 0 0 0-.343.15L8.62 9.368a1.162 1.162 0 0 0-.524.778 1.24 1.24 0 0 0 .211.937 1.338 1.338 0 0 0 1.435.533 1.235 1.235 0 0 0 .344-.151l2.132-1.36a4.067 4.067 0 0 1 1.135-.498 4.44 4.44 0 0 1 4.765 1.766 4.108 4.108 0 0 1 .702 3.108 3.857 3.857 0 0 1-1.742 2.583l-5.589 3.562a4.072 4.072 0 0 1-1.135.499m10.358-17.95C18.484-.015 14.082-.96 10.9 1.068L5.31 4.63a6.412 6.412 0 0 0-2.896 4.295 6.753 6.753 0 0 0 .666 4.336 6.43 6.43 0 0 0-.96 2.396 6.833 6.833 0 0 0 1.168 5.167c2.229 3.19 6.63 4.135 9.812 2.108l5.59-3.562a6.41 6.41 0 0 0 2.896-4.295 6.756 6.756 0 0 0-.665-4.336 6.429 6.429 0 0 0 .958-2.396 6.831 6.831 0 0 0-1.167-5.168Z"></path></svg> <svg
class="inline-svg"
stroke="currentColor"
fill="currentColor"
stroke-width="0"
role="img"
viewBox="0 0 24 24"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
><title /><path
d="M10.354 21.125a4.44 4.44 0 0 1-4.765-1.767 4.109 4.109 0 0 1-.703-3.107 3.898 3.898 0 0 1 .134-.522l.105-.321.287.21a7.21 7.21 0 0 0 2.186 1.092l.208.063-.02.208a1.253 1.253 0 0 0 .226.83 1.337 1.337 0 0 0 1.435.533 1.231 1.231 0 0 0 .343-.15l5.59-3.562a1.164 1.164 0 0 0 .524-.778 1.242 1.242 0 0 0-.211-.937 1.338 1.338 0 0 0-1.435-.533 1.23 1.23 0 0 0-.343.15l-2.133 1.36a4.078 4.078 0 0 1-1.135.499 4.44 4.44 0 0 1-4.765-1.766 4.108 4.108 0 0 1-.702-3.108 3.855 3.855 0 0 1 1.742-2.582l5.589-3.563a4.072 4.072 0 0 1 1.135-.499 4.44 4.44 0 0 1 4.765 1.767 4.109 4.109 0 0 1 .703 3.107 3.943 3.943 0 0 1-.134.522l-.105.321-.286-.21a7.204 7.204 0 0 0-2.187-1.093l-.208-.063.02-.207a1.255 1.255 0 0 0-.226-.831 1.337 1.337 0 0 0-1.435-.532 1.231 1.231 0 0 0-.343.15L8.62 9.368a1.162 1.162 0 0 0-.524.778 1.24 1.24 0 0 0 .211.937 1.338 1.338 0 0 0 1.435.533 1.235 1.235 0 0 0 .344-.151l2.132-1.36a4.067 4.067 0 0 1 1.135-.498 4.44 4.44 0 0 1 4.765 1.766 4.108 4.108 0 0 1 .702 3.108 3.857 3.857 0 0 1-1.742 2.583l-5.589 3.562a4.072 4.072 0 0 1-1.135.499m10.358-17.95C18.484-.015 14.082-.96 10.9 1.068L5.31 4.63a6.412 6.412 0 0 0-2.896 4.295 6.753 6.753 0 0 0 .666 4.336 6.43 6.43 0 0 0-.96 2.396 6.833 6.833 0 0 0 1.168 5.167c2.229 3.19 6.63 4.135 9.812 2.108l5.59-3.562a6.41 6.41 0 0 0 2.896-4.295 6.756 6.756 0 0 0-.665-4.336 6.429 6.429 0 0 0 .958-2.396 6.831 6.831 0 0 0-1.167-5.168Z"
/></svg
>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -1 +1,13 @@
<svg class="inline-svg" stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M3 19h18l-9 -15z"></path></svg> <svg
class="inline-svg"
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M3 19h18l-9 -15z" /></svg
>

Before

Width:  |  Height:  |  Size: 299 B

After

Width:  |  Height:  |  Size: 303 B

View file

@ -5,77 +5,82 @@ const vitalsUrl = 'https://vitals.vercel-analytics.com/v1/vitals';
// Improve type safety by defining the navigator.connection type // Improve type safety by defining the navigator.connection type
interface NavigatorWithConnection extends Navigator { interface NavigatorWithConnection extends Navigator {
connection: { connection: {
effectiveType: string; effectiveType: string;
}; };
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
type Params = Record<string, any>; // Define a type for 'params' type Params = Record<string, any>; // Define a type for 'params'
function getConnectionSpeed() { function getConnectionSpeed() {
return 'connection' in navigator && 'connection' && 'effectiveType' in (navigator as NavigatorWithConnection).connection return 'connection' in navigator &&
? (navigator as NavigatorWithConnection).connection.effectiveType 'connection' &&
: ''; 'effectiveType' in (navigator as NavigatorWithConnection).connection
? (navigator as NavigatorWithConnection).connection.effectiveType
: '';
} }
function sendToAnalytics(metric: Metric, options: { function sendToAnalytics(
params: Params; metric: Metric,
path: string; options: {
analyticsId: string; params: Params;
debug: boolean; path: string;
}) { analyticsId: string;
const page = Object.entries(options.params).reduce( debug: boolean;
(acc, [key, value]) => acc.replace(value, `[${key}]`), }
options.path ) {
); const page = Object.entries(options.params).reduce(
(acc, [key, value]) => acc.replace(value, `[${key}]`),
options.path
);
const body = { const body = {
dsn: options.analyticsId, dsn: options.analyticsId,
id: metric.id, id: metric.id,
page, page,
href: location.href, href: location.href,
event_name: metric.name, event_name: metric.name,
value: metric.value.toString(), value: metric.value.toString(),
speed: getConnectionSpeed(), speed: getConnectionSpeed()
}; };
if (options.debug) { if (options.debug) {
console.log('[Web Vitals]', metric.name, JSON.stringify(body, null, 2)); console.log('[Web Vitals]', metric.name, JSON.stringify(body, null, 2));
} }
// Serialize body to a URLSearchParams object // Serialize body to a URLSearchParams object
const searchParams = new URLSearchParams(body); const searchParams = new URLSearchParams(body);
// The type 'Record<string, string>' is compatible with 'URLSearchParams' // The type 'Record<string, string>' is compatible with 'URLSearchParams'
const blob = new Blob([searchParams.toString()], { const blob = new Blob([searchParams.toString()], {
type: 'application/x-www-form-urlencoded', type: 'application/x-www-form-urlencoded'
}); });
if (navigator.sendBeacon) { if (navigator.sendBeacon) {
navigator.sendBeacon(vitalsUrl, blob); navigator.sendBeacon(vitalsUrl, blob);
} else { } else {
fetch(vitalsUrl, { fetch(vitalsUrl, {
body: blob, body: blob,
method: 'POST', method: 'POST',
credentials: 'omit', credentials: 'omit',
keepalive: true, keepalive: true
}); });
} }
} }
export function webVitals(options: { export function webVitals(options: {
params: Params; // Use the defined 'Params' type here params: Params; // Use the defined 'Params' type here
path: string; path: string;
analyticsId: string; analyticsId: string;
debug: boolean; debug: boolean;
}) { }) {
try { try {
getFID((metric) => sendToAnalytics(metric, options)); getFID((metric) => sendToAnalytics(metric, options));
getTTFB((metric) => sendToAnalytics(metric, options)); getTTFB((metric) => sendToAnalytics(metric, options));
getLCP((metric) => sendToAnalytics(metric, options)); getLCP((metric) => sendToAnalytics(metric, options));
getCLS((metric) => sendToAnalytics(metric, options)); getCLS((metric) => sendToAnalytics(metric, options));
getFCP((metric) => sendToAnalytics(metric, options)); getFCP((metric) => sendToAnalytics(metric, options));
} catch (err) { } catch (err) {
console.error('[Web Vitals]', err); console.error('[Web Vitals]', err);
} }
} }

View file

@ -30,7 +30,7 @@
let routes = [ let routes = [
{ url: '/', label: 'Home' }, { url: '/', label: 'Home' },
{ url: '/projects', label: 'Projects' }, { url: '/projects', label: 'Projects' },
{ url: '/tools', label: 'Tools' }, { url: '/tools', label: 'Tools' }
// { url: '/blog', label: 'Blog' } // { url: '/blog', label: 'Blog' }
]; ];

View file

@ -5,7 +5,10 @@
<svelte:head> <svelte:head>
<title>hellob.art &mdash; home</title> <title>hellob.art &mdash; home</title>
<meta name="description" content="Meet Bart, a passionate DevOps engineer from Zaandam, Netherlands. With expertise in Azure, Kubernetes, and automation, he loves solving challenges through code. Discover his journey, interests in cats and whiskey, and how to connect with him for exciting collaborations."> <meta
name="description"
content="Meet Bart, a passionate DevOps engineer from Zaandam, Netherlands. With expertise in Azure, Kubernetes, and automation, he loves solving challenges through code. Discover his journey, interests in cats and whiskey, and how to connect with him for exciting collaborations."
/>
</svelte:head> </svelte:head>
<main class="container mx-auto px-4 py-8 text-left"> <main class="container mx-auto px-4 py-8 text-left">
@ -38,7 +41,11 @@
</p> </p>
</div> </div>
<div class="md:col-span-1 flex justify-end"> <div class="md:col-span-1 flex justify-end">
<img src={picture} alt="Bart van der Braak with a noire effect" class="max-w-1/3 mb-4 object-cover" /> <img
src={picture}
alt="Bart van der Braak with a noire effect"
class="max-w-1/3 mb-4 object-cover"
/>
</div> </div>
</div> </div>
@ -46,11 +53,11 @@
<p class="text-lg leading-relaxed mb-8"> <p class="text-lg leading-relaxed mb-8">
As a DevOps engineer, I thrive on solving complex challenges with the power of code and As a DevOps engineer, I thrive on solving complex challenges with the power of code and
automation. My passion for streamlining workflows led me to create internal tooling using automation. My passion for streamlining workflows led me to create internal tooling using APIs,
APIs, boosting productivity for myself and my colleagues. Outside of work, I enjoy taking on boosting productivity for myself and my colleagues. Outside of work, I enjoy taking on side
side projects that push my boundaries, expanding my skill set, and exploring new projects that push my boundaries, expanding my skill set, and exploring new technologies. I
technologies. I strongly believe that innovation and continuous learning are key drivers of strongly believe that innovation and continuous learning are key drivers of success in the
success in the ever-evolving tech landscape. ever-evolving tech landscape.
</p> </p>
<h2 class="text-3xl font-bold mb-4">Cat Lover and Whiskey Enthusiast</h2> <h2 class="text-3xl font-bold mb-4">Cat Lover and Whiskey Enthusiast</h2>

View file

@ -1,6 +1,6 @@
<script> <script>
/** @type {import('./$types').PageData} */ /** @type {import('./$types').PageData} */
export let data; export let data;
</script> </script>
<svelte:head> <svelte:head>

View file

@ -49,7 +49,10 @@
<svelte:head> <svelte:head>
<title>hellob.art &mdash; projects</title> <title>hellob.art &mdash; projects</title>
<meta name="description" content="Explore a diverse collection of web applications and virtual tours in the portfolio of a passionate DevOps engineer. Discover innovative projects in React, Golang, Next.js, and more."> <meta
name="description"
content="Explore a diverse collection of web applications and virtual tours in the portfolio of a passionate DevOps engineer. Discover innovative projects in React, Golang, Next.js, and more."
/>
</svelte:head> </svelte:head>
<main class="container mx-auto px-4 py-8 text-left"> <main class="container mx-auto px-4 py-8 text-left">

View file

@ -2,7 +2,7 @@
<script lang="ts"> <script lang="ts">
import { Canvas } from '@threlte/core'; import { Canvas } from '@threlte/core';
import { T } from '@threlte/core'; import { T } from '@threlte/core';
import { ContactShadows, Float, Grid, OrbitControls } from '@threlte/extras'; import { ContactShadows, Float, OrbitControls } from '@threlte/extras';
import Github from './models/Github.svelte'; import Github from './models/Github.svelte';
import TerraformFlat from './models/TerraformFlat.svelte'; import TerraformFlat from './models/TerraformFlat.svelte';
import Kubernetes from './models/Kubernetes.svelte'; import Kubernetes from './models/Kubernetes.svelte';
@ -11,7 +11,10 @@
<svelte:head> <svelte:head>
<title>hellob.art &mdash; tools</title> <title>hellob.art &mdash; tools</title>
<meta name="description" content="Explore essential DevOps tools like Kubernetes, Terraform, Warp, and version control platforms GitHub, Azure DevOps, and GitLab."> <meta
name="description"
content="Explore essential DevOps tools like Kubernetes, Terraform, Warp, and version control platforms GitHub, Azure DevOps, and GitLab."
/>
</svelte:head> </svelte:head>
<main class="container mx-auto px-4 py-8 text-left"> <main class="container mx-auto px-4 py-8 text-left">
@ -56,15 +59,6 @@
<T.DirectionalLight intensity={0.5} position.x={5} position.y={3} /> <T.DirectionalLight intensity={0.5} position.x={5} position.y={3} />
<T.AmbientLight intensity={0.2} /> <T.AmbientLight intensity={0.2} />
<!-- <Grid
position.y={-0.001}
cellColor="#ffffff"
sectionColor="#ffffff"
sectionThickness={0}
fadeDistance={40}
cellSize={2}
/> -->
<ContactShadows scale={10} blur={2} far={2.5} opacity={0.5} /> <ContactShadows scale={10} blur={2} far={2.5} opacity={0.5} />
<Float floatIntensity={1} floatingRange={[0, 1]}> <Float floatIntensity={1} floatingRange={[0, 1]}>

View file

@ -4,25 +4,25 @@ Command: npx @threlte/gltf@1.0.0-next.13 ./src/lib/assets/vectors/github.glb --t
--> -->
<script> <script>
import { Group } from 'three' import { Group } from 'three';
import { T, forwardEventHandlers } from '@threlte/core' import { T, forwardEventHandlers } from '@threlte/core';
import { useGltf } from '@threlte/extras' import { useGltf } from '@threlte/extras';
export const ref = new Group() export const ref = new Group();
const gltf = useGltf('/models/github-transformed.glb', { useDraco: true }) const gltf = useGltf('/models/github-transformed.glb', { useDraco: true });
const component = forwardEventHandlers() const component = forwardEventHandlers();
</script> </script>
<T is={ref} dispose={false} {...$$restProps} bind:this={$component}> <T is={ref} dispose={false} {...$$restProps} bind:this={$component}>
{#await gltf} {#await gltf}
<slot name="fallback" /> <slot name="fallback" />
{:then gltf} {:then gltf}
<T.Mesh geometry={gltf.nodes.Github_Mesh.geometry} material={gltf.materials['SVGMat.001']} /> <T.Mesh geometry={gltf.nodes.Github_Mesh.geometry} material={gltf.materials['SVGMat.001']} />
{:catch error} {:catch error}
<slot name="error" {error} /> <slot name="error" {error} />
{/await} {/await}
<slot {ref} /> <slot {ref} />
</T> </T>

View file

@ -4,34 +4,34 @@ Command: npx @threlte/gltf@1.0.0-next.13 ./static/models/kubernetes.glb --transf
--> -->
<script> <script>
import { Group } from 'three' import { Group } from 'three';
import { T, forwardEventHandlers } from '@threlte/core' import { T, forwardEventHandlers } from '@threlte/core';
import { useGltf } from '@threlte/extras' import { useGltf } from '@threlte/extras';
export const ref = new Group() export const ref = new Group();
const gltf = useGltf('/models/kubernetes-transformed.glb', { useDraco: true }) const gltf = useGltf('/models/kubernetes-transformed.glb', { useDraco: true });
const component = forwardEventHandlers() const component = forwardEventHandlers();
</script> </script>
<T is={ref} dispose={false} {...$$restProps} bind:this={$component}> <T is={ref} dispose={false} {...$$restProps} bind:this={$component}>
{#await gltf} {#await gltf}
<slot name="fallback" /> <slot name="fallback" />
{:then gltf} {:then gltf}
<T.Mesh <T.Mesh
geometry={gltf.nodes.Curve.geometry} geometry={gltf.nodes.Curve.geometry}
material={gltf.materials['SVGMat.006']} material={gltf.materials['SVGMat.006']}
rotation={[Math.PI / 2, 0, 0.9]} rotation={[Math.PI / 2, 0, 0.9]}
/> />
<T.Mesh <T.Mesh
geometry={gltf.nodes.Curve001.geometry} geometry={gltf.nodes.Curve001.geometry}
material={gltf.materials['SVGMat.007']} material={gltf.materials['SVGMat.007']}
rotation={[Math.PI / 2, 0, 0.9]} rotation={[Math.PI / 2, 0, 0.9]}
/> />
{:catch error} {:catch error}
<slot name="error" {error} /> <slot name="error" {error} />
{/await} {/await}
<slot {ref} /> <slot {ref} />
</T> </T>

View file

@ -4,28 +4,28 @@ Command: npx @threlte/gltf@1.0.0-next.13 ./static/models/terraform-flat.glb --tr
--> -->
<script> <script>
import { Group } from 'three' import { Group } from 'three';
import { T, forwardEventHandlers } from '@threlte/core' import { T, forwardEventHandlers } from '@threlte/core';
import { useGltf } from '@threlte/extras' import { useGltf } from '@threlte/extras';
export const ref = new Group() export const ref = new Group();
const gltf = useGltf('/models/terraform-flat-transformed.glb', { useDraco: true }) const gltf = useGltf('/models/terraform-flat-transformed.glb', { useDraco: true });
const component = forwardEventHandlers() const component = forwardEventHandlers();
</script> </script>
<T is={ref} dispose={false} {...$$restProps} bind:this={$component}> <T is={ref} dispose={false} {...$$restProps} bind:this={$component}>
{#await gltf} {#await gltf}
<slot name="fallback" /> <slot name="fallback" />
{:then gltf} {:then gltf}
<T.Group rotation={[Math.PI / 2, 0, 5]}> <T.Group rotation={[Math.PI / 2, 0, 5]}>
<T.Mesh geometry={gltf.nodes.Curve_1.geometry} material={gltf.materials.SVGMat} /> <T.Mesh geometry={gltf.nodes.Curve_1.geometry} material={gltf.materials.SVGMat} />
<T.Mesh geometry={gltf.nodes.Curve_2.geometry} material={gltf.materials['SVGMat.001']} /> <T.Mesh geometry={gltf.nodes.Curve_2.geometry} material={gltf.materials['SVGMat.001']} />
</T.Group> </T.Group>
{:catch error} {:catch error}
<slot name="error" {error} /> <slot name="error" {error} />
{/await} {/await}
<slot {ref} /> <slot {ref} />
</T> </T>

View file

@ -4,26 +4,34 @@ Command: npx @threlte/gltf@1.0.0-next.13 ./static/models/warp.glb --transform
--> -->
<script> <script>
import { Group } from 'three' import { Group } from 'three';
import { T, forwardEventHandlers } from '@threlte/core' import { T, forwardEventHandlers } from '@threlte/core';
import { useGltf } from '@threlte/extras' import { useGltf } from '@threlte/extras';
export const ref = new Group() export const ref = new Group();
const gltf = useGltf('/models/warp-transformed.glb', { useDraco: true }) const gltf = useGltf('/models/warp-transformed.glb', { useDraco: true });
const component = forwardEventHandlers() const component = forwardEventHandlers();
</script> </script>
<T is={ref} dispose={false} {...$$restProps} bind:this={$component}> <T is={ref} dispose={false} {...$$restProps} bind:this={$component}>
{#await gltf} {#await gltf}
<slot name="fallback" /> <slot name="fallback" />
{:then gltf} {:then gltf}
<T.Mesh geometry={gltf.nodes.Warp.geometry} material={gltf.materials.SVGMat} rotation={[Math.PI / 2, 0, 0.3]} /> <T.Mesh
<T.Mesh geometry={gltf.nodes.Warp001.geometry} material={gltf.materials.Gradient} rotation={[Math.PI / 2, 0, 0.3]} /> geometry={gltf.nodes.Warp.geometry}
{:catch error} material={gltf.materials.SVGMat}
<slot name="error" {error} /> rotation={[Math.PI / 2, 0, 0.3]}
{/await} />
<T.Mesh
geometry={gltf.nodes.Warp001.geometry}
material={gltf.materials.Gradient}
rotation={[Math.PI / 2, 0, 0.3]}
/>
{:catch error}
<slot name="error" {error} />
{/await}
<slot {ref} /> <slot {ref} />
</T> </T>

View file

@ -1,98 +0,0 @@
:root {
/* =~= Theme Properties =~= */
--theme-font-family-base: system-ui;
--theme-font-family-heading: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--theme-font-color-base: 0 0 0;
--theme-font-color-dark: 255 255 255;
--theme-rounded-base: 4px;
--theme-rounded-container: 12px;
--theme-border-base: 2px;
/* =~= Theme On-X Colors =~= */
--on-primary: 0 0 0;
--on-secondary: 255 255 255;
--on-tertiary: 0 0 0;
--on-success: 0 0 0;
--on-warning: 0 0 0;
--on-error: 255 255 255;
--on-surface: 255 255 255;
/* =~= Theme Colors =~= */
/* primary | #67a1ba */
--color-primary-50: 232 241 245; /* ⬅ #e8f1f5 */
--color-primary-100: 225 236 241; /* ⬅ #e1ecf1 */
--color-primary-200: 217 232 238; /* ⬅ #d9e8ee */
--color-primary-300: 194 217 227; /* ⬅ #c2d9e3 */
--color-primary-400: 149 189 207; /* ⬅ #95bdcf */
--color-primary-500: 103 161 186; /* ⬅ #67a1ba */
--color-primary-600: 93 145 167; /* ⬅ #5d91a7 */
--color-primary-700: 77 121 140; /* ⬅ #4d798c */
--color-primary-800: 62 97 112; /* ⬅ #3e6170 */
--color-primary-900: 50 79 91; /* ⬅ #324f5b */
/* secondary | #4F46E5 */
--color-secondary-50: 229 227 251; /* ⬅ #e5e3fb */
--color-secondary-100: 220 218 250; /* ⬅ #dcdafa */
--color-secondary-200: 211 209 249; /* ⬅ #d3d1f9 */
--color-secondary-300: 185 181 245; /* ⬅ #b9b5f5 */
--color-secondary-400: 132 126 237; /* ⬅ #847eed */
--color-secondary-500: 79 70 229; /* ⬅ #4F46E5 */
--color-secondary-600: 71 63 206; /* ⬅ #473fce */
--color-secondary-700: 59 53 172; /* ⬅ #3b35ac */
--color-secondary-800: 47 42 137; /* ⬅ #2f2a89 */
--color-secondary-900: 39 34 112; /* ⬅ #272270 */
/* tertiary | #0EA5E9 */
--color-tertiary-50: 219 242 252; /* ⬅ #dbf2fc */
--color-tertiary-100: 207 237 251; /* ⬅ #cfedfb */
--color-tertiary-200: 195 233 250; /* ⬅ #c3e9fa */
--color-tertiary-300: 159 219 246; /* ⬅ #9fdbf6 */
--color-tertiary-400: 86 192 240; /* ⬅ #56c0f0 */
--color-tertiary-500: 14 165 233; /* ⬅ #0EA5E9 */
--color-tertiary-600: 13 149 210; /* ⬅ #0d95d2 */
--color-tertiary-700: 11 124 175; /* ⬅ #0b7caf */
--color-tertiary-800: 8 99 140; /* ⬅ #08638c */
--color-tertiary-900: 7 81 114; /* ⬅ #075172 */
/* success | #84cc16 */
--color-success-50: 237 247 220; /* ⬅ #edf7dc */
--color-success-100: 230 245 208; /* ⬅ #e6f5d0 */
--color-success-200: 224 242 197; /* ⬅ #e0f2c5 */
--color-success-300: 206 235 162; /* ⬅ #ceeba2 */
--color-success-400: 169 219 92; /* ⬅ #a9db5c */
--color-success-500: 132 204 22; /* ⬅ #84cc16 */
--color-success-600: 119 184 20; /* ⬅ #77b814 */
--color-success-700: 99 153 17; /* ⬅ #639911 */
--color-success-800: 79 122 13; /* ⬅ #4f7a0d */
--color-success-900: 65 100 11; /* ⬅ #41640b */
/* warning | #EAB308 */
--color-warning-50: 252 244 218; /* ⬅ #fcf4da */
--color-warning-100: 251 240 206; /* ⬅ #fbf0ce */
--color-warning-200: 250 236 193; /* ⬅ #faecc1 */
--color-warning-300: 247 225 156; /* ⬅ #f7e19c */
--color-warning-400: 240 202 82; /* ⬅ #f0ca52 */
--color-warning-500: 234 179 8; /* ⬅ #EAB308 */
--color-warning-600: 211 161 7; /* ⬅ #d3a107 */
--color-warning-700: 176 134 6; /* ⬅ #b08606 */
--color-warning-800: 140 107 5; /* ⬅ #8c6b05 */
--color-warning-900: 115 88 4; /* ⬅ #735804 */
/* error | #d31922 */
--color-error-50: 248 221 222; /* ⬅ #f8ddde */
--color-error-100: 246 209 211; /* ⬅ #f6d1d3 */
--color-error-200: 244 198 200; /* ⬅ #f4c6c8 */
--color-error-300: 237 163 167; /* ⬅ #eda3a7 */
--color-error-400: 224 94 100; /* ⬅ #e05e64 */
--color-error-500: 211 25 34; /* ⬅ #d31922 */
--color-error-600: 190 23 31; /* ⬅ #be171f */
--color-error-700: 158 19 26; /* ⬅ #9e131a */
--color-error-800: 127 15 20; /* ⬅ #7f0f14 */
--color-error-900: 103 12 17; /* ⬅ #670c11 */
/* surface | #063142 */
--color-surface-50: 218 224 227; /* ⬅ #dae0e3 */
--color-surface-100: 205 214 217; /* ⬅ #cdd6d9 */
--color-surface-200: 193 204 208; /* ⬅ #c1ccd0 */
--color-surface-300: 155 173 179; /* ⬅ #9badb3 */
--color-surface-400: 81 111 123; /* ⬅ #516f7b */
--color-surface-500: 6 49 66; /* ⬅ #063142 */
--color-surface-600: 5 44 59; /* ⬅ #052c3b */
--color-surface-700: 5 37 50; /* ⬅ #052532 */
--color-surface-800: 4 29 40; /* ⬅ #041d28 */
--color-surface-900: 3 24 32; /* ⬅ #031820 */
}

View file

@ -1,19 +1,19 @@
{ {
"name": "", "name": "",
"short_name": "", "short_name": "",
"icons": [ "icons": [
{ {
"src": "/android-chrome-192x192.png", "src": "/android-chrome-192x192.png",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png" "type": "image/png"
}, },
{ {
"src": "/android-chrome-512x512.png", "src": "/android-chrome-512x512.png",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png" "type": "image/png"
} }
], ],
"theme_color": "#ffffff", "theme_color": "#ffffff",
"background_color": "#ffffff", "background_color": "#ffffff",
"display": "standalone" "display": "standalone"
} }

View file

@ -4,15 +4,29 @@ module.exports = {
darkMode: 'class', darkMode: 'class',
content: [ content: [
'./src/**/*.{html,js,svelte,ts}', './src/**/*.{html,js,svelte,ts}',
require('path').join(require.resolve( require('path').join(require.resolve('@skeletonlabs/skeleton'), '../**/*.{html,js,svelte,ts}')
'@skeletonlabs/skeleton'),
'../**/*.{html,js,svelte,ts}'
)
], ],
theme: { theme: {
extend: {}, extend: {
colors: {
'logo-blue-start': {
light: '#314755',
DEFAULT: '#314755',
dark: '#7196AD'
},
'logo-blue-stop': {
light: '#26a0da',
DEFAULT: '#26a0da',
dark: '#7CC6E9'
}
},
dark: {
// <-- Add this section for dark mode classes
'logo-text-gradient-dark': {
'@apply': 'from-logo-blue-start-dark to-logo-blue-stop-dark'
}
}
}
}, },
plugins: [ plugins: [...require('@skeletonlabs/skeleton/tailwind/skeleton.cjs')()]
...require('@skeletonlabs/skeleton/tailwind/skeleton.cjs')() };
]
}

View file

@ -3,10 +3,10 @@ import { defineConfig } from 'vite';
export default defineConfig({ export default defineConfig({
plugins: [sveltekit()], plugins: [sveltekit()],
ssr: { ssr: {
noExternal: ['three'] noExternal: ['three']
}, },
define: { define: {
'import.meta.env.VERCEL_ANALYTICS_ID': JSON.stringify(process.env.VERCEL_ANALYTICS_ID) 'import.meta.env.VERCEL_ANALYTICS_ID': JSON.stringify(process.env.VERCEL_ANALYTICS_ID)
} }
}); });