aboutsummaryrefslogtreecommitdiff
path: root/front/src
diff options
context:
space:
mode:
Diffstat (limited to 'front/src')
-rw-r--r--front/src/app.css120
-rw-r--r--front/src/app.tsx34
-rw-r--r--front/src/components/carousel.css68
-rw-r--r--front/src/components/carousel.tsx31
-rw-r--r--front/src/components/navbar-item.tsx8
-rw-r--r--front/src/components/navbar.css277
-rw-r--r--front/src/components/navbar.tsx20
-rw-r--r--front/src/index.css121
-rw-r--r--front/src/main.tsx5
-rw-r--r--front/src/pages/contact.css22
-rw-r--r--front/src/pages/contact.tsx34
-rw-r--r--front/src/pages/games.css0
-rw-r--r--front/src/pages/games.tsx393
-rw-r--r--front/src/pages/home.tsx29
-rw-r--r--front/src/pages/projects.css137
-rw-r--r--front/src/pages/projects.tsx50
-rw-r--r--front/src/vite-env.d.ts1
17 files changed, 1350 insertions, 0 deletions
diff --git a/front/src/app.css b/front/src/app.css
new file mode 100644
index 0000000..b4086a2
--- /dev/null
+++ b/front/src/app.css
@@ -0,0 +1,120 @@
+#app-main {
+ font-family: 'Hack', monospace;
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem 2rem 2rem 2rem;
+ text-align: center;
+}
+
+#app {
+ margin: 0 auto;
+ text-align: center;
+ align-content: center;
+ justify-content: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.preact:hover {
+ filter: drop-shadow(0 0 2em #673ab8aa);
+}
+
+.main-info {
+ text-align: center;
+}
+
+@media (min-width: 1150px) {
+ .main-info {
+ margin-top: 72px;
+ }
+}
+
+.main-info-image {
+ width: 128px;
+ height: 128px;
+ border-radius: 100%;
+ margin: 6px 6px 6px 6px;
+}
+
+.main-info-title {
+ font-size: 42pt;
+}
+
+.main-info-subtitle {
+ font-size: 26pt;
+ font-style: italic;
+ color: #5c6370;
+}
+
+.quiet {
+ color: var(--color-gray);
+ font-style: italic;
+}
+
+.section {
+ font-size: 22pt;
+}
+
+.highlight {
+ color: #e5c07b;
+}
+
+@media (max-width: 480px) {
+ .main-info-title {
+ font-size: 32pt;
+ }
+
+ .main-info-subtitle {
+ font-size: 18pt;
+ }
+}
+
+@media (max-width: 1150px) and (min-width: 480px) {
+ .main-info-title {
+ font-size: 42pt;
+ }
+
+ .main-info-subtitle {
+ font-size: 26pt;
+ }
+}
+
+@media (min-width: 1150px) {
+ .main-info-title {
+ font-size: 42pt;
+ }
+
+ .main-info-subtitle {
+ font-size: 26pt;
+ }
+}
+
+
+@media (max-width: 480px) {
+ .about-paragraph {
+ margin: auto;
+ font-size: 16pt;
+ max-width: 90%;
+ }
+}
+
+@media (max-width: 1150px) and (min-width: 480px) {
+ .about-paragraph {
+ margin: auto;
+ font-size: 18pt;
+ max-width: 80%;
+ }
+}
+
+@media (min-width: 1150px) {
+ .about-paragraph {
+ margin: auto;
+ font-size: 18pt;
+ max-width: 60%;
+ }
+}
diff --git a/front/src/app.tsx b/front/src/app.tsx
new file mode 100644
index 0000000..5ba8e6f
--- /dev/null
+++ b/front/src/app.tsx
@@ -0,0 +1,34 @@
+import './app.css'
+import { Navbar } from './components/navbar'
+import Contact from './pages/contact';
+import Games from './pages/games';
+import Home from './pages/home'
+import { Router, Route, CustomHistory } from 'preact-router';
+import Projects from './pages/projects';
+import { HashHistory, createHashHistory } from 'history';
+
+const hashHistoryAdapter = (hashHistory: HashHistory): CustomHistory => {
+ return {
+ listen: (callback) => hashHistory.listen(({ location }) => callback(location)),
+ location: hashHistory.location,
+ push: hashHistory.push,
+ replace: hashHistory.replace
+ };
+};
+export function App() {
+ const history = hashHistoryAdapter(createHashHistory());
+
+ return (
+ <>
+ <Navbar />
+ <div id="app-main">
+ <Router history={history}>
+ <Route path="/" component={Home} />
+ <Route path="/contact" component={Contact} />
+ <Route path="/games" component={Games} />
+ <Route path="/projects" component={Projects} />
+ </Router>
+ </div>
+ </>
+ )
+}
diff --git a/front/src/components/carousel.css b/front/src/components/carousel.css
new file mode 100644
index 0000000..f311805
--- /dev/null
+++ b/front/src/components/carousel.css
@@ -0,0 +1,68 @@
+.carousel-content {
+ align-self: center;
+ max-height: 100%;
+ white-space: nowrap;
+ -ms-overflow-style: none; /* hide scrollbar in IE and Edge */
+ scrollbar-width: none; /* hide scrollbar in Firefox */
+}
+
+.carousel-item {
+ width: 100%;
+ flex-shrink: 0;
+ height: auto;
+ float: left;
+ text-align: center;
+ transition: all 250ms linear;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+.slick-slider {
+ margin: 24px;
+}
+
+.slick-slide {
+ margin: 0 auto;
+ border-radius: 10px;
+ text-align: center;
+ float: none !important;
+ display: inline-block !important;
+ vertical-align: middle;
+ min-height: 1px;
+}
+
+.carousel-item > * {
+ border-radius: 10px;
+ vertical-align: middle;
+ width: 100%;
+ height: auto;
+}
+
+.slick-dots li button::before {
+ color: var(--color-fg) !important;
+}
+
+@media (max-width: 1150px) {
+ .carousel-wrapper {
+ margin: 60px auto;
+ width: 330px;
+ height: 220px;
+ }
+}
+
+@media (max-width: 1150px) and (min-width: 480px) {
+ .carousel-wrapper {
+ margin: 60px auto;
+ width: 480px;
+ height: 360px;
+ }
+}
+
+@media (min-width: 1150px) {
+ .carousel-wrapper {
+ float: right;
+ width: 480px;
+ height: 360px;
+ }
+}
+
diff --git a/front/src/components/carousel.tsx b/front/src/components/carousel.tsx
new file mode 100644
index 0000000..af9279b
--- /dev/null
+++ b/front/src/components/carousel.tsx
@@ -0,0 +1,31 @@
+import './carousel.css';
+import Slider, { Settings } from 'react-slick';
+import "slick-carousel/slick/slick.css";
+import "slick-carousel/slick/slick-theme.css";
+
+export default function Carousel(props: { children: any }) {
+ const settings: Settings = {
+ dots: true,
+ infinite: true,
+ speed: 500,
+ slidesToShow: 1,
+ slidesToScroll: 1
+ };
+
+ return (
+ <div class="carousel-wrapper">
+ <Slider {...settings}>
+ {
+ props.children instanceof Array ?
+ props.children.map((child: any) => {
+ return (
+ <div class="carousel-item">{child}</div>
+ );
+ })
+ :
+ <div class="carousel-item">{props.children}</div>
+ }
+ </Slider>
+ </div>
+ );
+}
diff --git a/front/src/components/navbar-item.tsx b/front/src/components/navbar-item.tsx
new file mode 100644
index 0000000..c2f2306
--- /dev/null
+++ b/front/src/components/navbar-item.tsx
@@ -0,0 +1,8 @@
+import * as preact from "preact";
+
+export function NavbarItem(props: any) {
+ const { name, href, children, rel } = props;
+
+ return (preact.createElement("div", { className: "navbar-item" },
+ preact.createElement("a", { className: "navbar-item-" + name, href: href, rel: rel }, children)));
+}
diff --git a/front/src/components/navbar.css b/front/src/components/navbar.css
new file mode 100644
index 0000000..466fdd6
--- /dev/null
+++ b/front/src/components/navbar.css
@@ -0,0 +1,277 @@
+/* on big screens, navbar is fixed to the top of the screen */
+.navbar-container {
+ position: fixed;
+ background-color: var(--color-bg);
+ top: 0;
+ width: 100%;
+ z-index: 9999;
+ margin: auto;
+}
+
+/* on smaller ones, make it behave as a normal element laid out at the top of the page */
+@media (max-width: 1150px) {
+ .navbar-container {
+ position: static;
+ }
+}
+
+.navbar {
+ margin-top: 20pt;
+ margin-bottom: 12pt;
+ align-items: center;
+ justify-content: center;
+ align-self: center;
+}
+
+.navbar-icon {
+ font-family: Hack, monospace;
+ font-weight: 500;
+ color: #646cff;
+ font-size: 1.5em;
+ padding: 0.5em;
+ margin: 0.5em;
+}
+
+.navbar {
+ align-self: center;
+ display: block;
+ width: 100%;
+ text-align: center;
+}
+
+.navbar-item {
+ font-family: Hack, monospace;
+ font-size: 18pt;
+ text-align: center;
+ float: none;
+ clear: left;
+ display: inline-block;
+ margin: 0 0.25em;
+ transition: all 0.2s ease-in-out;
+}
+
+.navbar-item:hover {
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ transition: all 0.2s ease-in-out;
+}
+
+.navbar-current {
+ font-weight: bold;
+}
+
+/* home */
+
+.navbar-item-home:link {
+ color: #98C379;
+ text-decoration: none;
+}
+
+.navbar-item-home:visited {
+ color: #98C379;
+ text-decoration: none;
+}
+
+.navbar-item-home:hover {
+ color: #afd088;
+ text-decoration: underline;
+}
+
+.navbar-item-home:active {
+ color: #afd088;
+ text-decoration: underline;
+}
+
+/* games */
+
+.navbar-item-games:link {
+ color: #e06c75;
+ text-decoration: none;
+}
+
+.navbar-item-games:visited {
+ color: #e06c75;
+ text-decoration: none;
+}
+
+.navbar-item-games:hover {
+ color: #ef7a80;
+ text-decoration: underline;
+}
+
+.navbar-item-games:active {
+ color: #ef7a90;
+ text-decoration: underline;
+}
+
+/* projects */
+
+.navbar-item-projects:link {
+ color: #d19a66;
+ text-decoration: none;
+}
+
+.navbar-item-projects:visited {
+ color: #d19a66;
+ text-decoration: none;
+}
+
+.navbar-item-projects:hover {
+ color: #dfa873;
+ text-decoration: underline;
+}
+
+.navbar-item-projects:active {
+ color: #dffa73;
+ text-decoration: underline;
+}
+
+/* github */
+
+.navbar-item-github:link {
+ color: #c678dd;
+ text-decoration: none;
+}
+
+.navbar-item-github:visited {
+ color: #c678dd;
+ text-decoration: none;
+}
+
+.navbar-item-github:hover {
+ color: #d286eb;
+ text-decoration: underline;
+}
+
+.navbar-item-github:active {
+ color: #d286eb;
+ text-decoration: underline;
+}
+
+/* itch */
+
+.navbar-item-itch:link {
+ color: #e06c75;
+ text-decoration: none;
+}
+
+.navbar-item-itch:visited {
+ color: #e06c75;
+ text-decoration: none;
+}
+
+.navbar-item-itch:hover {
+ color: #ef7a80;
+ text-decoration: underline;
+}
+
+.navbar-item-itch:active {
+ color: #ef7a90;
+ text-decoration: underline;
+}
+
+/* twitter */
+
+.navbar-item-twitter:link {
+ text-decoration: none;
+}
+
+.navbar-item-twitter:visited {
+ text-decoration: none;
+}
+
+.navbar-item-twitter:hover {
+ text-decoration: underline;
+}
+
+.navbar-item-twitter:active {
+ text-decoration: underline;
+}
+
+/* mastodon */
+
+.navbar-item-mastodon:link {
+ color: #6a4ae0;
+ text-decoration: none;
+}
+
+.navbar-item-mastodon:visited {
+ color: #6a4ae0;
+ text-decoration: none;
+}
+
+.navbar-item-mastodon:hover {
+ color: #7a55e8;
+ text-decoration: underline;
+}
+
+.navbar-item-mastodon:active {
+ color: #7a55e8;
+ text-decoration: underline;
+}
+
+/* cohost */
+
+.navbar-item-cohost:link {
+ color: #b63b73;
+ text-decoration: none;
+}
+
+.navbar-item-cohost:visited {
+ color: #b63b73;
+ text-decoration: none;
+}
+
+.navbar-item-cohost:hover {
+ color: #c54a7f;
+ text-decoration: underline;
+}
+
+.navbar-item-cohost:active {
+ color: #c54a7f;
+ text-decoration: underline;
+}
+
+/* tumblr */
+
+.navbar-item-tumblr:link {
+ color: #00b8ff;
+ text-decoration: none;
+}
+
+.navbar-item-tumblr:visited {
+ color: #00b8ff;
+ text-decoration: none;
+}
+
+.navbar-item-tumblr:hover {
+ color: #00c5ff;
+ text-decoration: underline;
+}
+
+.navbar-item-tumblr:active {
+ color: #00c5ff;
+ text-decoration: underline;
+}
+
+/* contact */
+
+.navbar-item-contact:link {
+ color: #e5c07b;
+ text-decoration: none;
+}
+
+.navbar-item-contact:visited {
+ color: #e5c07b;
+ text-decoration: none;
+}
+
+.navbar-item-contact:hover {
+ color: #f2ce89;
+ text-decoration: underline;
+}
+
+.navbar-item-contact:active {
+ color: #f2ce89;
+ text-decoration: underline;
+}
diff --git a/front/src/components/navbar.tsx b/front/src/components/navbar.tsx
new file mode 100644
index 0000000..ba3d7d7
--- /dev/null
+++ b/front/src/components/navbar.tsx
@@ -0,0 +1,20 @@
+import './navbar.css';
+
+import { NavbarItem } from './navbar-item';
+
+export function Navbar() {
+ return (
+ <div class="navbar-container">
+ <div class="navbar">
+ <NavbarItem name="home" href="/">[Home]</NavbarItem>
+ <NavbarItem name="games" href="/games">[Games]</NavbarItem>
+ <NavbarItem name="projects" href="/projects">[Other Projects]</NavbarItem>
+ <NavbarItem name="github" href="https://github.com/Duckonaut">[GitHub]</NavbarItem>
+ <NavbarItem name="itch" href="https://duckonaut.itch.io/">[Itch.io]</NavbarItem>
+ <NavbarItem name="twitter" href="https://twitter.com/duckonaut">[Twitter]</NavbarItem>
+ <NavbarItem name="mastodon" href="https://mastodon.gamedev.place/@duckonaut" rel="me">[Mastodon]</NavbarItem>
+ <NavbarItem name="contact" href="/contact">[Contact]</NavbarItem>
+ </div>
+ </div>
+ );
+}
diff --git a/front/src/index.css b/front/src/index.css
new file mode 100644
index 0000000..cf6f743
--- /dev/null
+++ b/front/src/index.css
@@ -0,0 +1,121 @@
+:root {
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: var(--color-fg);
+ background-color: var(--color-bg);
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+
+ /* variables */
+ --color-bg: #161f30;
+ --color-fg: #a3b3d9;
+ --color-search-blue: #083C5A;
+ --color-white: #a3b3d9;
+ --color-gray: #647089;
+ --color-dark-gray: #3e4451;
+ --color-context: #6b737f;
+ --color-light-gray: #c8ccd4;
+ --color-tree-gray: #1b1f27;
+ --color-blue: #6080dd;
+ --color-vivid-blue: #61afef;
+ --color-dark-blue: #223E55;
+ --color-folder-blue: #61afef;
+ --color-light-blue: #a3b3d9;
+ --color-green: #449871;
+ --color-cyan: #56b6c2;
+ --color-light-green: #98c379;
+ --color-red: #c13251;
+ --color-orange: #c18a56;
+ --color-light-red: #e06c75;
+ --color-yellow: #e5c07b;
+ --color-purple: #604bd8;
+ --color-magenta: #b071fc;
+}
+
+a:link {
+ font-weight: 500;
+ color: #4fc1ff;
+ text-decoration: inherit;
+}
+
+a:visited {
+ color: #4fc1ff;
+}
+
+a:hover {
+ color: #60d2ff;
+}
+
+a:active {
+ color: #66d8ff;
+}
+
+
+body {
+ margin: 0;
+ /* display: flex; */
+ /* place-items: center; */
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+span {
+ display: inline;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
+
+.hack {
+ font-family: Hack, monospace;
+ font-weight: 500;
+}
+
+.grow {
+ transition: all .2s ease-in-out;
+ transform: scale(1);
+}
+
+.grow:hover {
+ transition: all .2s ease-in-out;
+ transform: scale(1.1);
+}
diff --git a/front/src/main.tsx b/front/src/main.tsx
new file mode 100644
index 0000000..846cd1e
--- /dev/null
+++ b/front/src/main.tsx
@@ -0,0 +1,5 @@
+import { render } from 'preact'
+import { App } from './app.tsx'
+import './index.css'
+
+render(<App />, document.getElementById('app')!)
diff --git a/front/src/pages/contact.css b/front/src/pages/contact.css
new file mode 100644
index 0000000..93b63bd
--- /dev/null
+++ b/front/src/pages/contact.css
@@ -0,0 +1,22 @@
+.contact-container {
+ width: 100%;
+ max-width: 1120px;
+ margin: auto;
+ margin-top: 24pt;
+ margin-bottom: 48pt;
+ align-items: center;
+ justify-content: center;
+ align-self: center;
+ font-size: 18pt;
+}
+
+.contact {
+ margin-top: 24pt;
+ margin-bottom: 8pt;
+ font-size: 20pt;
+ color: #98C379;
+}
+
+.highlight {
+ color: #e5c07b;
+}
diff --git a/front/src/pages/contact.tsx b/front/src/pages/contact.tsx
new file mode 100644
index 0000000..efc9eba
--- /dev/null
+++ b/front/src/pages/contact.tsx
@@ -0,0 +1,34 @@
+import './contact.css';
+
+export default function Contact() {
+ return (
+ <div class="main-info">
+ <div class="main-info-title">
+ Contact
+ </div>
+ <div class="contact-container">
+ <div class="contact">
+ Discord
+ </div>
+
+ <span class="quiet">usually the fastest way to reach me</span>
+ <br />
+ <span class="highlight">EchoDuck</span>#7866
+
+ <div class="contact">
+ Matrix
+ </div>
+ <span class="quiet">for the FOSS folks</span>
+ <br />
+ <span class="highlight">@echoduck</span>:matrix.org
+
+ <div class="contact">
+ Email
+ </div>
+ <span class="quiet">I check my email daily</span>
+ <br />
+ <span class="highlight">duckonaut</span>@gmail.com
+ </div>
+ </div>
+ );
+}
diff --git a/front/src/pages/games.css b/front/src/pages/games.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/front/src/pages/games.css
diff --git a/front/src/pages/games.tsx b/front/src/pages/games.tsx
new file mode 100644
index 0000000..314813d
--- /dev/null
+++ b/front/src/pages/games.tsx
@@ -0,0 +1,393 @@
+import Carousel from '../components/carousel';
+import './projects.css';
+
+export default function Games() {
+ return (
+ <>
+ <div class="main-info">
+ <div class="main-info-title">
+ Game Projects
+ </div>
+ <div class="main-info-subtitle">
+ my game projects, mostly from game jams
+ </div>
+ </div>
+ <div class="projects-container">
+ <div class="project">
+ <div class="project-title"><a href="https://jellingfish-games.itch.io/mr-final-boss">Mr. Final Boss</a>
+ </div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ <img class="grow icon" src="./assets/images/unity.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ <img class="grow icon" src="./assets/images/html5.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ The legends say that one day, brave Heroes will slay the evil and malicious Ignatius, the Chaos
+ Bringer... But YOU won't go down without a fight! Be the bossfight everyone is dreading and hunt
+ down as many Heroes as you can in your last stand using a variety of abilities you can choose from!
+ <br />
+ Game made in 72 hours for <a href="https://ldjam.com/events/ludum-dare/50">Ludum Dare 50</a>, with
+ the theme "Delay the Inevitable".
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/mr-final-boss/thumbnail.png" />
+ <img src="assets/games/mr-final-boss/screenshot1.png" />
+ <img src="assets/games/mr-final-boss/screenshot2.png" />
+ <img src="assets/games/mr-final-boss/screenshot3.png" />
+ <img src="assets/games/mr-final-boss/screenshot4.png" />
+ </Carousel>
+ </div>
+
+ <div class="project">
+ <div class="project-title"><a href="https://oroshibu.itch.io/bumbling-builders">BUMBLING BUILDERS</a></div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ <img class="grow icon" src="./assets/images/unity.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ <img class="grow icon" src="./assets/images/html5.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ A physics puzzle game in which you need to protect little creatures from danger that could come from
+ any direction. Build forts with tetris-style blocks. The game features 30+ levels, multiple distinct
+ enemies and a star rating system.
+ <br />
+ Game made in 72 hours for <a href="https://ldjam.com/events/ludum-dare/49">Ludum Dare 49</a>, with
+ the theme "Unstable".
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/bumbling-builders/thumbnail.png" />
+ <img src="assets/games/bumbling-builders/screenshot1.png" />
+ <img src="assets/games/bumbling-builders/screenshot2.png" />
+ <img src="assets/games/bumbling-builders/screenshot3.png" />
+ </Carousel>
+ </div>
+
+ <div class="project">
+ <div class="project-title"><a href="https://www.newgrounds.com/portal/view/850576">Dicemask</a>
+ </div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ <img class="grow icon" src="./assets/images/unity.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/html5.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ Adventure through a dungeon of gambling themed enemies!
+ Craft your perfect dice from many powerful spells,
+ combo them to destroy everything in your path, and descend deeper.
+ <br />
+ Game made in under 50 hours for <a href="https://itch.io/jam/gmtk-jam-2022">GMTK Game Jam 2022</a>,
+ with
+ the theme "Roll of the dice".
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/dicemask/thumbnail.png" />
+ </Carousel>
+ </div>
+
+ <div class="project">
+ <div class="project-title"><a href="https://duckonaut.itch.io/wuzmag">WUZMAG</a>
+ </div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ <img class="grow icon" src="./assets/images/unity.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ <img class="grow icon" src="./assets/images/html5.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ Turn based arcade survival game.
+ Survive as long as you can by freezing enemies and using them to defeat more enemies.
+ <br />
+ Game made in roughly 8 hours for a private game jam with friends.
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/wuzmag/thumbnail.png" />
+ <img src="assets/games/wuzmag/screenshot1.png" />
+ <img src="assets/games/wuzmag/screenshot2.png" />
+ <img src="assets/games/wuzmag/screenshot3.png" />
+ </Carousel>
+ </div>
+
+ <div class="project">
+ <div class="project-title"><a href="https://duckonaut.itch.io/miro">Miro</a>
+ </div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ <img class="grow icon" src="./assets/images/monogame.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ Small chill game made mostly as an experiment for a nice 2D renderer mechanic.
+ Infect the world around you, breaking it down into its simplest components.
+ <br />
+ Game made in roughly 8 hours for a private game jam with friends.
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/miro/thumbnail.png" />
+ <img src="assets/games/miro/screenshot1.png" />
+ <img src="assets/games/miro/screenshot2.png" />
+ <img src="assets/games/miro/screenshot3.png" />
+ </Carousel>
+ </div>
+
+ <div class="project">
+ <div class="project-title"><a href="https://duckonaut.itch.io/thermal-trail">Thermal Trail</a></div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ <img class="grow icon" src="./assets/images/godot.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ <img class="grow icon" src="./assets/images/html5.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ Play as Yolka, a mountain goat who found an unknown egg. Keep the egg warm as you navigate the 3
+ distinct worlds, and bring it to the hottest place you know: the depths of a volcano.
+ <br />
+ Game made in a week for <a
+ href="https://www.newgrounds.com/bbs/topic/1476469#bbspost26906541_post_text">Newgrounds July
+ Jam 2021</a>, with the theme "Egg".
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/thermal-trail/gameart.png" />
+ <img src="assets/games/thermal-trail/screenshot1.png" />
+ <img src="assets/games/thermal-trail/screenshot2.png" />
+ <img src="assets/games/thermal-trail/screenshot3.png" />
+ <img src="assets/games/thermal-trail/screenshot4.png" />
+ </Carousel>
+ </div>
+
+ <div class="project">
+ <div class="project-title"><a href="https://duckonaut.itch.io/greachers">Greachers</a></div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ <img class="grow icon" src="./assets/images/monogame.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ Tiny idle simulation game where you manage a team of randomly generated little fellas as they fight
+ other greachers in a sidescrolling world with beautiful procedurally generated graphics.
+ <br />
+ Game made in 2 weeks for <a href="https://itch.io/jam/lowrezjam-2021">LOWREZJAM 2021</a>, with the
+ theme "Minibeasts".
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/greachers/title.png" />
+ <img src="assets/games/greachers/screenshot1.png" />
+ <img src="assets/games/greachers/screenshot2.png" />
+ <img src="assets/games/greachers/screenshot3.png" />
+ </Carousel>
+ </div>
+
+ <div class="project">
+ <div class="project-title"><a href="https://duckonaut.itch.io/third-party">Third Party</a></div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/godot.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ <img class="grow icon" src="./assets/images/html5.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ A top-down stealth game where you play as a spy tasked with stealing important data from a rivaling
+ government. Your task would be easy enough if your objective wasn’t in a underground top-secret
+ facility handling an alien outbreak. Without access to conventional stealth techniques, use corpses
+ of your enemies to sneak through the battlefield.
+ <br />
+ Game made in 72 hours for <a href="https://ldjam.com/events/ludum-dare/48/">Ludum Dare 48</a>, with
+ the theme "Deeper and deeper".
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/third-party/thumbnail.png" />
+ <img src="assets/games/third-party/screenshot1.jpg" />
+ <img src="assets/games/third-party/screenshot2.jpg" />
+ <img src="assets/games/third-party/screenshot3.jpg" />
+ <img src="assets/games/third-party/screenshot4.jpg" />
+ </Carousel>
+ </div>
+ <div class="project">
+ <div class="project-title"><a href="https://xatriv.itch.io/your-left">Your Left</a></div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ <img class="grow icon" src="./assets/images/unity.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ A simple pacman-inspired arcade game. Try to grab all the stars in a randomly generated maze before
+ the time expires, while your controls are scattered all over the screen. Get as far as you can to
+ get the highest score.
+ <br />
+ Game made in 8 hours for <a href="https://itch.io/jam/jamjam-bhl-kntg-polygon">Jam Jam</a>, a local
+ in-person event organized by <a href="https://www.kntgpolygon.pl/">KNTG Polygon</a>, with
+ the theme "One Click".
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/your-left/thumbnail.png" />
+ <img src="assets/games/your-left/screenshot1.jpg" />
+ <img src="assets/games/your-left/screenshot2.jpg" />
+ <img src="assets/games/your-left/screenshot3.jpg" />
+ </Carousel>
+ </div>
+ <div class="project">
+ <div class="project-title"><a href="https://duckonaut.itch.io/riff-n-rage">Riff n' Rage</a></div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ <img class="grow icon" src="./assets/images/monogame.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ You just got your first guitar, and through sheer luck managed to land in the king's throne room,
+ trying to entertain him. Sadly, his subjects aren't huge fans of your music. Dodge them while trying
+ to play the best you can, or the king won't be merciful.
+ <br />
+ Game made in 48 hours for a special solo game jam among friends. My theme was "Power at a price".
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/riff-n-rage/thumbnail.png" />
+ <img src="assets/games/riff-n-rage/screenshot1.png" />
+ <img src="assets/games/riff-n-rage/screenshot2.png" />
+ </Carousel>
+ </div>
+ <div class="project">
+ <div class="project-title"><a href="https://duckonaut.itch.io/survive-the-temple">Survive the Temple</a>
+ </div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/godot.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ <img class="grow icon" src="./assets/images/html5.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ A quick movement focused platformer that tests your short term memory. Survive the trap system of an
+ ancient temple! Dash through the lanterns in the correct order before the time runs out, or face
+ certain death!
+ <br />
+ Game made in 48 hours for <a href="https://ldjam.com/events/ludum-dare/47">Ludum Dare Compo 47</a>
+ with the theme "Stuck in a loop".
+ </div>
+ </div>
+ <Carousel>
+ <img src="assets/games/survive-the-temple/cover.png" />
+ <img src="assets/games/survive-the-temple/screenshot.png" />
+ </Carousel>
+ </div>
+ </div>
+ </>
+ );
+}
+
diff --git a/front/src/pages/home.tsx b/front/src/pages/home.tsx
new file mode 100644
index 0000000..9b29803
--- /dev/null
+++ b/front/src/pages/home.tsx
@@ -0,0 +1,29 @@
+export default function Home() {
+ return (
+ <>
+ <div class="main-info">
+ <div class="main-info-title">
+ Stanisław Zagórowski
+ </div>
+ <div class="main-info-subtitle">
+ aka Duckonaut, EchoDuck
+ </div>
+ <img src="assets/images/duckpfp.png" class="main-info-image logo grow" />
+ </div>
+
+ <div class="about-paragraph">
+ <p>
+ Hello! I'm a programmer, game designer, and artist. I'm currently a student at the Warsaw University of
+ Technology, studying Computer Science. A list of the games I've worked on is in the <a class="games-link"
+ href="#/games">games</a> section. Other projects I've been a part of are available in the <a class="projects-link"
+ href="#/projects">projects</a> section.
+ I also enjoy some lower-level programming and learning about the inner workings of various systems. The main
+ technologies I use are <span class="highlight">C#</span>, <span class="highlight">Unity</span>
+ , <span class="highlight">Python</span>, <span class="highlight">Rust</span> and <span class="highlight">C</span>,
+ although I'm also familiar with <span class="highlight">Godot</span>, <span class="highlight">C++</span>
+ , <span class="highlight">Java</span> and some <span class="highlight">JavaScript</span> and <span class="highlight">TypeScript</span>.
+ </p>
+ </div>
+ </>
+ );
+}
diff --git a/front/src/pages/projects.css b/front/src/pages/projects.css
new file mode 100644
index 0000000..f9cc07f
--- /dev/null
+++ b/front/src/pages/projects.css
@@ -0,0 +1,137 @@
+.icon {
+ display: inline;
+ width: 32px;
+ height: 32px;
+ transition: 0.3s;
+ transform-origin: center;
+ filter: brightness(70%)
+}
+
+.icon:hover {
+ filter: brightness(80%);
+}
+
+.icon-row {
+ width: 240px;
+ height: 36px;
+}
+
+.icon-container {
+ height: 36px;
+ float: right;
+}
+
+.icon-text {
+ width: auto;
+ height: 36px;
+ line-height: 36px;
+ float: left;
+ vertical-align: middle;
+ margin-right: 8px;
+ color: #5c6370;
+}
+
+.projects-container {
+ width: 100%;
+ max-width: 1120px;
+ margin: auto;
+ margin-top: 24pt;
+ margin-bottom: 48pt;
+ align-items: center;
+ justify-content: center;
+ align-self: center;
+}
+
+.project {
+ display: table;
+ align-self: center;
+ clear: both;
+ margin-bottom: 24pt;
+}
+
+.project-info {
+ font-size: 14pt;
+}
+
+.project-description {
+ font-size: 16pt;
+ text-align: justify;
+}
+
+.project-image-gallery {
+ margin-left: 24px;
+ margin-right: 10px;
+}
+
+@media (max-width: 1150px) {
+ .project-title {
+ text-align: center;
+ font-size: 24pt;
+ margin-bottom: 8px;
+ text-decoration-line: underline;
+ }
+
+ .project-image-gallery {
+ margin: 60px auto;
+ width: 330px;
+ height: 220px;
+ }
+
+ .project-info {
+ float: none;
+ width: 90%;
+ margin: auto;
+ }
+
+ .project-description {
+ font-size: 14pt;
+ }
+}
+
+@media (max-width: 1150px) and (min-width: 480px) {
+ .project-title {
+ text-align: center;
+ font-size: 24pt;
+ margin-bottom: 8px;
+ text-decoration-line: underline;
+ }
+ .project-image-gallery {
+ margin: 60px auto;
+ width: 480px;
+ height: 360px;
+ }
+
+ .project-info {
+ float: none;
+ width: 90%;
+ margin: auto;
+ }
+
+ .project-description {
+ font-size: 14pt;
+ }
+}
+
+@media (min-width: 1150px) {
+ .project-title {
+ text-align: left;
+ font-size: 32pt;
+ margin-bottom: 8px;
+ text-decoration-line: underline;
+ }
+ .project-image-gallery {
+ float: right;
+ width: 480px;
+ height: 360px;
+ }
+ .project-info {
+ float: left;
+ max-width: 600px;
+ }
+
+ .project-description {
+ font-size: 16pt;
+ }
+}
+
+
diff --git a/front/src/pages/projects.tsx b/front/src/pages/projects.tsx
new file mode 100644
index 0000000..4e64704
--- /dev/null
+++ b/front/src/pages/projects.tsx
@@ -0,0 +1,50 @@
+import './projects.css';
+import Carousel from '../components/carousel';
+
+export default function Projects() {
+ return (
+ <>
+ <div class="main-info">
+ <div class="main-info-title">
+ Other Projects
+ </div>
+ <div class="main-info-subtitle">
+ projects that are not games
+ </div>
+ </div>
+
+ <div class="projects-container">
+
+ <div class="project">
+ <div class="project-title"><a href="https://spiritmod.fandom.com/wiki/Spirit_Mod_Wiki">Spirit Mod</a></div>
+ <div class="project-info">
+ <div class="icon-row">
+ <div class="icon-text">Made using</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/csharp.png" />
+ </div>
+ </div>
+ <div class="icon-row">
+ <div class="icon-text">Available on</div>
+ <div class="icon-container">
+ <img class="grow icon" src="./assets/images/windows.png" />
+ </div>
+ </div>
+ <hr />
+ <div class="project-description">
+ The Spirit Mod is one of the largest mods for Terraria: with more than 1300 items, 8 bosses, and
+ hundreds of enemies, as well as 3 new events and 3 brand new biomes, the mod has a lot to offer.
+ <br />
+ I had the privilege of contributing some system code, mainly the "Stargoop" system.
+ </div>
+ </div>
+ <Carousel>
+ <img class="project-image-gallery-item" src="assets/projects/spirit-mod/Thumbnail.png" />
+ <img class="project-image-gallery-item" src="assets/projects/spirit-mod/Demo1.gif" />
+ <img class="project-image-gallery-item" src="assets/projects/spirit-mod/Demo2.gif" />
+ </Carousel>
+ </div>
+ </div>
+ </>
+ );
+}
diff --git a/front/src/vite-env.d.ts b/front/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/front/src/vite-env.d.ts
@@ -0,0 +1 @@
+/// <reference types="vite/client" />