Compare commits

..

37 Commits

Author SHA1 Message Date
282a5e774e Update '.gitea/workflows/ci.yml'
All checks were successful
Build
Deploy
2023-04-11 10:06:10 +02:00
1a7727cd7d Update '.gitea/workflows/ci.yml'
All checks were successful
Build
Deploy
2023-04-10 21:11:08 +02:00
63cab3af76 Update '.gitea/workflows/ci.yml'
Some checks failed
Build
Deploy
2023-04-10 21:08:46 +02:00
aa0dfd15c9 Update '.gitea/workflows/ci.yml'
Some checks are pending
Build
Deploy
2023-04-10 20:52:46 +02:00
a18f197141 Update '.gitea/workflows/ci.yml'
All checks were successful
Build
Deploy
2023-04-10 20:50:40 +02:00
63cc1858eb Update '.gitea/workflows/ci.yml'
All checks were successful
Build
Deploy
2023-04-10 20:32:08 +02:00
69c446da5a Update '.gitea/workflows/ci.yml'
All checks were successful
Build
Deploy
2023-04-10 20:22:26 +02:00
abab04eb1d Update '.gitea/workflows/ci.yml'
All checks were successful
Build
Deploy
2023-04-10 20:12:49 +02:00
7f4a81be3f Update '.gitea/workflows/ci.yml'
Some checks failed
Build
Deploy
2023-04-10 19:52:21 +02:00
3ab21267c6 Update '.gitea/workflows/ci.yml'
Some checks failed
Build
Deploy
2023-04-10 19:47:37 +02:00
fe0a8febc2 Update '.gitea/workflows/ci.yml'
Some checks failed
Build
Deploy
2023-04-10 19:36:24 +02:00
22e1fc2eb8 Update '.gitea/workflows/ci.yml'
Some checks failed
Build
Deploy
2023-04-03 10:22:18 +02:00
43123a3e5b Update '.gitea/workflows/ci.yml'
Some checks failed
Build
Deploy
2023-04-03 10:17:54 +02:00
c18b1b0fb6 Update '.gitea/workflows/ci.yml'
Some checks failed
Deploy
Build
2023-04-03 10:13:27 +02:00
b314df57fb Update '.gitea/workflows/ci.yml'
Some checks failed
Build
Deploy
2023-04-03 10:08:00 +02:00
85059ab1bf Update '.gitea/workflows/ci.yml'
Some checks failed
Build
Deploy
2023-04-03 10:04:30 +02:00
8bbc4cd77c Update '.gitea/workflows/ci.yml'
Some checks failed
Build
Deploy
2023-04-03 09:56:55 +02:00
5382c4394b adjusted order of steps
Some checks failed
Build
Deploy
2023-04-03 09:29:37 +02:00
58a1236c71 added different install method
Some checks failed
Build
Deploy
2023-04-02 19:51:44 +02:00
b1788a6102 added docker setup
Some checks failed
Build
Deploy
2023-04-02 19:49:11 +02:00
574c5d8fb8 spelling mistake
Some checks failed
Build
Deploy
2023-04-02 19:44:16 +02:00
012dd7c52a added nodejs install
Some checks failed
Build
Deploy
2023-04-02 19:38:40 +02:00
3e47016cd9 added container
Some checks failed
Build
Deploy
2023-04-02 19:34:07 +02:00
cd620f686e renamed secrets
Some checks failed
Build
Deploy
2023-04-02 17:43:36 +02:00
d6e81e47f4 migrated actions
Some checks failed
Build
Deploy
2023-04-02 17:41:30 +02:00
e1ed3d53db added a leftbar
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-12 10:59:55 +01:00
57a50a5810 responsive design 2023-02-11 18:22:23 +01:00
aa795fb090 small fixes to ci
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-09 22:00:35 +01:00
5c674e1541 updated packages
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-09 21:54:13 +01:00
3cef2f4107 added logo second time
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-09 20:33:32 +01:00
ee8e51f62b added log
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-02-09 20:30:59 +01:00
0340ce23e7 added favicon
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-02-09 20:22:08 +01:00
372984e55b revert 2023-02-09 20:21:20 +01:00
248868b1bd added favicon 2023-02-09 20:18:46 +01:00
93dc92b56e first release
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-02-09 20:17:22 +01:00
6a116f40bb more modifications 2023-02-06 14:17:50 +01:00
eb6f590dbd added heading 2023-01-28 17:28:31 +01:00
21 changed files with 3759 additions and 1724 deletions

