homepage iniT
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
#### Freelance
|
||||
|
||||
_08/2021 - present_ ~ **Lead/staff software engineer, freelance**
|
||||
|
||||
I currenly work as a freelance software engineer, in either lead or staff positions. A dedicated page for which can be found [here](/freelance/).
|
||||
|
||||
#### Companion Group Ltd.
|
||||
|
||||
_11/2025 - present_ ~ **Staff engineer for [AA, MMO]**
|
||||
|
||||
_Details will be added in due time._
|
||||
|
||||
_09/2025 - 11/2025_ ~ **Gameplay engineer for Storm Lancers (ProbablyMonsters)**
|
||||
|
||||
Worked on Xbox+DualSense controller input support for PC port of the game, both for EGS (custom logic with RawInput) and Steam (Steam Input API). Additionally contributed to Steamdeck support.
|
||||
|
||||
_05/2025 - 09/2025_ ~ **Senior game backend/SRE engineer for Project Ghost (Fantastic Pixel Castle)**
|
||||
|
||||
- Implementation of back-end functionality (C++)
|
||||
- Containerization of game server and services (Docker, C++, UE5)
|
||||
- Migrating infrastructure to infrastructure-as-code (Terraform, AWS)
|
||||
- Remote log persistence setup for game server and services (C++, UE5)
|
||||
- Contributions to custom build system and local development workflow
|
||||
- Development of various internal tools and APIs
|
||||
|
||||
_01/2025 - 05/2025_ ~ **AI bot engineer, Unreal Engine for [AA]**
|
||||
|
||||
Implementation of AI bots based on behavior trees, with support for game abilities (GAS) by bots. I added support for combat with various weapons and implemented bot spawning based on level settings with support for loadouts. Various game logic was modified to be compatible with bots.
|
||||
|
||||
_10/2024 - present_ ~ **Lead developer, maintainer for [capsa.gg](https://capsa.gg) (open-source)**
|
||||
|
||||
[Capsa](https://capsa.gg) is a non-intrusive open-source logging solution for Unreal Engine. For Capsa, I created the API server and web panel from scratch and contributed to the Unreal Engine plugin. Additionally, I created the documentation website and a video playlist for demo and integration guide.
|
||||
|
||||
_04/2024 - 12/2024_ ~ **Gears of War: E-Day (The Coalition/Microsoft)**
|
||||
|
||||
Supporting Online and Platform Services. _Details will be added in due time._
|
||||
|
||||
_08/2023 - 03/2024_ ~ **Senior game backend engineer for [AAA, Amazon Games, unannounced]**
|
||||
|
||||
- Containerization of game servers and integration with CI/CD (Docker, GitLab)
|
||||
- Development of custom game server orchestration solution (C# .NET 6, SAM, DynamoDB)
|
||||
- Integration of game server orchestration into game server code (C++/Unreal Engine)
|
||||
- Prototype of real-time back-end service to game server communication (MQTT, C++, Unreal Engine)
|
||||
- Integration of Amazon GameLift into custom Online Subsystem (AWS, C++/Unreal Engine)
|
||||
- Development of API server between players and GameLift (Golang, JWT, JWK, Kubernetes, Helm)
|
||||
- Game server infrastructure and deployment automation (Terraform, AWS, GitLab, Scripting)
|
||||
|
||||
_08/2023 - 04/2024_ ~ **Development lead (part-time) for prototype of Project Dual**
|
||||
|
||||
- Initial set-up of prototype in Unreal Engine 5.2
|
||||
- Development of proof-of-concept of TeamManager subystem (C++/Unreal Engine)
|
||||
- Creation of various game elements and levels (Unreal Engine Blueprints)
|
||||
- Involved with technical oversight and support, advice for production version of game
|
||||
|
||||
_01/2023 - 08/2023_ ~ **Online game client engineer for VAIL VR (AEXLAB)**
|
||||
|
||||
- Migrating to Armada game server orchestration; client, server and CI/CD side implementation
|
||||
- Implementation of various SDKs into game client and server code (C++/Unreal Engine)
|
||||
- Guiding adoption and implementation of AccelByte services into the game (C++/Unreal Engine)
|
||||
- Zero-downtime migration of PlayFab to AccelByte for authentication and entitlements (Golang)
|
||||
- Implemented game server player progression: stats tracking/uploads, MMR, rewards (C++)
|
||||
- Development lead for server browser, matchmaking, player progression and marketplace
|
||||
|
||||
#### CoolGames B.V.
|
||||
|
||||
_05/2022 - 10/2022_ ~ **Software and data engineer**
|
||||
|
||||
Migration of millions of player accounts across multiple games to a new backend system, with near-zero downtime. Built custom data export/import pipelines between Gamesparks and Nakama, with high performance. In addition, I made several DevOps/SRE improvements and supporting tools.
|
||||
|
||||
#### Bytecode Digital Agency B.V.
|
||||
|
||||
_05/2018 - 03/2022_ ~ **Co-founder and techlead**
|
||||
|
||||
Together with a business partner, I founded Bytecode Digital Agency. Our office was located in Delfgauw. Our team specialized in custom application development, mostly for software start-ups targeting web and mobile.
|
||||
|
||||
As technical lead, my activities were mostly focused on building the network layers between different applications, as well as hands-on development on back-end applications. Additionally, I worked on internal software, cyber security and cloud infrastructure. In August 2021, I announced my exit from Bytecode.
|
||||
|
||||
#### VNG Realisering, Team NLX
|
||||
|
||||
_08/2021 - 12/2021_ ~ **Senior software engineer**
|
||||
|
||||
I worked on the NLX project, an open-source software project that allows data sharing between organisations in a safe, secure and privacy-proof way. This included work on the back-end (Go), front-end (React) and SRE (Kuebernetes, Helm), improvements in development and build setup to improve development experience and speed. I have introduced Typescript into the React codebase and build systems and provided React and Typescript training to back-end developers. Part of my contributions are public [on GitLab](https://gitlab.com/commonground/nlx/nlx/-/commits/master?search=Luciano).
|
||||
|
||||
#### Airchip B.V.
|
||||
|
||||
_02/2021 - 11/2021_ ~ **CTO, ad interim**
|
||||
|
||||
Airchip was a startup that aimed to revolutionize digital ordering of drinks at festivals, even without internet connection. At Airchip, I fulfilled the role of CTO on an ad-interim basis (via Bytecode). My responsibilities included hands-on development of the back-end application (Go) and taking care of the site reliability engineering. I also had an advisory role for the three native mobile applications (Kotlin, Swift) and the BLE-protocol.
|
||||
|
||||
#### Dearly B.V.
|
||||
|
||||
_06/2020 - 11/2021_ ~ **Partner and techlead, ad interim**
|
||||
|
||||
Dearly is an initiative to help people with deal with grief and making grief more accessible to talk about, both in private and business setting. Similarly to Yourpwr, I was responsible for the technical side of the Dearly platform and advisor.
|
||||
|
||||
#### Youngpwr B.V.
|
||||
|
||||
_02/2020 - 08/2021_ ~ **Partner and techlead, ad interim**
|
||||
|
||||
Youngpwr is an initiative to support the development of entrepreneurial skills in young people. I was responsible for the technical side of the Youngpwr platform, which included software-architecture, infrastructure, systems integration, data engineering, security and code quality. Part of the management team (board member) and technical advisor.
|
||||
|
||||
#### Eneco / Dept Agency
|
||||
|
||||
_05/2019 - 03/2020_ ~ **Software engineer, ad interim**
|
||||
|
||||
Leading frontend developer for De Omschakelaar project at Eneco, an innovative tool that played a crucial role in the customer journey and promoted in several big marketing campaigns. I created several code generation tools and tackled technical debt. The technology stack used is mainly based on Typescript/Javascript and ReactJS.
|
||||
|
||||
#### Stager Software
|
||||
|
||||
_12/2017 - 05/2018_ ~ **Full-stack software engineer**
|
||||
|
||||
During my time working at Stager, I worked as a full-stack (with focus on the front-end) developer on the main Stager ticketing application. Technologies I used here were mostly ReactJS and Play! Framework (Java).
|
||||
|
||||
#### Nooijen Web Solutions
|
||||
|
||||
_05/2015 - 05/2018_ ~ **Owner, founder and developer**
|
||||
|
||||
Nooijen Solutions is a web designing/develop business that aims to creates beautiful websites and web apps. I worked here as one of the main developers (Wordpress, html, css, php, js, server-work) and I also do all of the administrative work.
|
||||
|
||||
#### Chemiewinkel
|
||||
|
||||
_07/2014 - 12/2018_ ~ **Owner and founder**
|
||||
|
||||
In the summer vacation of 2014, I started Chemiewinkel. The reason why I started a webshop in lab supplies as a 15-year-old, was because I was (and still am!) fascinated by chemistry, and supplies for hobby chemists were very hard to come by. I built and managed the webshop.
|
||||
|
||||
## Volunteer experience
|
||||
|
||||
#### Bookclub Philosophy
|
||||
|
||||
_06-2021 - present_ ~ **Reading group leader, moderator**
|
||||
|
||||
Leading the reading groups on Stoicism, Aristotle and general book discussion group.
|
||||
|
||||
Other resonsibilities include Discord server administration, development and maintenance of the [custom-made bot](https://github.com/lucianonooijen/socrates-discord-bot), helping out new members and automating tasks.
|
||||
|
||||
#### Gaga Animal Care
|
||||
|
||||
_04/2017 - present_ ~ **Board member, webmaster**
|
||||
|
||||
Volunteer for the dog shelter in Greece. Involved with planning and executing multiple neutering programs each year.
|
||||
Other responsibilities include website creation and maintenance.
|
||||
|
||||
#### Pijnackerse Watervienden
|
||||
|
||||
_2013 - 2015_ ~ **Swimming tutor assistant**
|
||||
|
||||
Leading and assisting swimming lessons for young children.
|
||||
|
||||
#### Atlas Animal Project
|
||||
|
||||
_10/2013 - 12/2015_ ~ **Volunteer**
|
||||
|
||||
Occasionally assisting Atlas representatives, usually at Schiphol airport with dogs that arrived or collecting dog crates and returning them to Kos via cargo.
|
||||
|
||||
#### Animal Rescue Kos
|
||||
|
||||
_03/2013_ ~ **Documentary director**
|
||||
|
||||
Assisting volunteers living on Kos and filming the activities. After filming I edited, released and promoted the documentary.
|
||||
|
||||
<!--Finished documentary: bit.ly/arkfilm or bit.ly/arkfilmgermany-->
|
||||
@@ -0,0 +1,101 @@
|
||||
<style>
|
||||
.gametitles-fallback { display: none }
|
||||
.gametitles {
|
||||
display: block;
|
||||
width: min(160rem, 90vw);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
.gametitles-fallback { display: block }
|
||||
.gametitles { display: none }
|
||||
}
|
||||
</style>
|
||||
|
||||
<p class="gametitles-fallback"><i>Mobile not supported</i></p>
|
||||
|
||||
<table class="gametitles">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Game</th>
|
||||
<th>Genre</th>
|
||||
<th>Studio/Publisher</th>
|
||||
<th>Technology</th>
|
||||
<th>Position/work</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>AA</td>
|
||||
<td><i>NDA</i></td>
|
||||
<td>MMO</td>
|
||||
<td><i>NDA</i></td>
|
||||
<td>Go, React, UE5</td>
|
||||
<td>Staff engineer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AA</td>
|
||||
<td>Storm Lancers</td>
|
||||
<td>Roguelite</td>
|
||||
<td>Probably Monsters</td>
|
||||
<td>C++, UE5</td>
|
||||
<td>Gameplay engineer (controller input)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AAA</td>
|
||||
<td>Project Ghost</td>
|
||||
<td>MMORPG</td>
|
||||
<td>Fantastic Pixel Castle</td>
|
||||
<td>C++, Modified UE5</td>
|
||||
<td>Senior backend/SRE engineer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AA</td>
|
||||
<td><i>NDA</i></td>
|
||||
<td>Survival/PvP</td>
|
||||
<td><i>NDA</i></td>
|
||||
<td>UE5, C++ </td>
|
||||
<td>Game client AI bot engineer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AAA</td>
|
||||
<td>Gears of War: E-Day</td>
|
||||
<td>Shooter</td>
|
||||
<td>The Coalition</td>
|
||||
<td><i>NDA</i></td>
|
||||
<td>Online and Platform Services (tech lead)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Indie</td>
|
||||
<td>Project Dual</td>
|
||||
<td>Platformer</td>
|
||||
<td>Companion Group</td>
|
||||
<td>UE5, C++</td>
|
||||
<td>Lead developer prototype</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AAA</td>
|
||||
<td><i>Unannounced</i></td>
|
||||
<td>PvP/PvE</td>
|
||||
<td>Amazon Games</td>
|
||||
<td>UE5, C++, .NET</td>
|
||||
<td>Game backend engineer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AA</td>
|
||||
<td>VAIL VR</td>
|
||||
<td>VR FPS</td>
|
||||
<td>AEXLAB, Meta</td>
|
||||
<td>UE4/5, C++</td>
|
||||
<td>Online Client Engineer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AA</td>
|
||||
<td>Several</td>
|
||||
<td>Casual</td>
|
||||
<td>Coolgames</td>
|
||||
<td>Nakama/HTML5</td>
|
||||
<td>Data migration engineer</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -0,0 +1,41 @@
|
||||
## Technologies used
|
||||
|
||||
The technologies I'm currently working with the most and am most familiar with are in **bold**.
|
||||
|
||||
### Game development
|
||||
|
||||
- Client: **Unreal Engine 5** (C++, Blueprints), C, C++
|
||||
- Backend: **C++** (Unreal Engine, custom), **C#** (.NET), **Go**
|
||||
|
||||
### Backend/server development
|
||||
|
||||
- **Golang** (Gin, Echo, Stdlib)
|
||||
- Typescript (NodeJS, Deno, Bun)
|
||||
- C# (.NET)
|
||||
- Elixir (Phoenix, OTP)
|
||||
|
||||
_Most often with **PostgreSQL** as the underlying database._
|
||||
|
||||
### Front-end and mobile development
|
||||
|
||||
- **React with Typescript** (NextJS)
|
||||
- Web Assembly (Golang, Zig, Odin, Jai, C/C++)
|
||||
- React Native (Expo or bare)
|
||||
- Progressive Web Apps
|
||||
- Elm
|
||||
|
||||
### Site Reliability Engineering and DevOps
|
||||
|
||||
- **Linux** (Ubuntu, Debian, Arch, CentOS)
|
||||
- **CI/CD** (GitLab, GitHub Actions, Azure DevOps, Jenkins)
|
||||
- Cloud (DigitalOcean, AWS, Azure, GCP)
|
||||
- Docker and Kubernetes (Compose, Helm)
|
||||
- Infrastructure and provisioning (Ansible, Terraform, Shell)
|
||||
- Systems integration
|
||||
- Nginx
|
||||
|
||||
### Domain specific
|
||||
|
||||
- **Compilers, parsers, DSLs**: Golang, C, C++
|
||||
- Systems programming: C, C++, Zig, Odin, Jai
|
||||
- Data science: SQL, Python, Javascript/Typescript
|
||||
@@ -0,0 +1,15 @@
|
||||
## Working method
|
||||
|
||||
_Methods I employ to deliver elegant, efficient, readable, understandable and maintainable code that adds value to a company and/or product._
|
||||
|
||||
- "Always choose the best tool for the job"
|
||||
- Cloud and application structure using [The Twelve-Factor App](https://12factor.net/)
|
||||
- Software architecture via a simplified version of the principles of [The Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html), [DDD](https://en.wikipedia.org/wiki/Domain-driven_design) and [Layered Architecture](https://en.wikipedia.org/wiki/Multitier_architecture).
|
||||
- Prevention of [technical debt](https://en.wikipedia.org/wiki/Technical_debt), short term and long term
|
||||
- Everything (even [infrastructure as code](https://en.wikipedia.org/wiki/Infrastructure_as_code)) in version control (Git/Perforce)
|
||||
- Project management via SCRUM/Agile principle, without unnecessary meetings
|
||||
- Bringing together Development, Security and Operations through [DevSecOps](https://www.devsecops.org/) and [secure by design](https://en.wikipedia.org/wiki/Secure_by_design).
|
||||
- Test-Driven Development (TDD) of domain logic where it makes sense
|
||||
- Versioning according to [Semantic Versioning](https://semver.org/)
|
||||
- Adhere to the [ACM Code of Ethics](https://www.acm.org/code-of-ethics)
|
||||
- Use of free (open-source) software where possible, contributing when possible
|
||||
Vendored
+351
@@ -0,0 +1,351 @@
|
||||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the `main` element consistently in IE.
|
||||
*/
|
||||
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input {
|
||||
/* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
/* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
@mixin max-xs() {
|
||||
@media screen and (max-width: 400px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin max-sm() {
|
||||
@media screen and (max-width: 600px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin max-md() {
|
||||
@media screen and (max-width: 800px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin max-lg() {
|
||||
@media screen and (max-width: 1000px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin max-xl() {
|
||||
@media screen and (max-width: 1200px) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Colours
|
||||
//
|
||||
$color-bg: #efebe0;
|
||||
|
||||
$color-text: #2e2b26;
|
||||
$color-heading: #2e2b26;
|
||||
|
||||
$color-link: #8b4513;
|
||||
$color-link-active: #cd4416;
|
||||
|
||||
$color-code-text: #223244;
|
||||
$color-code-bg: #dadada;
|
||||
|
||||
$color-quote: #666;
|
||||
|
||||
//
|
||||
// Widths
|
||||
//
|
||||
$container-max-width: 120rem;
|
||||
$blogpost-width: 80rem;
|
||||
@@ -0,0 +1,84 @@
|
||||
@use "_vars.scss";
|
||||
@use "_responsive.scss";
|
||||
|
||||
*,
|
||||
*:after,
|
||||
*:before {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
font-size: 62.5%; // Set base to 10px
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
color: vars.$color-text;
|
||||
background-color: vars.$color-bg;
|
||||
|
||||
font-family: "Noto Sans Mono", monospace;
|
||||
font-size: 1.8em;
|
||||
font-weight: 400;
|
||||
|
||||
letter-spacing: 0.032em;
|
||||
line-height: 1.8em;
|
||||
|
||||
@include responsive.max-md() {
|
||||
font-size: 1.4em;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: vars.$container-max-width;
|
||||
width: 100%;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
margin-top: 1.6rem;
|
||||
margin-bottom: 2.4rem;
|
||||
}
|
||||
|
||||
.centered {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
//
|
||||
// Print
|
||||
//
|
||||
@media print {
|
||||
@page {
|
||||
size: auto;
|
||||
margin: 0;
|
||||
}
|
||||
nav,
|
||||
footer {
|
||||
display: none !important;
|
||||
}
|
||||
html {
|
||||
font-size: 36%;
|
||||
padding: 32px;
|
||||
}
|
||||
.content {
|
||||
margin-top: -24px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
@use "_vars.scss";
|
||||
@use "_responsive.scss";
|
||||
|
||||
.list {
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 4rem 0;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: row-reverse;
|
||||
padding: 0.4rem 0;
|
||||
border-bottom: 1px solid #bbb;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 20rem;
|
||||
margin-left: 3rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: vars.$color-text;
|
||||
line-height: 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
@include responsive.max-md() {
|
||||
li {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
border-bottom: none;
|
||||
padding: 0.6rem 0;
|
||||
|
||||
span {
|
||||
margin-left: 0;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
@use "_vars.scss";
|
||||
@use "_responsive.scss";
|
||||
|
||||
.block-experience {
|
||||
h4 {
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 2.4rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
@use "_vars.scss";
|
||||
@use "_responsive.scss";
|
||||
|
||||
//
|
||||
// Menu base
|
||||
//
|
||||
|
||||
.topnav {
|
||||
height: 60px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.topnav-title {
|
||||
color: vars.$color-text;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
.topnav-list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
}
|
||||
.topnav-link {
|
||||
color: vars.$color-text;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Mobile menu
|
||||
//
|
||||
|
||||
.mobilemenu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@include responsive.max-md() {
|
||||
.mobilemenu {
|
||||
display: initial;
|
||||
color: vars.$color-text;
|
||||
}
|
||||
.topnav-list {
|
||||
display: none;
|
||||
gap: 0;
|
||||
}
|
||||
.topnav-list.navopen {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
right: 20px;
|
||||
padding-left: 0 !important;
|
||||
|
||||
height: auto;
|
||||
text-align: right;
|
||||
background-color: #ddd;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.topnav-item {
|
||||
display: inline-block;
|
||||
border-top: solid 1px #999;
|
||||
min-width: 200px;
|
||||
padding: 12px 24px;
|
||||
}
|
||||
.topnav-item:first-of-type {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
@use "_vars.scss";
|
||||
@use "_responsive.scss";
|
||||
|
||||
article.blogpost {
|
||||
max-width: vars.$blogpost-width;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased !important;
|
||||
-moz-font-smoothing: antialiased !important;
|
||||
text-rendering: optimizelegibility !important;
|
||||
}
|
||||
|
||||
.post-content {
|
||||
margin-top: 64px;
|
||||
|
||||
img {
|
||||
width: 80%;
|
||||
margin-left: 10%;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@include responsive.max-md() {
|
||||
.post-content {
|
||||
margin-top: 36px;
|
||||
}
|
||||
.highlight {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.endofpost {
|
||||
max-width: 400px;
|
||||
margin: 3em auto 3.4em;
|
||||
display: block;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-top: 1px solid #888;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
a[href^="#fn:"]:before {
|
||||
content: "[";
|
||||
}
|
||||
a[href^="#fn:"]:after {
|
||||
content: "]";
|
||||
}
|
||||
|
||||
.footnotes hr {
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-top: 1px solid #888;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
@use "_vars.scss";
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
td,
|
||||
th {
|
||||
text-align: left;
|
||||
border: 1px solid vars.$color-quote;
|
||||
padding: 0.8rem 1rem;
|
||||
font-size: 1.6rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
tr {
|
||||
&:first-child th {
|
||||
border-top: 0;
|
||||
}
|
||||
&:last-child td {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
td:first-child,
|
||||
th:first-child {
|
||||
border-left: 0;
|
||||
}
|
||||
td:last-child,
|
||||
th:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
@use "sass:color";
|
||||
|
||||
@use "_vars.scss";
|
||||
@use "_responsive.scss";
|
||||
|
||||
//
|
||||
// Headings
|
||||
//
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: vars.$color-heading;
|
||||
font-weight: 600;
|
||||
margin: 3.2rem 0 1.4rem 0;
|
||||
letter-spacing: 0.024em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.4em;
|
||||
font-weight: 700;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.6em;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
h5 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
@include responsive.max-md() {
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.6em;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
h5 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Body text
|
||||
//
|
||||
|
||||
a {
|
||||
font-weight: 600;
|
||||
color: vars.$color-link;
|
||||
text-decoration: none;
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: vars.$color-link-active;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1.8rem 0;
|
||||
text-shadow: 0.5px 0.5px 0px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
blockquote:not(.alert) {
|
||||
border-left: 2px solid vars.$color-quote;
|
||||
padding-left: 1.6rem;
|
||||
font-style: italic;
|
||||
|
||||
p {
|
||||
color: vars.$color-quote;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ALERT BLOCKQUOTES
|
||||
//
|
||||
|
||||
blockquote.alert {
|
||||
padding: 0;
|
||||
border: 2px solid vars.$color-quote;
|
||||
background: vars.$color-code-bg;
|
||||
border-radius: 1.4rem;
|
||||
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.05);
|
||||
|
||||
margin: 1rem -3.2rem;
|
||||
|
||||
.alert-heading {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 0;
|
||||
background-color: vars.$color-quote;
|
||||
border-radius: 1.2rem 1.2rem 0 0;
|
||||
}
|
||||
|
||||
.alert-heading-emoji {
|
||||
margin: 0.4rem 0;
|
||||
width: 3.2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.alert-heading-text {
|
||||
margin: 0.4rem 0;
|
||||
}
|
||||
|
||||
> p {
|
||||
padding: 1.6rem 3.2rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@include responsive.max-md {
|
||||
margin: 1rem -1.6rem;
|
||||
.alert-heading-emoji {
|
||||
width: 2.8rem;
|
||||
}
|
||||
> p {
|
||||
padding: 1.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$alert-accents: (
|
||||
tip: #388e3c,
|
||||
note: #1976d2,
|
||||
info: #244c91,
|
||||
warning: #ffb700,
|
||||
caution: #ff7b00,
|
||||
danger: #d32f2f,
|
||||
);
|
||||
@each $name, $accent in $alert-accents {
|
||||
blockquote.alert-#{$name} {
|
||||
border: 2px solid color.mix(white, $accent, 70%);
|
||||
background: color.mix(white, $accent, 90%);
|
||||
|
||||
.alert-heading {
|
||||
background: color.mix(white, $accent, 70%);
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Code
|
||||
//
|
||||
|
||||
pre {
|
||||
padding: 2.4rem 2rem;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
margin: 2.4rem -2rem;
|
||||
|
||||
@include responsive.max-md() {
|
||||
margin: 2.4rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
color: vars.$color-code-text;
|
||||
background-color: vars.$color-code-bg;
|
||||
font-family: "Anonymous Pro", monospace;
|
||||
font-weight: 500;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
line-height: 1.6;
|
||||
|
||||
code {
|
||||
color: unset;
|
||||
background-color: unset;
|
||||
padding: 0;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Start new code
|
||||
@use "normalize.scss";
|
||||
|
||||
@use "src/_vars.scss"; // Variables
|
||||
@use "src/base.scss"; // Base styles, including layout etc.
|
||||
@use "src/typography.scss"; // Typography setup
|
||||
|
||||
@use "src/navigation.scss"; // Navbar styling
|
||||
@use "src/table.scss"; // Tables styling
|
||||
@use "src/list.scss"; // Styles for list page
|
||||
@use "src/post.scss"; // Blogpost specific code
|
||||
|
||||
@use "src/misc.scss"; // Misc styling for specific blocks etc
|
||||
// End new code
|
||||
Reference in New Issue
Block a user