Compare commits

...

15 Commits

Author SHA1 Message Date
Ward Truyen
ae0e261618 fix: icon missing url 2025-08-19 17:00:06 +02:00
Ward Truyen
dfc9abbb6d feat: icons are now links too 2025-08-19 16:59:06 +02:00
Ward Truyen
90f4daa2ad feat: Updated Introduction to match CV 2025-08-02 22:12:37 +02:00
Ward Truyen
747de6374f fix: typo in cv 2025-08-02 22:12:04 +02:00
Ward Truyen
fc9691b228 feat: Updated CV 2025-08-02 22:01:52 +02:00
Ward Truyen
30ce8a4282 fix: pulled footer out of main and improved carousel img alt text 2025-07-28 10:42:53 +02:00
Ward Truyen
829075fe4d feat: OG metatags setting picture size 2025-07-27 17:52:55 +02:00
Ward Truyen
3065719d7d fix: OG urls should not have www 2025-07-27 17:48:34 +02:00
Ward Truyen
9040f5ad53 fix: OG image not comming through again 2025-07-27 17:45:17 +02:00
Ward Truyen
9a1f0361bc fix: OG image not comming through 2025-07-27 15:34:29 +02:00
Ward Truyen
c79327a6f8 feat: added favicon link in head 2025-07-27 15:21:46 +02:00
Ward Truyen
2f6e9d4ea2 chore: improved visibility on low res mobile 2025-07-27 15:12:30 +02:00
Ward Truyen
b6472fadcd docs: Added short README.md 2025-07-27 14:17:44 +02:00
Ward Truyen
651dd34bf5 feat!: inserted new site 2025-07-27 14:10:59 +02:00
Ward Truyen
90cdef8909 feat!:moved old site to old folder 2025-07-27 14:10:26 +02:00
28 changed files with 891 additions and 427 deletions

10
README.md Normal file
View File

@@ -0,0 +1,10 @@
# Ward Truyen's CV website
Made using Bootstrap, Oneko's cat, and Zumari's Starback.
As required created with CSS, HTML and JavaScript.
## Thanks to
- My wife and son.
- Uncle Miel.
- The rest of the families.

6
src/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,209 +0,0 @@
/* Author: Ward Truyen
* Version: 1.0.0
*/
html{
scroll-behavior: smooth !important;
}
html,
body {
margin: 0px;
padding: 0px;
height: 100%;
display: flex;
flex-direction: column;
overflow: auto;
}
.theme-button {
float: right;
margin: 0.5em;
}
.card {
padding: 10px;
border: 1px solid darkblue;
background-color: #ddddddcc;
border-radius: 0.5em;
box-shadow: 3px 3px 3px #30303090;
margin: 1em 0.5em;
display: inline-block;
}
.card>h1 {
font-size: 2em;
}
html {
background-image: linear-gradient(-30deg, #C0E0FF6F 70%, #FFE0C04F);
}
.flex {
display: flex;
flex-direction: column;
}
.content {
/* display: inline-block; */
margin: auto;
/* margin-top: 1em; */
min-width: 80%;
/* min-height: 40%; */
padding-right: 8px;
}
.block-photo {
padding: 10px;
border-top: 1px solid black;
border-bottom: 1px solid black;
/* border: 1px solid darkblue; */
background-image: url('../img/sunnyclouds.jpg');
background-repeat: no-repeat;
background-attachment: fixed;
background-size: 100% 100%;
box-shadow: inset 0px 0px 6px #30303090;
margin-top: 1em;
margin-bottom: 1em;
}
.block-darker {
padding: 10px;
/* border: 1px solid darkblue; */
/* background-color: #80808040; */
background-image: linear-gradient(#00000000, #d0e08030, #d0e08030, #00000000);
/* box-shadow: 3px 3px 3px #30303090; */
/* border-radius: 4px; */
margin-top: 1em;
margin-bottom: 1em;
}
.block-alert {
display: inline-block;
padding: 10px;
border: 1px solid darkblue;
background-color: #ffaaaadd;
box-shadow: 3px 3px 3px #30303090;
border-radius: 4px;
margin-top: 1em;
margin-bottom: 1em;
}
.block-white {
padding: 10px;
border: 1px solid darkblue;
background-color: #ffffffcc;
box-shadow: 3px 3px 3px #30303090;
margin-top: 1em;
margin-bottom: 1em;
}
.content>h1 {
font-family: "Raleway", sans-serif;
font-size: 3em;
margin-top: 0px;
margin-bottom: 8px;
text-decoration: underline;
text-shadow: 0px 0px 4px white, 2px 2px 6px;
}
.content>p {
margin-left: 1em;
}
.content>h2 {
margin-left: 0.2em;
}
.content>h2 {
margin-top: 1.5em;
}
.content>h2 {
margin-top: 0.2em;
}
.content>h3 {
margin-left: 0.8em;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
/* img { */
/* display: inline-block; */
/* margin: 0 auto; */
/* max-width: 100%; */
/* } */
ul {
margin: .5em 0;
}
ul.dashed {
list-style-type: '- ';
}
.text-red {
color: red;
}
html.theme-dark {
color-scheme: dark;
background-image: linear-gradient(-10deg, #1010206F 60%, #5050506F);
color: white;
}
.theme-dark>body>main>.block-white {
border: 1px solid darkgray;
background-color: black;
box-shadow: 3px 3px 5px #101010C0;
}
.theme-dark>body>main>.content>h1 {
text-shadow: 0px 0px 3px blue, 2px 2px 6px;
}
.theme-dark>body>main>.content>.block-alert {
background: none;
border-color: red;
color: red;
}
.splide__slide img {
display: block;
width: 100%;
height: auto;
margin: 0 auto;
}
#image-carousel {
width: 50rem;
margin: 0 auto;
}
@media only screen and (max-width: 800px){
#image-carousel {
width: 40rem;
}
}
@media only screen and (max-height: 800px){
#image-carousel {
width: 40rem;
}
}
@media only screen and (max-width: 600px){
#image-carousel {
width: 25rem;
}
}
@media only screen and (max-height: 600px){
#image-carousel {
width: 25rem;
}
}
@media(orientation: portrait) {
main {
margin-top: 0;
}
}