40
.gitea/workflows/ci.yml Normal file
View File

@@ -0,0 +1,40 @@
name: Build and Deploy
on: [push]
jobs:
Build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Nodejs
uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npm run build
Deploy:
runs-on: ubuntu-docker
steps:
- uses: actions/checkout@v3
- name: Use Nodejs
uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npm run build
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
with:
platforms: linux/amd64,linux/arm64
- uses: docker/login-action@v2
with:
registry: gitea.xeovalyte.dev
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
- run: docker buildx build -t gitea.xeovalyte.dev/xeovalyte/portfolio --platform=linux/amd64,linux/arm64 .
- run: docker inspect gitea.xeovalyte.dev/xeovalyte/portfolio
- run: docker push gitea.xeovalyte.dev/xeovalyte/portfolio

1
.prettierigonore Normal file
View File

@@ -0,0 +1 @@
.nuxt

1
.prettierrc.json Normal file
View File

@@ -0,0 +1 @@
{}

View File

@@ -1,13 +0,0 @@
pipeline:
publish:
image: plugins/docker
secrets:
- docker_password
settings:
username: xeovalyte
password:
from_secret: docker_password
repo: gitea.xeovalyte.dev/xeovalyte/website
tags:
- latest
registry: gitea.xeovalyte.dev

View File

@@ -2,11 +2,8 @@ FROM node:18
WORKDIR /usr/src/app
COPY . .
RUN npm install
RUN npm run build
COPY .output .
EXPOSE 3000
CMD [ "node", ".output/server/index.mjs" ]
CMD [ "node", "server/index.mjs" ]

View File

@@ -1,5 +1,5 @@
<template>
<div>
<NuxtWelcome />
<NuxtPage />
</div>
</template>

View File

@@ -1,3 +1,18 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
h1 {
@apply text-4xl;
}
h2 {
@apply text-3xl;
}
h3 {
@apply text-2xl;
}
h4 {
@apply text-xl;
}
}

21
assets/icons/logo.svg Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="48"
height="48"
viewBox="0 0 12.7 12.7"
version="1.1"
id="svg5"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<g
id="layer1">
<path
id="rect753"
style="fill:#0080ff;fill-opacity:1;stroke-width:0.367356"
d="M 0.8196733,1.5362707 5.1211071,5.8377046 4.3020509,6.657378 -2e-7,2.355327 V 4.81373 L 3.0725407,7.8862709 0.8196733,10.139138 H 3.2774591 L 4.3014337,9.1151643 5.1211071,9.9342203 6.35,11.163729 7.578893,9.9342203 8.3985664,9.1151643 9.4225412,10.139138 H 11.880326 L 9.6274592,7.8862709 12.7,4.81373 V 2.355327 L 8.3979491,6.657378 7.578893,5.8377046 11.880326,1.5362707 H 9.4225412 L 6.35,4.6088116 3.2774591,1.5362707 Z M 6.35,7.0665975 7.1696734,7.8856537 6.35,8.7053271 5.5303266,7.8856537 Z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 958 B

View File

