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
updates:
- package-ecosystem: "github-actions"
directory: "/"
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: "weekly"
interval: 'weekly'
reviewers:
- "bartvdbraak"
- 'bartvdbraak'

View file

@ -1,4 +1,5 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"]
}
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"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
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.unlighthouse

View file

@ -1,6 +1,6 @@
<div align="center">
<h1 align="center">hellob.art</h1>
<h5>a simple portfolio</h5>
<h5>personal website built with Svelte</h5>
</div>
<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>
</div>
<div align="center">
<a href="https://hellob.art?ref=github">hellob.art</a>
</div>
<br/>
## Installation
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.
- **Tailwind CSS:** A utility-first CSS framework packed with classes.
- **Skeleton:** UI Toolkit for Svelte + Tailwind.
## Deployment
The portfolio is hosted using [Vercel](https://vercel.com). You can access it at [https://hellob.art](https://hellob.art).
- **Threlte:** Declarative Three.js for Svelte.
## 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!
## Get in Touch
Some dependencies may hold different licenses but are in compliance with GPLv3:
Let's connect! You can find me on:
- Website: [hellob.art](https://hellob.art)
- GitHub: [github.com/bartvdbraak](https://github.com/bartvdbraak)
- Email: bart@vanderbraak.nl
Looking forward to hearing from you! 😊
- `MIT`: Compatible with GPLv3.
- `Apache 2.0`: Compatible with GPLv3.
- `BSD-3-Clause`: Compatible with GPLv3.
- `BSD-2-Clause`: Compatible with GPLv3.
- `ISC`: Compatible with GPLv3.
- `Python-2.0`: Compatible with GPLv3. (Note: Python has its own license, and version 2.0 is compatible with GPLv3).
- `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 config = {
plugins: [
tailwindcss(),
autoprefixer
]
plugins: [tailwindcss(), autoprefixer]
};
module.exports = config;

View file

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

View file

@ -1,4 +1,20 @@
html,
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 {
const birthDate = new Date(birthdate);
const currentDate = new Date();
let age = currentDate.getFullYear() - birthDate.getFullYear();
const monthDiff = currentDate.getMonth() - birthDate.getMonth();
const birthDate = new Date(birthdate);
const currentDate = new Date();
if (monthDiff < 0 || (monthDiff === 0 && currentDate.getDate() < birthDate.getDate())) {
age--;
}
let age = currentDate.getFullYear() - birthDate.getFullYear();
const monthDiff = currentDate.getMonth() - birthDate.getMonth();
return age;
if (monthDiff < 0 || (monthDiff === 0 && currentDate.getDate() < birthDate.getDate())) {
age--;
}
return age;
}

View file

@ -13,29 +13,47 @@
<AppBar>
<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>
<Hamburger />
</span>
</button>
<img src="./icon.svg" alt="Logo" srcset="" class="pr-2" />
<h2 class="code">hellob.art</h2>
<img width="32" height="24" src="./icon.svg" alt="Logo" srcset="" class="" />
<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 slot="trail">
<a
href="https://linkedin.com/in/bartvdbraak"
target="_blank"
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
href="https://github.com/bartvdbraak"
target="_blank"
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 />
</svelte:fragment>
</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>
{#each routes as route}
<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>
{/each}
</ul>

View file

@ -16,11 +16,15 @@
<a class="card bg-initial card-hover overflow-hidden" href={link}>
<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>
<div class="p-4 space-y-4">
<h6 class="h6">{headerSubTitle}</h6>
<h3 class="h3" data-toc-ignore>{title}</h3>
<header class="h6">{headerSubTitle}</header>
<span class="h3" data-toc-ignore>{title}</span>
<article>
<p>
{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
interface NavigatorWithConnection extends Navigator {
connection: {
effectiveType: string;
};
connection: {
effectiveType: string;
};
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Params = Record<string, any>; // Define a type for 'params'
function getConnectionSpeed() {
return 'connection' in navigator && 'connection' && 'effectiveType' in (navigator as NavigatorWithConnection).connection
? (navigator as NavigatorWithConnection).connection.effectiveType
: '';
return 'connection' in navigator &&
'connection' &&
'effectiveType' in (navigator as NavigatorWithConnection).connection
? (navigator as NavigatorWithConnection).connection.effectiveType
: '';
}
function sendToAnalytics(metric: Metric, options: {
params: Params;
path: string;
analyticsId: string;
debug: boolean;
}) {
const page = Object.entries(options.params).reduce(
(acc, [key, value]) => acc.replace(value, `[${key}]`),
options.path
);
function sendToAnalytics(
metric: Metric,
options: {
params: Params;
path: string;
analyticsId: string;
debug: boolean;
}
) {
const page = Object.entries(options.params).reduce(
(acc, [key, value]) => acc.replace(value, `[${key}]`),
options.path
);
const body = {
dsn: options.analyticsId,
id: metric.id,
page,
href: location.href,
event_name: metric.name,
value: metric.value.toString(),
speed: getConnectionSpeed(),
};
const body = {
dsn: options.analyticsId,
id: metric.id,
page,
href: location.href,
event_name: metric.name,
value: metric.value.toString(),
speed: getConnectionSpeed()
};
if (options.debug) {
console.log('[Web Vitals]', metric.name, JSON.stringify(body, null, 2));
}
if (options.debug) {
console.log('[Web Vitals]', metric.name, JSON.stringify(body, null, 2));
}
// Serialize body to a URLSearchParams object
const searchParams = new URLSearchParams(body);
// Serialize body to a URLSearchParams object
const searchParams = new URLSearchParams(body);
// The type 'Record<string, string>' is compatible with 'URLSearchParams'
const blob = new Blob([searchParams.toString()], {
type: 'application/x-www-form-urlencoded',
});
if (navigator.sendBeacon) {
navigator.sendBeacon(vitalsUrl, blob);
} else {
fetch(vitalsUrl, {
body: blob,
method: 'POST',
credentials: 'omit',
keepalive: true,
});
}
// The type 'Record<string, string>' is compatible with 'URLSearchParams'
const blob = new Blob([searchParams.toString()], {
type: 'application/x-www-form-urlencoded'
});
if (navigator.sendBeacon) {
navigator.sendBeacon(vitalsUrl, blob);
} else {
fetch(vitalsUrl, {
body: blob,
method: 'POST',
credentials: 'omit',
keepalive: true
});
}
}
export function webVitals(options: {
params: Params; // Use the defined 'Params' type here
path: string;
analyticsId: string;
debug: boolean;
params: Params; // Use the defined 'Params' type here
path: string;
analyticsId: string;
debug: boolean;
}) {
try {
getFID((metric) => sendToAnalytics(metric, options));
getTTFB((metric) => sendToAnalytics(metric, options));
getLCP((metric) => sendToAnalytics(metric, options));
getCLS((metric) => sendToAnalytics(metric, options));
getFCP((metric) => sendToAnalytics(metric, options));
} catch (err) {
console.error('[Web Vitals]', err);
}
try {
getFID((metric) => sendToAnalytics(metric, options));
getTTFB((metric) => sendToAnalytics(metric, options));
getLCP((metric) => sendToAnalytics(metric, options));
getCLS((metric) => sendToAnalytics(metric, options));
getFCP((metric) => sendToAnalytics(metric, options));
} catch (err) {
console.error('[Web Vitals]', err);
}
}

View file

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

View file

@ -5,7 +5,10 @@
<svelte:head>
<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>
<main class="container mx-auto px-4 py-8 text-left">
@ -38,21 +41,25 @@
</p>
</div>
<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>
<h2 class="text-3xl font-bold mb-4">Solving Problems with Code and Automation</h2>
<p class="text-lg leading-relaxed mb-8">
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
APIs, boosting productivity for myself and my colleagues. Outside of work, I enjoy taking on
side projects that push my boundaries, expanding my skill set, and exploring new
technologies. I strongly believe that innovation and continuous learning are key drivers of
success in the ever-evolving tech landscape.
automation. My passion for streamlining workflows led me to create internal tooling using APIs,
boosting productivity for myself and my colleagues. Outside of work, I enjoy taking on side
projects that push my boundaries, expanding my skill set, and exploring new technologies. I
strongly believe that innovation and continuous learning are key drivers of success in the
ever-evolving tech landscape.
</p>
<h2 class="text-3xl font-bold mb-4">Cat Lover and Whiskey Enthusiast</h2>
<p class="text-lg leading-relaxed mb-8">

View file

@ -1,6 +1,6 @@
<script>
/** @type {import('./$types').PageData} */
export let data;
/** @type {import('./$types').PageData} */
export let data;
</script>
<svelte:head>
@ -8,4 +8,4 @@
</svelte:head>
<!-- <h1>{data.title}</h1>
<div>{@html data.content}</div> -->
<div>{@html data.content}</div> -->

View file

@ -49,7 +49,10 @@
<svelte:head>
<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>
<main class="container mx-auto px-4 py-8 text-left">

View file

@ -2,7 +2,7 @@
<script lang="ts">
import { Canvas } 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 TerraformFlat from './models/TerraformFlat.svelte';
import Kubernetes from './models/Kubernetes.svelte';
@ -11,7 +11,10 @@
<svelte:head>
<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>
<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.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} />
<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>
import { Group } from 'three'
import { T, forwardEventHandlers } from '@threlte/core'
import { useGltf } from '@threlte/extras'
import { Group } from 'three';
import { T, forwardEventHandlers } from '@threlte/core';
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>
<T is={ref} dispose={false} {...$$restProps} bind:this={$component}>
{#await gltf}
<slot name="fallback" />
{:then gltf}
<T.Mesh geometry={gltf.nodes.Github_Mesh.geometry} material={gltf.materials['SVGMat.001']} />
{:catch error}
<slot name="error" {error} />
{/await}
{#await gltf}
<slot name="fallback" />
{:then gltf}
<T.Mesh geometry={gltf.nodes.Github_Mesh.geometry} material={gltf.materials['SVGMat.001']} />
{:catch error}
<slot name="error" {error} />
{/await}
<slot {ref} />
<slot {ref} />
</T>

View file

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

View file

@ -4,28 +4,28 @@ Command: npx @threlte/gltf@1.0.0-next.13 ./static/models/terraform-flat.glb --tr
-->
<script>
import { Group } from 'three'
import { T, forwardEventHandlers } from '@threlte/core'
import { useGltf } from '@threlte/extras'
import { Group } from 'three';
import { T, forwardEventHandlers } from '@threlte/core';
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>
<T is={ref} dispose={false} {...$$restProps} bind:this={$component}>
{#await gltf}
<slot name="fallback" />
{:then gltf}
<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_2.geometry} material={gltf.materials['SVGMat.001']} />
</T.Group>
{:catch error}
<slot name="error" {error} />
{/await}
{#await gltf}
<slot name="fallback" />
{:then gltf}
<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_2.geometry} material={gltf.materials['SVGMat.001']} />
</T.Group>
{:catch error}
<slot name="error" {error} />
{/await}
<slot {ref} />
<slot {ref} />
</T>

View file

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

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": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

View file

@ -4,15 +4,29 @@ module.exports = {
darkMode: 'class',
content: [
'./src/**/*.{html,js,svelte,ts}',
require('path').join(require.resolve(
'@skeletonlabs/skeleton'),
'../**/*.{html,js,svelte,ts}'
)
require('path').join(require.resolve('@skeletonlabs/skeleton'), '../**/*.{html,js,svelte,ts}')
],
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: [
...require('@skeletonlabs/skeleton/tailwind/skeleton.cjs')()
]
}
plugins: [...require('@skeletonlabs/skeleton/tailwind/skeleton.cjs')()]
};

View file

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