File diff suppressed because one or more lines are too long

169
src/css/style.css Normal file
View File

@@ -0,0 +1,169 @@
.navbar {
background-color: #000b;
/* background: linear-gradient(0deg,rgba(35, 43, 62, 200) 0%, rgba(0, 0, 0, 200) 100%); */
border-bottom: 1px solid grey;
}
.divider {
height: 3rem;
background-color: rgba(0, 0, 0, .1);
border: solid rgba(0, 0, 0, .15);
border-width: 1px 0;
box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
}
.my-picture {
width: 8em;
aspect-ratio: 1;
border-radius: 5px;
float: right;
}
#icons>a {
display: inline;
width: unset;
}
.img-icon {
width: 4em;
aspect-ratio: 1;
margin: .5em .5em;
padding: 3px;
transition: all .2s;
border-radius: 5px;
}
.img-icon:hover {
width: 5em;
margin: 0;
border: 1px solid white;
box-shadow: 0 0 15px rgba(255, 255, 255, .8);
background-color: #FFFFFF88;
}
.card {
width: 40rem;
padding: 10px;
border: 1px solid black;
background-color: #aaaaaadd;
border-radius: 0.5em;
box-shadow: .5em .5em 1.5em rgba(0, 0, 0, .3);
margin: 1em 0.5em;
display: inline-block;
box-shadow: inset 0 0 3px black;
}
.card iframe {
width: 100%;
aspect-ratio: 16/9;
}
.card a {
color: #0000FF;
}
a {
color: #8888FF;
}
.carousel {
max-width: 80vh;
}
.carousel-control-next,
.carousel-control-prev {
filter: brightness(.5) drop-shadow(0px 0px 1px #FFFFFF);
}
.carousel-caption>h5 {
color: #aaaaffdd;
}
.carousel-indicators [data-bs-target] {
background-color: #aaaaffdd;
}
.attention {
font-size: 1.5em;
}
.rowlines-short li:not(:last-of-type)::after {
content: "";
width: 52%;
margin: 0 4rem;
border-bottom: 1px solid #66666688;
}
.rowlines li:not(:last-of-type)::after {
content: "";
width: 78%;
margin: 0 4rem;
border-bottom: 1px solid #66666688;
}
.rowlines-short li,
.rowlines li {
transition: all .2s;
}
.rowlines li:hover {
/* background-color: #8888; */
box-shadow: inset 0 0 3px white;
text-decoration: underline;
}
.rowlines-short li:hover {
text-decoration: underline;
}
canvas {
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
z-index: -2;
}
body {
overflow-x: hidden;
}
#canvas {
position: fixed;
top: 0px;
height: 100%;
width: 100%;
}
.note {
background: #00000032;
border: 2px solid #888888;
border-radius: 0.5em;
box-shadow: .5em .5em 1.5em rgba(0, 0, 0, .3);
padding: 1em;
margin: 1em auto;
width: 50%;
}
@media (max-width: 800px) {
.note {
width: 80%;
}
.card {
width: 32rem;
}
.attention {
font-size: 1.3em;
}
ul {
padding-left: 1rem;
}
}
@media(max-width: 600px) {
body {
font-size: 80%;
}
}

BIN
src/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/img/arch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
src/img/docker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
src/img/gitea.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
src/img/lua.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
src/img/me.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
src/img/mountain2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
src/img/neovim.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

BIN
src/img/nginx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
src/img/oneko.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