@@ -0,0 +1,17 @@
<template>
<div class="fixed hidden lg:block left-3 top-1/2 text-primary-500 space-y-1 z-50">
<div @click="scrollToElement('heading')" class="py-2 hover:cursor-pointer">
<div class="h-1 rounded-full bg-primary-500 transition-all duration-300 hover:cursor-pointer" :class="route.hash === '#heading' ? 'w-16' : 'w-8'" />
</div>
<div @click="scrollToElement('about')" class="py-2 hover:cursor-pointer">
<div class="h-1 rounded-full bg-primary-500 transition-all duration-300 hover:cursor-pointer" :class="route.hash === '#about' ? 'w-16' : 'w-8'" />
</div>
<div @click="scrollToElement('skills')" class="py-2 hover:cursor-pointer">
<div class="h-1 rounded-full bg-primary-500 transition-all duration-300 hover:cursor-pointer" :class="route.hash === '#skills' ? 'w-16' : 'w-8'" />
</div>
</div>
</template>
<script setup>
const route = useRoute()
</script>

View File

@@ -0,0 +1,41 @@
<template>
<section class="flex h-screen snap-center items-center justify-center">
<div
class="my-40 mx-3 flex w-full max-w-xl flex-wrap items-center justify-center gap-5 whitespace-pre-wrap text-lg text-primary-500"
>
<h2
v-animate="{ preset: 'slide-right', duration: 500 }"
class="mb-10 text-center text-3xl font-bold"
>
{{ t("title") }}
</h2>
<div v-animate="{ preset: 'slide-right', delay: 400, duration: 500 }">
{{ t("message") }}
</div>
</div>
</section>
</template>
<script setup>
const { t } = useI18n({ useScope: "local" });
</script>
<i18n lang="yaml">
en:
message: |
Hi,
My name is Timo Boomers (16) also known as Xeovalyte. I live in the Netherlands and I have always found electronics and computers interesting.
When I was 12 I started programming. I now program Websites, Discord bots and Arduino.
title: "About"
nl:
message: |
Hallo,
Mijn naam is Timo Boomers (16) ook wel bekend als Xeovalyte. Ik heb electronica en computers altijd interresant gevonden en ben toen gaan programmeren.
Toen ik 12 was begon ik met programmeren. Ondertussen programmeer ik Websites, Discord bots en Arduino.
title: "Over mij"
</i18n>

View File

@@ -0,0 +1,44 @@
<template>
<section
class="relative flex h-screen snap-center items-center justify-center"
>
<div
class="flex flex-wrap items-center justify-center gap-5 text-center text-primary-500"
>
<img
v-animate="{ preset: 'slide-left', delay: 300 }"
src="../../assets/icons/logo.svg"
alt="Logo Xeovalyte"
width="150"
/>
<div class="space-y-2">
<h1
v-animate="{ preset: 'slide-up', delay: 450 }"
class="sm:text-7xl text-6xl font-bold"
>
Xeovalyte
</h1>
<div
v-animate="{ preset: 'slide-right', delay: 600 }"
class="h-1 w-full rounded-full bg-primary-500"
/>
<h3
v-animate="{ preset: 'slide-down', delay: 750 }"
class="text-4xl font-bold"
>
Timo Boomers
</h3>
</div>
<Icon
@click="scrollToElement('about')"
size="2em"
name="ph:arrow-fat-line-down"
class="absolute bottom-20 basis-full animate-bounce hover:cursor-pointer"
/>
</div>
</section>
</template>
<script setup>
</script>

View File

@@ -0,0 +1,85 @@
<template>
<section class="flex h-screen snap-center items-center justify-center">
<div
class="my-40 mx-5 flex w-full max-w-3xl flex-col text-primary-500"
v-animate="{ stagger: true, preset: 'slide-left', duration: 500 }"
>
<h2 class="mb-10 text-center text-3xl font-bold">
{{ t("skills.skills") }}
</h2>
<h2 class="text-lg font-bold">Arduino</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-3/5 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.intermediate") }}
</h2>
</div>
<h2 class="text-lg font-bold">Docker</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-4/5 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.advanced") }}
</h2>
</div>
<h2 class="text-lg font-bold">Javascript</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-2/3 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.intermediate") }}
</h2>
</div>
<h2 class="text-lg font-bold">Linux</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-4/5 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.advanced") }}
</h2>
</div>
<h2 class="text-lg font-bold">Nuxt</h2>
<div class="mb-5 grid grid-cols-5 items-center gap-x-4">
<div
class="col-span-5 h-4 w-full rounded-full bg-dark-600 sm:col-span-4"
>
<div class="h-4 w-3/5 rounded-full bg-primary-100" />
</div>
<h2 class="hidden text-lg font-bold sm:inline-block">
{{ t("skills.intermediate") }}
</h2>
</div>
</div>
</section>
</template>
<script setup>
const { t } = useI18n({ useScope: "local" });
</script>
<i18n lang="yaml">
en:
skills:
skills: "Skills"
intermediate: "Intermediate"
advanced: "Advanced"
nl:
skills:
skills: "Vaardigheden"
intermediate: "Gemiddeld"
advanced: "Geavanceerd"
</i18n>

