diff --git a/src/content/links.json b/src/content/links.json
new file mode 100644
index 0000000..86803d0
--- /dev/null
+++ b/src/content/links.json
@@ -0,0 +1,130 @@
+{
+ "links": [
+ {
+ "name": "Chess.org",
+ "href": "https://www.chess.com/member/brulijam",
+ "icon": "https://simpleicons.org/icons/chessdotcom.svg",
+ "group": 2
+ },
+ {
+ "name": "Credit Card",
+ "href": "mastercard.html",
+ "icon": "https://simpleicons.org/icons/mastercard.svg",
+ "group": 5
+ },
+ {
+ "name": "Discord",
+ "href": "https://discordapp.com/users/144893706514726913",
+ "icon": "https://simpleicons.org/icons/discord.svg",
+ "group": 0
+ },
+ {
+ "name": "Folding@home",
+ "href": "https://stats.foldingathome.org/donor/id/72929244",
+ "icon": "",
+ "group": 5
+ },
+ {
+ "name": "Github",
+ "href": "https://github.com/Brulijam",
+ "icon": "https://simpleicons.org/icons/github.svg",
+ "group": 1
+ },
+ {
+ "name": "Gitea",
+ "href": "https://git.brulijam.com/brulijam",
+ "icon": "https://simpleicons.org/icons/gitea.svg",
+ "group": 1
+ },
+ {
+ "name": "Instagram",
+ "href": "https://instagram.com/julian.brammer",
+ "icon": "https://simpleicons.org/icons/instagram.svg",
+ "group": 0
+ },
+ {
+ "name": "Lichess",
+ "href": "https://lichess.org/@/brulijam",
+ "icon": "https://simpleicons.org/icons/lichess.svg",
+ "group": 2
+ },
+ {
+ "name": "Mastodon",
+ "href": "https://mstdn.brulijam.dev/@brulijam",
+ "icon": "https://simpleicons.org/icons/mastodon.svg",
+ "group": 0
+ },
+ {
+ "name": "Matrix",
+ "href": "https://brulijam.dev/mtrx/#/@brulijam:brulijam.dev?web-instance[element.io]=chat.brulijam.dev&client=element.io",
+ "icon": "https://simpleicons.org/icons/matrix.svg",
+ "group": 0
+ },
+ {
+ "name": "Obsidian",
+ "href": "https://md.brulijam.com",
+ "icon": "https://simpleicons.org/icons/obsidian.svg",
+ "group": 1
+ },
+ {
+ "name": "Osu!",
+ "href": "https://osu.ppy.sh/users/3490953",
+ "icon": "https://simpleicons.org/icons/osu.svg",
+ "group": 2
+ },
+ {
+ "name": "PayPal",
+ "href": "https://www.paypal.com/paypalme/julianbrammer/",
+ "icon": "https://simpleicons.org/icons/paypal.svg",
+ "group": 5
+ },
+ {
+ "name": "Screeps",
+ "href": "https://screeps.com/a/#!/profile/Brulijam",
+ "icon": "",
+ "group": 2
+ },
+ {
+ "name": "Signal",
+ "href": "https://signal.me/#eu/Bt1D65df5FOnAZVB0u9WHJG5wAz2WLnS_ALOiTAUmXHbs66TAjdHZ4YJi_wbyJnq",
+ "icon": "https://simpleicons.org/icons/signal.svg",
+ "group": 0
+ },
+ {
+ "name": "Snapchat",
+ "href": "https://www.snapchat.com/add/julian.brammer",
+ "icon": "https://simpleicons.org/icons/snapchat.svg",
+ "group": 0
+ },
+ {
+ "name": "Soundcloud",
+ "href": "https://soundcloud.com/brulijam",
+ "icon": "https://simpleicons.org/icons/soundcloud.svg",
+ "group": 1
+ },
+ {
+ "name": "Spotify",
+ "href": "https://open.spotify.com/user/giibu0t7te5mchiu2ugisudnv",
+ "icon": "https://simpleicons.org/icons/spotify.svg",
+ "group": 1
+ },
+ {
+ "name": "Steam",
+ "href": "https://steamcommunity.com/id/Brulijam/",
+ "icon": "https://simpleicons.org/icons/steam.svg",
+ "group": 2
+ },
+ {
+ "name": "Telegram",
+ "href": "https://t.me/julian_brammer",
+ "icon": "https://simpleicons.org/icons/telegram.svg",
+ "group": 0
+ },
+ {
+ "name": "Youtube",
+ "href": "https://youtube.com/@brulijam",
+ "icon": "https://simpleicons.org/icons/youtube.svg",
+ "group": 1
+ }
+ ]
+}
diff --git a/src/content/video.mp4 b/src/content/video.mp4
new file mode 100644
index 0000000..8cb2887
Binary files /dev/null and b/src/content/video.mp4 differ
diff --git a/src/css/main.css b/src/css/main.css
new file mode 100644
index 0000000..a5c19a8
--- /dev/null
+++ b/src/css/main.css
@@ -0,0 +1,158 @@
+:root {
+ --bg-color: rgb(16, 16, 16);
+ --primary: rgb(240, 240, 240);
+
+ --secondary-color: rgb(0, 138, 216);
+
+ --font-weight: 400;
+ --font-family: "Lucida Console";
+
+ --link-font-weight: 1000;
+ --link-border-radius: 10px;
+
+ --page-max-width: 800px;
+}
+
+/* General */
+body {
+ background-color: var(--bg-color);
+ color: var(--primary);
+ font-family: var(--font-family), monospace;
+ font-weight: var(--font-weight);
+ overflow-x: hidden;
+ margin: 20px;
+
+ & a {
+ color: var(--secondary-color);
+ }
+
+ & a:hover {
+ text-decoration: none;
+ }
+
+ & h1, p {
+ margin: 0;
+ }
+}
+
+main {
+ max-width: var(--page-max-width);
+ margin: 0 auto;
+}
+
+/* Header*/
+header {
+ text-align: center;
+ width: max-content;
+ margin: 0 auto;
+
+ & .names {
+ /*margin: 0 auto;*/
+ width: min-content;
+ white-space: nowrap;
+
+ & h1, p {
+
+ text-align: left;
+ color: var(--secondary-color);
+ }
+ }
+
+ & img {
+ border-radius: 50%;
+ max-width: 300px;
+ padding: 0;
+ }
+}
+
+/* Links */
+.linkGroup {
+ margin: auto;
+ box-sizing: border-box;
+
+ /* if wide */
+ @media only screen and (min-width: 480px) {
+ display: flex;
+ flex-wrap: wrap;
+ }
+
+ & .link {
+ height: fit-content;
+ position: relative;
+ top: 0;
+ transition: top ease 100ms;
+
+ /* if slim */
+ @media only screen and (max-width: 480px) {
+ margin-bottom: 10px;
+ margin-left: 10%;
+ margin-right: 10%;
+ }
+
+ /* if wide */
+ @media only screen and (min-width: 480px) {
+ padding: 5px;
+ }
+ }
+}
+
+
+.linkButton {
+ font-weight: var(--link-font-weight);
+ font-size: 25px;
+ line-height: 30px;
+ text-align: center;
+ text-decoration: none;
+
+ color: rgb(0, 0, 0);
+ background-color: var(--secondary-color);
+
+ display: block;
+ box-sizing: border-box;
+ padding: 10px 20px;
+ border-radius: var(--link-border-radius);
+
+ /* if slim */
+ @media only screen and (max-width: 480px) {
+ width: 100%;
+ }
+
+ & .icon {
+ width: 20px;
+ height: 20px;
+ padding-right: 10px;
+ padding-bottom: 4px;
+ vertical-align: middle;
+ }
+}
+
+.link:hover {
+ filter: drop-shadow(0px 0px 5px var(--secondary-color)) brightness(1.05);
+ top: -2px;
+}
+
+.links:hover .link:not(:hover) a {
+ filter: brightness(0.8);
+}
+
+/* Timers */
+.timer p {
+ /* if slim */
+ @media only screen and (max-width: 480px) {
+ margin-bottom: 20px;
+ }
+}
+
+.timer p span {
+ color: var(--secondary-color);
+ text-decoration: none;
+}
+
+/* Footer */
+footer {
+ text-align: center;
+
+ & a {
+ padding: 0 2px;
+ }
+}
\ No newline at end of file
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 0000000..5691bf4
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,65 @@
+
+
+
+
+
+ Brulijam
+
+
+
+
+
+
+
+
+
+
Julian Brammer
+
@brulijam
+
+
+
+
+ Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
+ dolore magna aliquyam erat, sed diam
+ voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
+ takimata sanctus est Lorem ipsum dolor sit
+ amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
+ labore et dolore magna aliquyam erat, sed
+ diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
+ takimata sanctus est Lorem ipsum dolor sit
+ amet.
+
+
+
+
+
+ javascript is not available. You can still see a list of my links here .
+
+
+
+
+ alive for seconds.
+ next birthday in seconds.
+ employed at subshell for
+ seconds.
+
+
+ alive since 1999-07-20T00:00:00 .
+ working at subshell since 2024-05-02T09:00:00 .
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/js/links.js b/src/js/links.js
new file mode 100644
index 0000000..35613aa
--- /dev/null
+++ b/src/js/links.js
@@ -0,0 +1,45 @@
+function createLinkDiv(link) {
+ const linkDiv = document.createElement('div');
+ linkDiv.className = 'link';
+
+ const anchor = document.createElement('a');
+ anchor.className = 'linkButton';
+ anchor.href = link.href;
+ anchor.target = '_blank';
+ anchor.innerHTML = link.icon ? ` ${link.name}` : link.name;
+
+ linkDiv.appendChild(anchor);
+ return linkDiv;
+}
+
+function createGroups(linksData) {
+ const container = document.querySelector('.links');
+
+ const groups = [...new Set(linksData.map(link => link.group))].sort((a, b) => a - b);
+
+ groups.forEach((group, index) => {
+ const groupContainer = document.createElement('div');
+ groupContainer.className = 'linkGroup';
+
+ linksData
+ .filter(link => link.group === group)
+ .forEach(link => {
+ const linkElement = createLinkDiv(link);
+ groupContainer.appendChild(linkElement);
+ });
+
+ container.appendChild(groupContainer);
+
+ if (index < groups.length - 1) {
+ const br = document.createElement('br');
+ container.appendChild(br);
+ }
+ });
+}
+
+fetch('content/links.json')
+ .then(response => response.json())
+ .then(data => {
+ createGroups(data.links);
+ })
+ .catch(error => console.error('Error:', error));
diff --git a/src/js/main.js b/src/js/main.js
new file mode 100644
index 0000000..0a2dec5
--- /dev/null
+++ b/src/js/main.js
@@ -0,0 +1,22 @@
+const secondaryColors = [
+ // "rgb(240, 240, 240)",
+ // "rgb(136, 139, 141)",
+ "rgb(224, 231, 34)",
+ "rgb(255, 173, 0)",
+ "rgb(244,54,76)",
+ // "rgb(219, 62, 177)",
+ "rgb(250, 150, 250)",
+ "rgb(250, 150, 150)",
+ "rgb(242, 172, 185)",
+ "rgb(0, 138, 216)",
+ "rgb(0, 178, 169)",
+ "rgb(88, 188, 64)",
+ "rgb(173, 223, 179)"
+];
+
+function setRandomSecondaryColor() {
+ const randomColor = secondaryColors[Math.floor(Math.random() * secondaryColors.length)];
+ document.documentElement.style.setProperty('--secondary-color', randomColor);
+}
+
+setRandomSecondaryColor();
diff --git a/src/js/timer.js b/src/js/timer.js
new file mode 100644
index 0000000..c51a123
--- /dev/null
+++ b/src/js/timer.js
@@ -0,0 +1,55 @@
+const birthdate = new Date("1999-07-20T00:00:00");
+const employedSince = new Date("2024-05-02T09:00:00");
+
+window.onload = startTimer;
+
+function startTimer() {
+ calculateTime();
+ setInterval(calculateTime, 42);
+}
+
+function calculateTime() {
+ const now = new Date();
+
+ // timer-alive-since
+ const aliveSinceMs = now - birthdate;
+ let aliveSinceTenthOfASecond = Math.floor((aliveSinceMs % 1000) / 10);
+ aliveSinceTenthOfASecond = aliveSinceTenthOfASecond.toString().padStart(2, "0");
+ const aliveSinceS = Math.floor(aliveSinceMs / 1000);
+
+ // timer-until-birthday
+ const nextBirthday = new Date(now.getFullYear(), birthdate.getMonth(), birthdate.getDate(),
+ birthdate.getHours(), birthdate.getMinutes(), birthdate.getSeconds());
+ if (nextBirthday < now) {
+ nextBirthday.setFullYear(now.getFullYear() + 1);
+ }
+ const nextBirthdayMs = nextBirthday - now;
+ let nextBirthdayTenthOfASecond = Math.floor((nextBirthdayMs % 1000) / 10);
+ nextBirthdayTenthOfASecond = nextBirthdayTenthOfASecond.toString().padStart(2, "0");
+ const nextBirthdayS = Math.floor(nextBirthdayMs / 1000);
+
+ // timer-employed-since
+ const employedSinceMs = now - employedSince;
+ let employedSinceTenthOfASecond = Math.floor((employedSinceMs % 1000) / 10);
+ employedSinceTenthOfASecond = employedSinceTenthOfASecond.toString().padStart(2, "0");
+ const employedSinceS = Math.floor(employedSinceMs / 1000);
+
+ // Update Document
+ updateDocument("timer-alive-since-s", `${formatNumber(aliveSinceS)}`)
+ updateDocument("timer-alive-since-ms", `.${formatNumber(aliveSinceTenthOfASecond)}`)
+ updateDocument("timer-until-birthday-s", `${formatNumber(nextBirthdayS)}`)
+ updateDocument("timer-until-birthday-ms", `.${formatNumber(nextBirthdayTenthOfASecond)}`)
+ updateDocument("timer-employed-since-s", `${formatNumber(employedSinceS)}`)
+ updateDocument("timer-employed-since-ms", `.${formatNumber(employedSinceTenthOfASecond)}`)
+}
+
+function updateDocument(id, value) {
+ const element = document.getElementById(id);
+ if (element) {
+ element.innerHTML = value;
+ }
+}
+
+function formatNumber(number) {
+ return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+}
\ No newline at end of file
diff --git a/src/mastercard.html b/src/mastercard.html
new file mode 100644
index 0000000..2296e23
--- /dev/null
+++ b/src/mastercard.html
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Brulijam
+
+
+
+
+
+
+ Sorry, your browser doesn't support embedded videos.
+
+
+
+
\ No newline at end of file
diff --git a/src/timers.html b/src/timers.html
new file mode 100644
index 0000000..68e00d5
--- /dev/null
+++ b/src/timers.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file