BIN
src/img/traefik.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
src/img/windows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
src/img/wterminal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -1,170 +1,339 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang=""> <html lang="en">
<head> <head>
<title>Ward Truyen home</title> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/main.css" /> <title>Ward Truyen's CV</title>
<link rel="stylesheet" href="css/splide.min.css" /> <link rel="shortcut icon" href="favicon.ico" />
</head>
<meta name="description" content="Op zoek naar een Java developer job.">
<body>
<main class="flex"> <!-- Facebook Meta Tags -->
<div class="block-white content"> <meta property="og:url" content="https://ward.truyen.network/">
<button class="theme-button" title="Dark theme on/off" onclick="toggleTheme();">&#9728;</button> <meta property="og:type" content="website">
<h1 id="ik">Ward Truyen:</h1> <meta property="og:title" content="Ward Truyen's CV">
<h2>Introductie</h2> <meta property="og:description" content="Op zoek naar een Java developer job.">
<p>Ik ben Ward Truyen, een veelzijdige computerliefhebber op zoek naar een job in de ICT. <meta property="og:image" content="https://ward.truyen.network/img/me.jpg">
Ik ben inzetbaar als programmeur, tester, ICT-Engineer en ICT-beheerder.</p> <meta property="og:image:width" content="400">
<meta property="og:image:height" content="400">
<p>Ik ben een <i>doe het zelf</i> type dat liever leert uit een fout dan er niet aan durven te beginnen.
<br>Mijn grote liefde gaat naar automatisatie-technieken. Aldus de computer-technologie trekt me aan, niets zo <!-- Twitter Meta Tags -->
veelzijdig in automatisatie als computers. <meta name="twitter:card" content="summary_large_image">
<br>De kennis die ik heb vergaard maak ik ook zeer graag nuttig, ik help graag. Mensen vinden dat ik een <meta property="twitter:domain" content="ward.truyen.network">
aangename stem heb en geruststellend overkom. <meta property="twitter:url" content="https://ward.truyen.network/">
<br>Met plezier heb ik al ontelbaar vele mensen geholpen bij computer problemen, en als trainer ondersteuning <meta name="twitter:title" content="Ward Truyen's CV">
geboden in hun opleiding tot junior Java developer. <meta name="twitter:description" content="Op zoek naar een Java developer job.">
</p> <meta name="twitter:image" content="https://ward.truyen.network/img/me.jpg">
<p> <link rel="stylesheet" href="css/bootstrap.min.css" />
Ik heb, onder andere, heel wat ervaring in de talen Java en Java-/Type-Script alsook bijhorende frameworks en <link rel="stylesheet" href="css/style.css">
tools </head>
<br>Dit stelt me in staat om aan een front-end en back-end te werken, alsook beheer ik de server. Full stack.
</p> <body class="text-bg-dark bg-dark">
<ul> <header>
<li>Back-end: Java, Maven &amp; Gradle, SQL, Hibernate, Lombok, Spring, JUnit voor testing</li> <nav class="navbar navbar-expand-md fixed-top navbar-dark">
<li>Front-end: HTML, CSS, JavaScript, Typescript &amp; Angular, JQuery, Bootstrap</li> <div class="container-fluid">
<li>Tools: npm, Git, Bash, Docker, SSH, en vele andere tools en scripts om de server, code en apps te beheren. <a class="navbar-brand" href="#">Ward Truyen</a>
</li> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown"
</ul> aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<p>Deze hou ik dan ook up to date door te werken aan mijn <a href="#famweb">familie website</a>.</p> <span class="navbar-toggler-icon"></span>
<p>Eveneens zijn Agile en Scrum gekende methodieken. En ken ik heel wat technieken als OOP, TDD, BDD, UML, SOLID </button>
en REST.</p> <div class="collapse navbar-collapse" id="navbarNavDropdown">
<p>Ik heb bij Multimedi 3 jaar gewerkt als trainer Java Developer, voor volwassenen. <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<br>Dankzij deze ervaring heb ik mijn full stack kennis met Java kunnen verzilveren en een kleine honderd mensen <li class="nav-item">
kunnen helpen in hun carriere. <a class="nav-link" href="#skills">Vaardigheden</a>
</p> </li>
<li class="nav-item">
<p><u>Naast het programmeren:</u> <a class="nav-link" href="#werk">Werkervaring</a>
<br>Kan ik het onderhoud, plaatsen, installeren en beheren van: servers, netwerk apparatuur, scanners, printers, </li>
applicaties en services. Linux, windows en Mac. <li class="nav-item">
<br>Ook kan ik je helpen op alle computers: server, desktop, laptop, tablet en op smartphone. <a class="nav-link" href="#studies">Studies</a>
<br>Eveneens ben ik een doe-het-zelver. Ik kan huishoudelijke elektriciteit-werken uitvoeren en elektronica repareren. </li>
</p> <li class="nav-item">
<p>Ik heb een hulpvaardig en verzorgd overkomen. Graag houd ik structuur en orde op mijn werkplaats. En kan ik <a class="nav-link" href="#portfolio">Portfolio</a>
blindelings typen. </p> </li>
<p id="mijncv">Voor meer informatie bekijk mijn cv <a href="docs/CV_WardTruyen_2025-Java.pdf">voor </ul>
Java/Full-Stack</a> of <a href="docs/CV_WardTruyen_2025-ICT_Engineer.pdf">voor ICT Engineer/Beheerder</a>.</p> </div>
</div> </div>
</nav>
<div class="content"> </header>
<h2>Zelf gemaakt 2024-2025:</h2>
<h3>Deze server en website</h3> <main>
<img style="max-width: 120px; height: auto; float: right;" src="img/tux.png"> <h1 class="visually-hidden">Ward Truyen's CV</h1>
<p>Deze <a href="https://nl.wikipedia.org/wiki/Server" <section id="intro">
title="Een server is een computer dat diensten verleent aan clients" target="_blank">server</a> heb ik <div class="p-2 my-5">
kunnen opzetten met <div class="note">
<a href="https://archlinux.org/" title="Besturingssysteem Arch Linux" target="_blank">Arch Linux</a> als <a <h2 class="d-inline">Introductie</h2>
href="https://nl.wikipedia.org/wiki/Besturingssysteem" title"Besturingssysteem" target="_blank">OS</a>. <img class="my-picture d-none d-md-block" src="img/me.jpg" alt="[my picture]" />
<br>Daarop staat <a href="https://doc.traefik.io/traefik/" title="Reverse proxy en load balancer" <p>Ik ben een gepassioneed informaticus. Ik heb een hulpvaardig karakter en ben zeer technisch geinformeerd.
target="_blank">Traefik</a> als <a href="https://en.wikipedia.org/wiki/Reverse_proxy" Bijleren doe ik graag en kan genieten van structuur en orde in mijn werk. Ik ben geduldig
title="1 domein en server met meerdere subdomeinen en/of servers en services" target="_blank">reverse en kan met volle concentratie problemen aanpakken en daarbij streven naar afwerking.
proxy</a> en de vele <a href="https://nl.wikipedia.org/wiki/Subdomein" Je kan me vinden voor een aangename babbel of een luisterend oor.</p>
title="Een subdomein is een domein dat deel uitmaakt van een groter domein" target="_blank">subdomeinen</a> <a href="docs/cv-wardtruyen-2025-Java.pdf" class="btn btn-primary" download>Download mijn CV</a>
zijn </div>
m.b.v. <a href="https://www.docker.com/" title="Container applicatie" target="_blank">Docker</a> beheerd. </div>
</p> </section>
<h3 id="famweb">Gezin website</h3>
<p>Op <a href="https://sf.truyen.network" target="_blank">sf.truyen.network</a> staat een kopie van <a <div id="skills" class="divider"></div>
href="https://tds.truyen.network" target="_blank">tds.truyen.network</a>
<br>Daarop staat een site voor het beheren van gezin gevens zoals contacten, winkellijstjes, kalender, <section>
takenlijstjes en notities. <div class="px-4 py-4">
<br>Deze is gemaakt met als backend Java, Spring en REST, als frontend is er Angular. <h2>Vaardigheden</h2>
<br>Dit met als doel gezins-gegevens overal beschikbaar te hebben zonder google of facebook en dergelijke <div class="row">
tech-giganten. <div class="col-4">
<br>Handig voor het winkellijstje af te gaan op je gsm. Alles bij de hand. <h4>Back-end</h4>
</p> <ul>
<p><a href="https://sf.truyen.network" target="_blank">sf.truyen.network</a> is dus de publieke test versie van <li>Java EE</li>
deze <li>Spring &amp; REST</li>
site, waar u op kan inloggen, testen en inspecteren <a href="#ik">(login gegevens staan in mijn CV)</a>.<br> <li>SQL &amp; Hibernate</li>
Mocht er <li>Lombok</li>
hier iets fout lopen, stuur me a.u.b. een e-mail of bel me, en ik los het ASAP op.</p> <li>Maven &amp; Gradle</li>
</div> <li>JSP</li>
<div class="block-darker flex"> <li>JUnit</li>
<div class="content"> <li>Multithreading &amp; Concurrency</li>
<section id="image-carousel" class="splide" aria-label="Beautiful Images"> </ul>
<div class="splide__track"> </div>
<ul class="splide__list"> <div class="col-4">
<li class="splide__slide"> <h4>Front-end</h4>
<img src="img/tds1.png" alt="tds.truyen.network"> <ul>
</li> <li>JavaScript</li>
<li class="splide__slide"> <li>TypeScript</li>
<img src="img/tds2.png" alt="tds.truyen.network"> <li>Angular</li>
</li> <li>HTML &amp; CSS</li>
<li class="splide__slide"> <li>NPM</li>
<img src="img/tds3.png" alt="tds.truyen.network"> <li>JQuery</li>
</li> <li>Bootstrap</li>
<li class="splide__slide"> <li>async &amp; wait</li>
<img src="img/tds4.png" alt="tds.truyen.network"> </ul>
</li> </div>
</ul> <div class="col-4">
</div> <h4>Tools</h4>
</section> <ul>
<script src="js/splide.min.js"></script> <li>Git</li>
<script> <li>Scrutm &amp; Agile</li>
document.addEventListener('DOMContentLoaded', function () { <li>VS code &amp; IntelliJ &amp; vim</li>
new Splide('#image-carousel').mount(); <li>Docker &amp; Virtualisatie</li>
}); <li>CI/CD</li>
</script> <li>Powershell &amp; bash</li>
</div> <li>Terminal &amp; SSH</li>
</div> </ul>
<div class="content"> </div>
<h3>WTerminal</h3> </div>
<p>Op <a href="https://wterminal.truyen.network" target="_blank">wterminal.truyen.network</a> kan u mijn <div class="row justify-content-center" id="icons">
browser-addon of website-tooltje WTerminal vinden.</p> <a target="_blank" href="https://en.wikipedia.org/wiki/Linux">
</div> <img class="img-icon" src="img/tux.png" alt="Linux" title="Tux, the linux mascot" /></a>
<a target="_blank" href="https://archlinux.org">
<div class="block-photo flex"> <img class="img-icon" src="img/arch.png" alt="Arch linux" title="Arch linux" /></a>
<div class="content"> <a target="_blank" href="https://www.microsoft.com/nl-be/windows">
<h2>Zelf gemaakt vroeger:</h2> <img class="img-icon" src="img/windows.png" alt="Windows" title="MS Windows" /></a>
<div class="card"> <a target="_blank" href="https://traefik.io">
<h1>Ronny</h1> <img class="img-icon" src="img/traefik.png" alt="Traefik" title="Traefik: a reverse proxy" /></a>
<p>Gemaakt in VB.net 2004-2006<br>Direct draw rendering</p> <a target="_blank" href="https://www.docker.com">
<iframe src="https://www.youtube.com/embed/m7tgDUc2jXs"> <img class="img-icon" src="img/docker.png" alt="Docker" title="Docker" /></a>
</iframe> <a target="_blank" href="https://www.lua.org">
</div> <img class="img-icon" src="img/lua.png" alt="Lua" title="Lua script" /></a>
<div class="card"> <a target="_blank" href="https://neovim.io">
<h1>Minesweeper</h1> <img class="img-icon" src="img/neovim.png" alt="Neovim" title="Neovim editor" /></a>
<p>Gemaakt in C/C++ 2006-2013<br>OpenGL rendering</p> <a target="_blank" href="https://nginx.org">
<iframe src="https://www.youtube.com/embed/Rejp6cVRxfc"> <img class="img-icon" src="img/nginx.png" alt="Nginx" title="Nginx a reverse proxy" /></a>
</iframe> </div>
</div> </div>
</div> </section>
</div>
<div id="werk" class="divider"></div>
<div class="block-white content">
<h2>Links naar de verschillende domeinen op deze server:</h2> <section>
<ul class="dashed"> <div class="px-4 py-4">
<li>website <a href="https://truyen.network" target="_blank">truyen.network</a> centrale website</li> <h2>Werkervaring</h2>
<li>gitea service op <a href="https://git.truyen.network" target="_blank">git.truyen.network</a> om git <ul class="rowlines">
repositories te beheren</li> <li class="row attention">
<li>website <a href="https://tds.truyen.network" target="_blank">tds.truyen.network</a> voor gezin data beheer <span class="col-5">Opleiding Java Enterprise</span>
</li> <span class="col-4">/</span>
<li>voorbeeld-website <a href="https://sf.truyen.network" target="_blank">sf.truyen.network</a> voor gezin <span class="col-3">2025 - Nu</span>
data </li>
beheer</li> <li class="row text-secondary">
<li>website <a href="https://willem.truyen.network" target="_blank">willem.truyen.network</a> bevat spelletjes <span class="col-5">Tijdelijke Interim jobs</span>
voor Willem</li> <span class="col-4">Verscheidene werkplaatsen</span>
<li>website <a href="https://wterminal.truyen.network" target="_blank">wterminal.truyen.network</a> voor <span class="col-3">2025 - Nu</span>
WTerminal, zelf gemaakte browser-addon project</li> </li>
</ul> <li class="row">
<span class="col-5">Zelfstudie Angular en docker</span>
<!-- <p class="text-red">Deze server wordt nog verder uitgebreid, stay tuned.</p> --> <span class="col-4">/</span>
<p>Laatste update: 22 Juli 2025</p> <span class="col-3">2023 - 2025</span>
</div> </li>
</main> <li class="row">
<span class="col-5">Allround ICT-er</span>
<script src="js/theme.js"></script> <span class="col-4">Nelissen computers</span>
</body> <span class="col-3">2022 - 2022</span>
</li>
</html> <li class="row attention">
<span class="col-5">ICT Trainer Java</span>
<span class="col-4">Multimedi</span>
<span class="col-3">2018 - 2021</span>
</li>
<li class="row">
<span class="col-5">Zelfstudie Java en Linux</span>
<span class="col-4">/</span>
<span class="col-3">2016 - 2017</span>
</li>
<li class="row">
<span class="col-5">Helpdesk technische dienst</span>
<span class="col-4">KUL</span>
<span class="col-3">2015 - 2016</span>
</li>
<li class="row">
<span class="col-5">Vrijwillig programmeur</span>
<span class="col-4">KUL</span>
<span class="col-3">2013 - 2014</span>
</li>
<li class="row text-secondary">
<span class="col-5">Tijdelijke Interim jobs</span>
<span class="col-4">Verscheidene werkplaatsen</span>
<span class="col-3">2007 - 2013</span>
</li>
<li class="row attention">
<span class="col-5">Programmeur C++</span>
<span class="col-4">Zetes</span>
<span class="col-3">2007 - 2007</span>
</li>
<li class="row">
<span class="col-5">Computer dokter</span>
<span class="col-4">Compudoc</span>
<span class="col-3">2006 - 2007</span>
</li>
</ul>
</div>
</section>
<div id="studies" class="divider"></div>
<section>
<div class="px-4 py-4">
<h2>Studies</h2>
<ul class="rowlines-short">
<li class="row">
<span class="col-6">Multimedi Java Enterprise ontwikkelaar</span>
<span class="col-6">2025 - nu</span>
</li>
<li class="row">
<span class="col-6">Multimedi Systeembeheer</span>
<span class="col-6">2017 - 2018</span>
</li>
<li class="row">
<span class="col-6">Cevora Java Enterprise ontwikkelaar</span>
<span class="col-6">2008 - 2009</span>
</li>
<li class="row">
<span class="col-6">A2: Elektrische installatietechnieken</span>
<span class="col-6">1998 - 2004</span>
</li>
</ul>
</div>
</section>
<div id="portfolio" class="divider"></div>
<section>
<div class="px-4 py-4">
<h2>Portfolio</h2>
<h4>Huidig project:</h4>
<a target="_blank" href="https://tds.truyen.network">TDS Family website</a>
<p>Full stack Java &amp; Angular website.</p>
<div id="carouselExampleIndicators" class="carousel carousel-dark slide carousel-fade mx-auto">
<div class="carousel-indicators">
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="0" class="active"
aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="1"
aria-label="Slide 2"></button>
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="2"
aria-label="Slide 3"></button>
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="3"
aria-label="Slide 4"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
<img src="img/tds1.png" class="d-block w-100" alt="Screenshot TDS Familiy site 1">
<div class="carousel-caption d-none d-md-block">
<h5>1</h5>
</div>
</div>
<div class="carousel-item">
<img src="img/tds2.png" class="d-block w-100" alt="Screenshot TDS Familiy site 2">
<div class="carousel-caption d-none d-md-block">
<h5>2</h5>
</div>
</div>
<div class="carousel-item">
<img src="img/tds3.png" class="d-block w-100" alt="Screenshot TDS Familiy site 3">
<div class="carousel-caption d-none d-md-block">
<h5>3</h5>
</div>
</div>
<div class="carousel-item">
<img src="img/tds4.png" class="d-block w-100" alt="Screenshot TDS Familiy site 4">
<div class="carousel-caption d-none d-md-block">
<h5>4</h5>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleIndicators"
data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleIndicators"
data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
<h4>Websites:</h4>
<ul>
<li><a target="_blank" href="https://ward.truyen.network">Ward(this one)</a></li>
<li><a target="_blank" href="https://willem.truyen.network">Willem games</a></li>
<li><a target="_blank" href="https://git.truyen.network">Gitea</a></li>
<!-- <li><a target="_blank" href="https://wterminal.truyen.network">WTerminal</a></li> -->
</ul>
<br>
<h4>Oudere projecten:</h4>
<div class="row">
<div class="card">
<a target="_blank" href="https://wterminal.truyen.network">
<h3>WTerminal</h3>
</a>
<p>JavaScript 2023-2024<br>
Kan gebruikt worden in websites en als browser-addon</p>
<h5>Screenshot:</h5>
<img style="width: 100%" src="img/wterminal.png" />
</div>
<div class="card">
<h3>Ronny</h3>
<p>VB.net 2004-2006<br>Game met Direct draw rendering</p>
<h5>Youtube video:</h5>
<iframe src="https://www.youtube.com/embed/m7tgDUc2jXs">
</iframe>
</div>
<div class="card">
<h3>Minesweeper</h3>
<p>C/C++ 2006-2013<br>Game met OpenGL rendering</p>
<h5>Youtube video:</h5>
<iframe src="https://www.youtube.com/embed/Rejp6cVRxfc">
</iframe>
</div>
</div>
</section>
</main>
<footer class="text-end">
<p class="text-secondary my-0 me-1">Life is a long lesson in humility.</p>
</footer>
<script src="js/bootstrap.min.js"></script>
<script src="js/starback.js"></script>
<canvas id="canvas"></canvas>
<script src="js/main.js"> </script>
<script src="js/oneko.js"> </script>
</body>
</html>