View File

@@ -0,0 +1,4 @@
export default function (hash) {
const element = document.getElementById(hash)
element.scrollIntoView({ behavior: 'smooth' })
}

View File

@@ -1,9 +1,44 @@
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss',
'@vueuse/nuxt',
'nuxt-icon',
'@nuxtjs/robots'
"@nuxtjs/tailwindcss",
"@vueuse/nuxt",
"nuxt-icon",
"nuxt-icons",
"@nuxtjs/robots",
"@nuxtjs/i18n",
"@nuxtjs/plausible",
],
plausible: {
domain: 'xeovalyte.com',
apiHost: 'https://plausible.xeovalyte.dev'
},
app: {
head: {
title: 'Xeovalyte | Timo Boomers Portfolio',
link: [
{
"rel": "icon",
"href": "/favicon.ico",
"type": "image/png"
}
],
meta: [
{ name: 'description', content: 'This is the official portfolio of Xeovalyte or Timo Boomers'}
]
})
}
},
i18n: {
baseUrl: 'https://xeovalyte.com',
locales: [
{ code: 'en', iso: 'en-US', isCatchallLocale: true },
{ code: 'nl', iso: 'nl-NL'},
],
defaultLocale: 'en',
detectBrowserLanguage: {
useCookie: true,
cookieKey: 'i18n_redirected',
redirectOn: 'root',
}
},
});

4925
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,13 +8,19 @@
"postinstall": "nuxt prepare"
},
"devDependencies": {
"@nuxtjs/tailwindcss": "^6.2.0",
"@vueuse/core": "^9.8.2",
"@vueuse/nuxt": "^9.8.2",
"nuxt": "3.0.0",
"nuxt-icon": "^0.1.8"
"@nuxtjs/tailwindcss": "^6.3.1",
"@vueuse/core": "^9.12.0",
"@vueuse/nuxt": "^9.12.0",
"nuxt": "3.2.0",
"nuxt-icon": "^0.2.11",
"prettier": "^2.8.4",
"prettier-plugin-tailwindcss": "^0.2.2"
},
"dependencies": {
"@nuxtjs/robots": "^3.0.0"
"@nuxtjs/i18n": "^8.0.0-beta.9",
"@nuxtjs/plausible": "^0.2.0",
"@nuxtjs/robots": "^3.0.0",
"locomotive-scroll": "^4.1.4",
"nuxt-icons": "^3.1.0"
}
}

29
pages/index.vue Normal file
View File

@@ -0,0 +1,29 @@
<template>
<LayoutLeftbar />
<div id="observe" class="h-screen snap-y snap-mandatory overflow-y-auto overflow-x-hidden bg-dark-200">
<SlidesHeading id="heading" />
<SlidesAbout id="about" />
<SlidesSkills id="skills" />
</div>
</template>
<script setup>
const router = useRouter()
const callback = (entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
router.replace({ hash: '#' + entry.target.id})
}
})
}
onMounted(() => {
let targets = document.querySelectorAll('section')
const observer = new IntersectionObserver(callback, { root: document.querySelector('#observe'), threshold: 0.9 })
targets.forEach(target => {
observer.observe(target)
})
})
</script>

101
plugins/motion.js Normal file
View File

@@ -0,0 +1,101 @@
export default defineNuxtPlugin((NuxtApp) => {
NuxtApp.vueApp.directive('animate', (el, binding) => {
el.classList.add('animate')
el.setAttribute('data-animate-duration', binding.value.duration || 250 )
el.setAttribute('data-animate-delay', binding.value.delay || 200 )
el.setAttribute('data-animate-preset', binding.value.preset || 'fade' )
el.setAttribute('data-animate-stagger', binding.value.stagger || false )
el.setAttribute('data-animate-stagger-delay', binding.value.staggerDelay || 100 )
})
NuxtApp.hook('page:finish', () => {
const applyClasses = (el, type) => {
const initialClasses = JSON.parse(el.getAttribute('data-animate-initial'))
const animateClasses = JSON.parse(el.getAttribute('data-animate-animate'))
if (type === 'initial') {
Object.keys(initialClasses).forEach(x => {
el.style[x] = initialClasses[x]
})
el.style['transition-property'] = 'none'
}
if (type === 'animate') {
Object.keys(animateClasses).forEach(x => {
el.style[x] = animateClasses[x]
})
el.style['transition-property'] = 'all'
}
}
const callback = (entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
applyClasses(entry.target, 'animate')
} else {
applyClasses(entry.target, 'initial')
}
})
}
// Configure staggering animations
let targets = document.querySelectorAll('.animate')
targets.forEach((target) => {
if (target.getAttribute('data-animate-stagger') === 'true') {
target.classList.remove('animate')
const collection = target.children
Object.values(collection).forEach((child, index) => {
child.setAttribute('data-animate-preset', target.getAttribute('data-animate-preset') )
child.setAttribute('data-animate-duration', target.getAttribute('data-animate-duration') )
child.style.transitionDelay = Number(target.getAttribute('data-animate-delay')) + index * Number(target.getAttribute('data-animate-stagger-delay')) + 'ms'
child.classList.add('animate')
})
} else {
target.style.transitionDelay = target.getAttribute('data-animate-delay') + 'ms'
}
})
// Configure presets
const observer = new IntersectionObserver(callback)
targets = document.querySelectorAll('.animate')
targets.forEach(target => {
const preset = target.getAttribute('data-animate-preset')
if (preset === 'fade') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0 }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100 }))
} else if (preset === 'slide-left') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateX(-6em)', filter: 'blur(5px)' }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateX(0)', filter: 'blur(0)' }))
} else if (preset === 'slide-right') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateX(6em)', filter: 'blur(5px)' }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateX(0)', filter: 'blur(0px)' }))
} else if (preset === 'slide-up') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateY(-2em)', filter: 'blur(5px)' }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateY(0)', filter: 'blur(0px)' }))
} else if (preset === 'slide-down') {
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateY(2em)', filter: 'blur(5px)' }))
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateY(0)', filter: 'blur(0px)' }))
}
applyClasses(target, 'initial')
target.classList.add('transition-all')
target.style['transition-duration'] = target.getAttribute('data-animate-duration') + 'ms'
observer.observe(target)
})
})
})

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View File

@@ -2,7 +2,32 @@
module.exports = {
content: [],
theme: {
extend: {},
extend: {
colors: {
dark: {
100: "#131920",
200: "#11171d",
300: "#0f141a",
400: "#0d1216",
500: "#0b0f13",
600: "#0a0d10",
700: "#080a0d",
800: "#06080a",
900: "#040506",
},
primary: {
100: "#66b2ff",
200: "#4da6ff",
300: "#39f",
400: "#1a8cff",
500: "#0080ff",
600: "#0073e6",
700: "#06c",
800: "#0059b3",
900: "#004c99",
},
},
},
},
plugins: [],
}
};

View File

@@ -1,4 +1,5 @@
{
// https://v3.nuxtjs.org/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
"extends": "./.nuxt/tsconfig.json",
"allowJs": true
}