7
src/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

49
src/js/main.js Normal file
View File

@@ -0,0 +1,49 @@
const starback = new Starback("#canvas", {
width: document.body.clientWidth,
height: document.body.clientHeight,
type: 'dot',
quantity: 100,
direction: 225,
backgroundColor: ['#0e1118', '#232b3e'],
randomOpacity: true,
});
const mountain = new Image();
mountain.src = 'img/mountain2.png';
mountain.onload = () => {
starback.addToFront((ctx) => {
ctx.drawImage(
mountain,
0,
0,
mountain.width,
mountain.height,
0,
canvas.height - mountain.height,
canvas.width,
mountain.height
);
});
}
function resizeCanvas() {
const canvas = document.getElementById("canvas");
canvas.setAttribute("width", window.innerWidth);
canvas.setAttribute("height", window.innerHeight);
}
function onLoadDoc() {
resizeCanvas();
const elements = document.getElementsByClassName("nav-link");
for (const el of elements) {
el.onclick = onNavLinkClick;
}
}
function onNavLinkClick() {
const collapse = document.getElementsByClassName('navbar-collapse');
if (collapse[0] != null)
collapse[0].classList.remove('show');
}
window.addEventListener("resize", resizeCanvas);
window.addEventListener("load", onLoadDoc);

310
src/js/oneko.js Normal file
View File

@@ -0,0 +1,310 @@
// oneko.js: https://github.com/adryd325/oneko.js
var onekoEnabled = true;
(function oneko() {
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
const isReducedMotion =
window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||
window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;
if (isReducedMotion || isMobile)
{
console.log("disabling cat");
onekoEnabled = false;
return;
}
const nekoEl = document.createElement("div");
let nekoPosX = window.innerWidth + 32;
let nekoPosY = window.innerHeight + 32;
let mousePosX = 0;
let mousePosY = 0;
let frameCount = 0;
let idleTime = 0;
let idleAnimation = null;
let idleAnimationFrame = 0;
const nekoSpeed = 10;
const spriteSets = {
idle: [[-3, -3]],
alert: [[-7, -3]],
scratchSelf: [
[-5, 0],
[-6, 0],
[-7, 0],
],
scratchWallN: [
[0, 0],
[0, -1],
],
scratchWallS: [
[-7, -1],
[-6, -2],
],
scratchWallE: [
[-2, -2],
[-2, -3],
],
scratchWallW: [
[-4, 0],
[-4, -1],
],
tired: [[-3, -2]],
sleeping: [
[-2, 0],
[-2, -1],
],
N: [
[-1, -2],
[-1, -3],
],
NE: [
[0, -2],
[0, -3],
],
E: [
[-3, 0],
[-3, -1],
],
SE: [
[-5, -1],
[-5, -2],
],
S: [
[-6, -3],
[-7, -2],
],
SW: [
[-5, -3],
[-6, -1],
],
W: [
[-4, -2],
[-4, -3],
],
NW: [
[-1, 0],
[-1, -1],
],
};
function init() {
nekoEl.id = "oneko";
nekoEl.ariaHidden = true;
nekoEl.style.width = "32px";
nekoEl.style.height = "32px";
nekoEl.style.position = "fixed";
nekoEl.style.pointerEvents = "none"; // no petting :(
nekoEl.style.imageRendering = "pixelated";
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
nekoEl.style.zIndex = 999999;
let nekoFile = "/img/oneko.gif"
const curScript = document.currentScript
if (curScript && curScript.dataset.cat) {
nekoFile = curScript.dataset.cat
}
nekoEl.style.backgroundImage = `url(${nekoFile})`;
document.body.appendChild(nekoEl);
document.addEventListener("mousemove", function(event) {
mousePosX = event.clientX;
mousePosY = event.clientY;
});
window.requestAnimationFrame(onAnimationFrame);
}
let lastFrameTimestamp;
function onAnimationFrame(timestamp) {
// Stops execution if the neko element is removed from DOM
if (!nekoEl.isConnected) {
return;
}
if (!lastFrameTimestamp) {
lastFrameTimestamp = timestamp;
}
if (timestamp - lastFrameTimestamp > 100) {
lastFrameTimestamp = timestamp
frame()
}
window.requestAnimationFrame(onAnimationFrame);
}
function setSprite(name, frame) {
const sprite = spriteSets[name][frame % spriteSets[name].length];
nekoEl.style.backgroundPosition = `${sprite[0] * 32}px ${sprite[1] * 32}px`;
}
function resetIdleAnimation() {
idleAnimation = null;
idleAnimationFrame = 0;
}
function idle() {
idleTime += 1;
// every ~ 20 seconds
if (
idleTime > 10 &&
Math.floor(Math.random() * 200) == 0 &&
idleAnimation == null
) {
let avalibleIdleAnimations = ["sleeping", "scratchSelf"];
let scratchDist = 64;
if (nekoPosX < scratchDist) {
avalibleIdleAnimations.push("scratchWallW");
}
if (nekoPosY < scratchDist) {
avalibleIdleAnimations.push("scratchWallN");
}
if (nekoPosX > window.innerWidth - scratchDist) {
avalibleIdleAnimations.push("scratchWallE");
}
if (nekoPosY > window.innerHeight - scratchDist) {
avalibleIdleAnimations.push("scratchWallS");
}
idleAnimation =
avalibleIdleAnimations[
Math.floor(Math.random() * avalibleIdleAnimations.length)
];
}
switch (idleAnimation) {
case "sleeping":
if (idleAnimationFrame < 8) {
setSprite("tired", 0);
break;
}
setSprite("sleeping", Math.floor(idleAnimationFrame / 4));
if (idleAnimationFrame > 192) {
resetIdleAnimation();
}
break;
case "scratchWallN":
case "scratchWallS":
case "scratchWallE":
case "scratchWallW":
case "scratchSelf":
setSprite(idleAnimation, idleAnimationFrame);
if (idleAnimationFrame > 9) {
resetIdleAnimation();
}
break;
default:
setSprite("idle", 0);
return;
}
idleAnimationFrame += 1;
}
function explodeHearts() {
const parent = nekoEl.parentElement;
const rect = nekoEl.getBoundingClientRect();
const scrollLeft = window.scrollX || document.documentElement.scrollLeft;
const scrollTop = window.scrollY || document.documentElement.scrollTop;
const centerX = rect.left + rect.width / 2 + scrollLeft;
const centerY = rect.top + rect.height / 2 + scrollTop;
for (let i = 0; i < 10; i++) {
const heart = document.createElement('div');
heart.className = 'heart';
heart.textContent = '❤';
const offsetX = (Math.random() - 0.5) * 50;
const offsetY = (Math.random() - 0.5) * 50;
heart.style.left = `${centerX + offsetX - 16}px`;
heart.style.top = `${centerY + offsetY - 16}px`;
heart.style.transform = `translate(-50%, -50%) rotate(${Math.random() * 360}deg)`;
parent.appendChild(heart);
setTimeout(() => {
parent.removeChild(heart);
}, 1000);
}
}
const style = document.createElement('style');
style.innerHTML = `
@keyframes heartBurst {
0% { transform: scale(0); opacity: 1; }
100% { transform: scale(1); opacity: 0; }
}
.heart {
position: absolute;
font-size: 2em;
animation: heartBurst 1s ease-out;
animation-fill-mode: forwards;
color: #ab9df2;
user-select: none;
}
`;
document.head.appendChild(style);
nekoEl.addEventListener('click', explodeHearts);
let previousOnekoEnabled = onekoEnabled;
function frame() {
if(previousOnekoEnabled != onekoEnabled)
{
nekoEl.style.display = onekoEnabled ? "block" : "none";
if(onekoEnabled)
document.getElementById("toggle-cat").classList.remove("sleepy");
else
document.getElementById("toggle-cat").classList.add("sleepy");
previousOnekoEnabled = onekoEnabled;
}
if (!onekoEnabled || mousePosX == 0 || mousePosY == 0)
return;
frameCount += 1;
const diffX = nekoPosX - mousePosX;
const diffY = nekoPosY - mousePosY;
const distance = Math.sqrt(diffX ** 2 + diffY ** 2);
if (distance < nekoSpeed || distance < 48) {
idle();
return;
}
idleAnimation = null;
idleAnimationFrame = 0;
if (idleTime > 1) {
setSprite("alert", 0);
// count down after being alerted before moving
idleTime = Math.min(idleTime, 7);
idleTime -= 1;
return;
}
let direction;
direction = diffY / distance > 0.5 ? "N" : "";
direction += diffY / distance < -0.5 ? "S" : "";
direction += diffX / distance > 0.5 ? "W" : "";
direction += diffX / distance < -0.5 ? "E" : "";
setSprite(direction, frameCount);
nekoPosX -= (diffX / distance) * nekoSpeed;
nekoPosY -= (diffY / distance) * nekoSpeed;
nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16);
nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16);
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
}
init();
})();

File diff suppressed because one or more lines are too long

1
src/js/starback.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,38 +0,0 @@
function toggleTheme() {
const theme = "theme-dark";//localStorage.getItem('theme');
const root = document.querySelector(":root");
root.classList.toggle(theme);
if (root.classList.contains(theme)) {
localStorage.setItem('theme', theme);
} else {
localStorage.setItem('theme', "theme-light");
}
}
function setTheme(themeName) {
console.log("setting them: " + themeName);
const root = document.querySelector(":root");
root.classList.add(themeName);
localStorage.setItem('theme', themeName);
}
function detectTheme() {
const theme = localStorage.getItem('theme');
if (theme === 'theme-dark' || theme === 'theme-light') {
setTheme(theme);
return;
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
setTheme('theme-dark');
return;
}
if (window.matchMedia('(prefers-color-scheme: light)').matches) {
setTheme('theme-light');
return;
}
setTheme('theme-light');
}
detectTheme();