45 Commits

Author SHA1 Message Date
4e367d73a0 order projects
Some checks failed
test / cargo test (push) Failing after 57s
2024-09-27 13:34:07 +02:00
85c98fac56 showcase page
Some checks failed
test / cargo test (push) Failing after 1m12s
2024-09-27 11:52:25 +02:00
f62673d6a7 yutube and instagram
Some checks failed
test / cargo test (push) Failing after 59s
2024-09-26 14:59:18 +02:00
221d5cef23 twitch and tiktok hover effects
Some checks failed
test / cargo test (push) Failing after 1m5s
2024-09-26 14:12:55 +02:00
dc1a01c352 yes yes yes
Some checks failed
test / cargo test (push) Failing after 1m6s
2024-09-26 12:19:45 +02:00
20d1314925 lol hide instagram between lg-xl
Some checks failed
test / cargo test (push) Failing after 1m12s
2024-09-25 16:21:35 +02:00
1eb0f55264 holy shit the responsiveness
Some checks failed
test / cargo test (push) Failing after 1m24s
2024-09-25 12:55:05 +02:00
fc26d77bfc few style 2024-09-25 11:05:19 +02:00
2949429fa4 calendly link
Some checks failed
test / cargo test (push) Failing after 58s
2024-09-20 16:31:00 +02:00
52bd4e5590 Contact page favicon
Some checks failed
test / cargo test (push) Failing after 1m3s
2024-09-20 12:35:30 +02:00
377aee315e mooooar moooar pretty fixes
Some checks failed
test / cargo test (push) Failing after 1m4s
2024-09-20 11:51:29 +02:00
f3c4df4458 strong bold medium and heading tag handling 2024-09-20 10:44:59 +02:00
6650366e60 better theme colors
Some checks failed
test / cargo test (push) Failing after 1m3s
2024-09-19 12:06:35 +02:00
0937de96dd coloooors 2024-09-18 18:36:54 +02:00
fb63a2011b fuckit 2024-09-18 16:30:16 +02:00
b9d42012ca trythis
Some checks failed
release / release (push) Failing after 5m55s
test / cargo test (push) Failing after 1m5s
2024-09-18 16:24:00 +02:00
21e04ccf73 just try this
Some checks failed
test / cargo test (push) Failing after 1m3s
release / release (push) Failing after 25s
2024-09-18 16:20:33 +02:00
1d23732812 try this
Some checks failed
release / release (push) Failing after 4m45s
test / cargo test (push) Failing after 1m9s
2024-09-18 16:04:07 +02:00
ea888a84ba fix code
Some checks failed
release / release (push) Has been cancelled
test / cargo test (push) Has been cancelled
2024-09-18 15:59:20 +02:00
b547bd9974 once again
Some checks failed
release / release (push) Failing after 3m36s
test / cargo test (push) Has been cancelled
2024-09-18 15:54:41 +02:00
eec2ceecf4 lets go
Some checks failed
release / release (push) Failing after 4m43s
test / cargo test (push) Failing after 1m4s
2024-09-18 15:41:34 +02:00
ca4e9674d4 lets see what te just prod says
Some checks failed
release / release (push) Has been cancelled
test / cargo test (push) Has been cancelled
2024-09-18 15:37:02 +02:00
9667ee54c4 wait on 3
Some checks failed
test / cargo test (push) Failing after 2m19s
release / release (push) Failing after 4m43s
2024-09-18 15:20:24 +02:00
a904450b71 more nice things
Some checks failed
release / release (push) Successful in 4m13s
test / cargo test (push) Failing after 2m20s
2024-09-18 15:10:59 +02:00
88fc3f47bf log
Some checks failed
release / release (push) Successful in 1m52s
test / cargo test (push) Failing after 2m15s
2024-09-18 13:54:29 +02:00
5a99eb40e7 what is wrong
Some checks failed
release / release (push) Failing after 3m59s
test / cargo test (push) Failing after 2m16s
2024-09-18 13:47:40 +02:00
3be70703e8 no background action
Some checks failed
test / cargo test (push) Waiting to run
release / release (push) Has been cancelled
2024-09-18 13:38:08 +02:00
92b38a1087 pls
Some checks failed
test / cargo test (push) Waiting to run
release / release (push) Has been cancelled
2024-09-18 13:28:24 +02:00
35dcde6953 different wait
Some checks failed
release / release (push) Failing after 23s
test / cargo test (push) Failing after 2m21s
2024-09-18 13:25:17 +02:00
1b24d45cd5 see logs
Some checks failed
release / release (push) Failing after 3m56s
test / cargo test (push) Failing after 2m13s
2024-09-18 13:17:18 +02:00
2e9e88b052 try thiiis
Some checks failed
release / release (push) Failing after 2m38s
test / cargo test (push) Failing after 2m19s
2024-09-18 13:10:06 +02:00
9b078c4a21 try this
Some checks failed
release / release (push) Failing after 23s
test / cargo test (push) Failing after 2m15s
2024-09-18 13:06:22 +02:00
7d454f502f more fixes
Some checks failed
test / cargo test (push) Failing after 2m48s
release / release (push) Failing after 22s
2024-09-18 12:56:49 +02:00
5134a6411e fix action
Some checks failed
release / release (push) Failing after 1m42s
test / cargo test (push) Failing after 2m19s
2024-09-18 12:52:26 +02:00
46394f362c run deploy action
Some checks failed
release / release (push) Failing after 0s
test / cargo test (push) Has been cancelled
2024-09-18 12:50:28 +02:00
fbb70fa6f2 deploy script
Some checks failed
test / cargo test (push) Failing after 2m26s
2024-09-18 12:47:25 +02:00
18bcd0a45e disable release workflow
Some checks failed
test / cargo test (push) Failing after 2m19s
2024-09-17 22:09:06 +02:00
49fff88702 amend release workflow
Some checks failed
test / cargo test (push) Waiting to run
release / release (push) Has been cancelled
2024-09-17 21:59:33 +02:00
9a1fab6eae differnt just
Some checks failed
release / release (push) Has been cancelled
test / cargo test (push) Failing after 2m18s
2024-09-17 21:48:34 +02:00
8baa9811d3 release workflow
Some checks failed
release / release (push) Failing after 1m32s
test / cargo test (push) Failing after 2m21s
2024-09-17 21:38:04 +02:00
bf83631e26 remove cargo ldd linking
Some checks failed
test / cargo test (push) Failing after 2m6s
2024-09-17 21:14:33 +02:00
568423d0dd not link with cc
Some checks failed
test / cargo test (push) Failing after 2m18s
2024-09-17 21:02:05 +02:00
72dcab0cd0 change test directory
Some checks failed
test / cargo test (push) Failing after 1m33s
2024-09-17 20:59:59 +02:00
01c4188293 please
Some checks failed
test / cargo test (push) Failing after 48s
2024-09-17 20:40:13 +02:00
43ca7d4c56 test workflow
Some checks failed
test / cargo test (push) Failing after 1m16s
2024-09-17 19:27:08 +02:00
77 changed files with 1436 additions and 584 deletions

View File

@ -0,0 +1,56 @@
name: release
# on:
# push:
# branches:
# main
on: workflow_dispatch
env:
PORT: 3081
jobs:
release:
name: release
runs-on: ubuntu-latest
container:
image: node:18
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: cache
uses: Swatinem/rust-cache@v2
working-directory: axum_server
- uses: taiki-e/install-action@just
# - uses: JarvusInnovations/background-action@v1
# with:
# run: just prod &
# working-directory: axum_server
# wait-on: http://localhost:3081
# wait-for: 10m
# tail: true
- name: Build release
run: cargo build --release
working-directory: axum_server
- name: Run server in background
run: just prod &
working-directory: axum_server
- uses: cygnetdigital/wait_for_response@v2.0.0
with:
url: 'http://127.0.0.1:3081/'
responseCode: '200,500'
timeout: 50000
interval: 2000
- name: run ssg
run: just ssg
working-directory: axum_server
- name: Server log
run: cat axum_server/server.log
- uses: actions/upload-artifact@v4
with:
name: dist
path: axum_server/dist/
retention-days: 10

View File

@ -0,0 +1,12 @@
name: test
on: [push, pull_request]
jobs:
test:
name: cargo test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cd axum_server && cargo test --all-features

View File

@ -17,7 +17,9 @@ tags:
Creating my own website with blog was something I had in my mind from start of my professional career after I left school.
I had a lot of new experience with development which I wanted to elaborate on and save into a small library so I can take a look back on my thoughts how they evolve over time.
This was like 6 years ago. I had a successful first attempt at doing so. I created a WordPress with the simplest theme I've found and wrote some articles. I've published it under a domain of one of the first startups I've been part of. I still have a backup of the _Wordpress_ database somewhere so I can export those articles here when I will feel like doing so. The blog haven't lived for long as the domain once expired and I was not satisfied with it enough to deploy it somewhere else.
This was like 6 years ago. I had a successful first attempt at doing so.
I created a WordPress with the simplest theme I've found and wrote some articles. I've published it under a domain of one of the first startups I've been part of. I still have a backup of the _Wordpress_ database somewhere so I can export those articles here when I will feel like doing so. The blog haven't lived for long as the domain once expired and I was not satisfied with it enough to deploy it somewhere else.
For all those years I was trying to create it in my spare time (of which wasn't that much apparently). There were several attempts. One with _Angular_ when it was "the cool kid on the block". Another one with _cycle.js_ which was not that far from being done. I regret it now as it would be really satisfying to finish that one. I had created neat <abbr title="Server side rendering">SSR</abbr> layer which was not really difficult to accomplish with _cycle.js_ as it is reactive and it only required skipping first client render of _virtual-dom_ after page load. I'm still in love with _cycle.js_ but after _sapper_ was released I've found out of its ability to create a nice **static site** I wanted to try it out. I think that the approach of **compiling the source code** as classic client applications have been doing for many years makes a lot of sense on the internet as well. This is the one thing I'd really like to be able to accomplish with reactive frameworks like _cycle.js_.
@ -115,7 +117,7 @@ For example this is the model of this blog post:
Neat part of the _CMS_ are those widgets. In editor they will be presented by appropriate component as well as in the editor preview.
I am very satisfied with it and I recommend it.
## What's next
## What's next {#whats-next}
I've decided not to wait for perfect product and I want to release this blog as soon as possible. I will have same approach as with other products. Make a <abbr title="Minimum Viable Product">**MVP**</abbr> and then release features as they are done.
I've put some features into _Github Projects Board_. I will very likely make a redesign with experimental layout changes. I'd like to experiment with colors and make the blog look distinguishable and personal while maintaining accessibility.

View File

@ -38,7 +38,9 @@ I've set a new **sub goal** for buying a streaming PC. I'll buy it when the stre
Last week I've been showing off new headphones that I've ordered and the *YouTube* algorithm has been suggesting great videos on the topic since. I will give another shoutout. This time it is to [Joshua's Valour *YouTube* channel](https://www.youtube.com/channel/UCx9bOYEjkevIDYONBAstK-A)
<iframe width="560" height="315" src="https://www.youtube.com/embed/hoLMdrD5pic" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<div class="video-embed">
<iframe class="embed" width="100%" height="100%" src="https://www.youtube.com/embed/hoLMdrD5pic" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
My next pick will be a [podcast *Lifespan* hosted by Dr. David Sinclair](https://open.spotify.com/show/3PkkSdQE8DfeiKvSk1Mg1J) where he talks about what we can do and how should we treat our bodies to live a longer and healthier life.

View File

@ -28,7 +28,7 @@ This week I've attended a [Rusty game jam #2](https://itch.io/jam/rusty-jam-2).
![Egg fetcher game preview](/images/uploads/screenshot-from-2022-06-26-22-37-16.png "Egg fetcher game preview")
[You can check the rusult built with WASM here.](/showcase/egg-fetcher/)
[You can check the result built with WASM here.](/showcase/egg-fetcher/)
## What's up with the weeklys

View File

@ -1,11 +1,12 @@
---
title: CK Vive
displayed: true
description: Websitefor *CK Vive* travel agency with a **custom CMS system** for
managing travel destinations.
cover_image: /images/uploads/ck_vive_logo.svg
link: https://ckvive.sk/
classification: website
tags:
- PHP
featured: false
---
Websitefor *CK Vive* travel agency with a **custom CMS system** for
managing travel destinations.

View File

@ -1,8 +1,6 @@
---
title: Košice Peace Marathon
displayed: true
description: "*Košice Peace Marathon* is the oldest marathon in Europe and the
third-oldest in the world."
link: https://www.kosicemarathon.com/
cover_image: /images/uploads/screenshot-from-2024-08-06-18-22-52.png
classification: website
@ -11,3 +9,5 @@ tags:
- MySQL
featured: false
---
*Košice Peace Marathon* is the oldest marathon in Europe and the
third-oldest in the world.

View File

@ -1,8 +1,6 @@
---
title: Docker
displayed: false
description: An introduction to Docker containerization technology and how it
differs from virtualization.
cover_image: /images/uploads/docker-use-cases.png
classification: presentation
tags:
@ -10,3 +8,5 @@ tags:
- Docker
featured: false
---
An introduction to Docker containerization technology and how it
differs from virtualization.

View File

@ -0,0 +1,13 @@
---
title: Unstoppable growth of front-end frameworks
displayed: true
link: https://michalvankodev.github.io/unstoppable-growth-of-frontend-frameworks/
classification: presentation
tags:
- Presentation
- NodeJS
featured: false
---
A simple summary of the web front-end evolution. Describes how and
why new tools in the NodeJS ecosystem improve & why there is still something
to explore.

View File

@ -0,0 +1,10 @@
---
title: Skosy
displayed: false
classification: webapp
tags:
- Webapp
featured: false
---
*Skosy* is a web application whose purpose is to **automate the
writing of integration tests** for websites.

View File

@ -0,0 +1,13 @@
---
title: beinSports
displayed: true
link: https://www.beinsports.com/en-us
cover_image: /images/uploads/bein_logo.af017869.webp
classification: website
tags:
- Freemarker
featured: false
---
*beIN Sports* is a global network of sports channels jointly owned
and operated by *Qatari Sports Investments*, an affiliate of *Al Jazeera Media
Networks*

View File

@ -0,0 +1,10 @@
---
title: Livesport.tv
displayed: false
classification: website
tags:
- Freemarker
featured: false
---
*Livesport.tv* is a network of premium online sports channels,
featuring all the top sports competitions from around the world.

View File

@ -0,0 +1,14 @@
---
title: Spreading the Web
displayed: true
link: https://michalvankodev.github.io/spreading-the-web
cover_image: /images/uploads/screenshot-from-2024-08-06-18-48-02.png
classification: presentation
tags:
- Presentation
- NodeJS
featured: false
---
A presentation about the rising number of use cases for utilizing
web technologies outside of the web platform such as native mobile
applications and robotics. 2015

View File

@ -0,0 +1,15 @@
---
title: FX Sales
displayed: true
link: https://www.caplin.com/business/fx-sales
cover_image: /images/uploads/fx_sales_screen2x.png
classification: webapp
tags:
- Webapp
- React
- Knockout
featured: false
---
*Caplin FX Sales* allows sales people to **trade on behalf of
their clients**. This needs to be an efficient workflow providing all the
relevant information to the sales user

View File

@ -1,11 +1,11 @@
---
title: SHIP (Structured heard input process)
displayed: true
description: "*SHIP* is a web application for **editors** who actively **track
trades offers and bids** on the commodity market."
classification: webapp
tags:
- Webapp
- Angular
featured: false
---
*SHIP* is a web application for **editors** who actively **track
trades offers and bids** on the commodity market.

View File

@ -0,0 +1,15 @@
---
title: responzIO
displayed: true
link: https://www.croptech.com/
cover_image: /images/uploads/responzio.png
classification: embedded
tags:
- Webapp
- Embedded
- NodeJS
featured: false
---
***responzIO*** is a smart, easy-to-use monitoring and automation
system. The ultimate tool for various applications such as hydroponics,
aquariums, and gardens.

View File

@ -0,0 +1,14 @@
---
title: Manualogic
displayed: false
classification: webapp
tags:
- Webapp
- Angular
- RxJS
featured: false
---
*Manualogic* is a **single-page application** for product manual
creators. It contains **custom web editor** and management system of
**translatable pages, books** and **products.** Its main goal is to enable
customers to get manuals of their products in digital form.

View File

@ -0,0 +1,13 @@
---
title: Signal Hub Manager
displayed: true
classification: webapp
tags:
- Webapp
- React
featured: false
---
*Signal Hub* is an end-to-end **Big Data analytics platform** for
large enterprises. It accelerates the process of extracting insights and
intelligence from large volumes of data, including data of different types and
in different formats.

View File

@ -1,9 +1,6 @@
---
title: Panoramic
displayed: true
description: "*Panoramic* was a company focused on building a web application
for data scientists to be able to create and share models and graphs in
between each other."
classification: webapp
tags:
- Webapp
@ -14,3 +11,6 @@ tags:
- Data analytics
featured: false
---
*Panoramic* was a company focused on building a web application
for data scientists to be able to create and share models and graphs in
between each other.

View File

@ -1,11 +1,6 @@
---
title: The Expert
displayed: true
description: _The Expert_ is a digital platform that connects clients to
interior designers around the world. For experts, it allows **managing** their
**portfolio and profile** and **schedule** in which they are open for
**consultations**. Clients are able to view their profiles and book
consultations.
link: https://www.theexpert.com/
cover_image: /images/uploads/the-expert-logo.svg
classification: webapp
@ -17,3 +12,8 @@ tags:
- GraphQL
featured: true
---
_The Expert_ is a digital platform that connects clients to
interior designers around the world. For experts, it allows **managing** their
**portfolio and profile** and **schedule** in which they are open for
**consultations**. Clients are able to view their profiles and book
consultations.

View File

@ -1,8 +1,7 @@
---
title: WebAssembly presentation
displayed: true
description: A presentation about what WebAssembly is about and how it might
affect the future of the world.
link: https://michalvankodev.github.io/presentation-webassembly/
cover_image: /images/uploads/screenshot-from-2024-08-06-18-52-41.png
classification: presentation
tags:
@ -10,3 +9,5 @@ tags:
- WebAssembly
featured: false
---
A presentation about what WebAssembly is about and how it might
affect the future of the world.

View File

@ -0,0 +1,14 @@
---
title: The Grand Escape
displayed: true
link: https://michalvankodev.itch.io/the-grand-escape
cover_image: /images/uploads/logo.png
classification: videogame
tags:
- Rust
- Bevy
featured: true
---
A videogame where you need to steer your boat to avoid obstacles
and enemy bullets. The difficulty will be increased after a certain time and
new enemies will be spawned to make your escape harder.

View File

@ -1,8 +1,6 @@
---
title: Renaissance of hypermedia systems
displayed: true
description: A presentation about hypermedia systems, HTMX, HyperView, and the
HATEOAS principles. 2024
link: https://michalvankodev.github.io/presentation-renaissance-of-hypermedia-systems/#/intro
cover_image: /images/uploads/screenshot-from-2024-08-06-19-01-03.png
classification: presentation
@ -12,3 +10,5 @@ tags:
- HTMX
featured: true
---
A presentation about hypermedia systems, HTMX, HyperView, and the
HATEOAS principles. 2024

View File

@ -1,12 +0,0 @@
---
title: beinSports
displayed: true
description: "*beIN Sports* is a global network of sports channels jointly owned
and operated by *Qatari Sports Investments*, an affiliate of *Al Jazeera Media
Networks*"
cover_image: /images/uploads/bein_logo.af017869.webp
classification: website
tags:
- Freemarker
featured: false
---

View File

@ -1,9 +1,9 @@
---
title: dev project test
displayed: true
description: Testing project
displayed: false
classification: webapp
tags:
- Webapp
featured: false
---
Testing project

View File

@ -1,14 +0,0 @@
---
title: FX Sales
displayed: true
description: "*Caplin FX Sales* allows sales people to **trade on behalf of
their clients**. This needs to be an efficient workflow providing all the
relevant information to the sales user"
cover_image: /images/uploads/fx_sales_screen2x.png
classification: webapp
tags:
- Webapp
- React
- Knockout
featured: false
---

View File

@ -1,8 +1,7 @@
---
title: HeyLady!
displayed: true
description: A thriving online community supporting women to learn and practise
speaking English.
link: https://www.heylady.io/
cover_image: /images/uploads/heyladylogo.svg
classification: webapp
tags:
@ -14,3 +13,5 @@ tags:
- PostgreSQL
featured: false
---
A thriving online community supporting women to learn and practise
speaking English.

View File

@ -1,10 +0,0 @@
---
title: Livesport.tv
displayed: false
description: "*Livesport.tv* is a network of premium online sports channels,
featuring all the top sports competitions from around the world."
classification: website
tags:
- Freemarker
featured: false
---

View File

@ -1,14 +0,0 @@
---
title: Manualogic
displayed: false
description: "*Manualogic* is a **single-page application** for product manual
creators. It contains **custom web editor** and management system of
**translatable pages, books** and **products.** Its main goal is to enable
customers to get manuals of their products in digital form."
classification: webapp
tags:
- Webapp
- Angular
- RxJS
featured: false
---

View File

@ -1,14 +0,0 @@
---
title: responzIO
displayed: true
description: "***responzIO*** is a smart, easy-to-use monitoring and automation
system. The ultimate tool for various applications such as hydroponics,
aquariums, and gardens."
cover_image: /images/uploads/responzio.png
classification: embedded
tags:
- Webapp
- Embedded
- NodeJS
featured: false
---

View File

@ -1,13 +0,0 @@
---
title: Signal Hub Manager
displayed: true
description: "*Signal Hub* is an end-to-end **Big Data analytics platform** for
large enterprises. It accelerates the process of extracting insights and
intelligence from large volumes of data, including data of different types and
in different formats."
classification: webapp
tags:
- Webapp
- React
featured: false
---

View File

@ -1,10 +0,0 @@
---
title: Skosy
displayed: false
description: "*Skosy* is a web application whose purpose is to **automate the
writing of integration tests** for websites."
classification: webapp
tags:
- Webapp
featured: false
---

View File

@ -1,13 +0,0 @@
---
title: Spreading the Web
displayed: true
description: A presentation about the rising number of use cases for utilizing
web technologies outside of the web platform such as native mobile
applications and robotics. 2015
cover_image: /images/uploads/screenshot-from-2024-08-06-18-48-02.png
classification: presentation
tags:
- Presentation
- NodeJS
featured: false
---

View File

@ -1,14 +0,0 @@
---
title: The Grand Escape
displayed: true
description: A videogame where you need to steer your boat to avoid obstacles
and enemy bullets. The difficulty will be increased after a certain time and
new enemies will be spawned to make your escape harder.
link: https://michalvankodev.itch.io/the-grand-escape
cover_image: /images/uploads/logo.png
classification: videogame
tags:
- Rust
- Bevy
featured: true
---

View File

@ -1,12 +0,0 @@
---
title: Unstoppable growth of front-end frameworks
displayed: true
description: A simple summary of the web front-end evolution. Describes how and
why new tools in the NodeJS ecosystem improve & why there is still something
to explore.
classification: presentation
tags:
- Presentation
- NodeJS
featured: false
---

View File

@ -1,2 +0,0 @@
[build]
rustflags = ["-Clink-arg=-fuse-ld=lld", "-Ctarget-cpu=native"]

View File

@ -24,18 +24,18 @@ image = "0.25.2"
anyhow = "1.0.86"
rayon = "1.10.0"
syntect = "5.2.0"
indoc = "2.0.5"
[build]
rustflags = ["-Z", "threads=8"]
[target.x86_64-unknown-linux-gnu]
rustflags = [
"-C", "link-arg=-fuse-ld=lld"
]
# [target.x86_64-unknown-linux-gnu]
# rustflags = [
# "-C", "link-arg=-fuse-ld=lld"
# ]
[profile.dev]
debug = false
debug = true
opt-level = 0
# codegen-units = 16
# lto = "thin"

View File

@ -46,7 +46,7 @@ wait_for_port:
# Kill the application running on port
kill:
kill $(lsof -t -i:{{port}})
kill $(pidof axum_server)
# Clean the dist folder
clean:
@ -67,3 +67,6 @@ export: clean
just wait_for_port
just ssg
just kill
deploy:
rsync -avz -e ssh ./dist/ michalvanko@katelyn:.config/containers/systemd/michalvankodev-site/dist/

View File

@ -0,0 +1,17 @@
(missing) static/images/uploads/20220212_120400.jpg (39d71161bfa42ccf425efe4c3505fe1f208401e7e7d6de1372585c3706f5bf92)
(missing) static/images/uploads/20220422_214530.jpg (3b965dd36c86cb60275d738b2ce36f6f513b37da860a40b8f27a76bc0e2c7f2b)
(missing) static/images/uploads/2020-03-23_20-24-15_387.jpg (62700bb93b007c76366bffc02f6596aedc23ab9536b377e063593f5e758ebc7e)
(missing) static/images/m-logo.png (a1d7e8031e1f09c024830822233b4f852ce3293ca4cf6ca1cb9c606bfd57cc7f)
(missing) static/images/uploads/img_7631.jpg (5f3d9c43d98184f01ca958c9d7a4c9a1d128a3536d715ea29b63f3acdb9f5098)
(missing) static/eye.png (6b639bd6eb9df5dbaa73508c9afb8fa78959ebc06edb2c8ee8130000a7d4eb89)
(missing) static/images/uploads/2020-03-23_20-24-18-981.jpg (c16bd70dfca5b8c44e1a0d9c9a4574b495ac037d8683fae3a744290a5cac33db)
(missing) static/images/uploads/img_20200301_171735.jpg (beeae37c0f079d89dcfe514738166a44025538542b5c68b4c4c8a188ead8f986)
(missing) static/images/uploads/2020-03-23_20-24-13_625.jpg (31fc6afbb95e85cef4de53f98a44d98362f7e8e52725071372d35df4830c90bb)
(missing) static/m-favicon-192x192.png (02c48e4e9a67e68a3c9458a90adf7b21a915991057d33fc606eda14abb9c4dc8)
(missing) static/images/uploads/img_7709.jpg (f36abe313b43ce98cacb04b8a05dc4d3ca44c81c18ff3c7bf42b0434427d8129)
(missing) static/images/uploads/screenshot.gif (b6d76282012e22b320b9ee999b59ef0dfacf376f4f8f91a0fc100a7008d7d2cc)
(missing) static/images/uploads/2020-03-23_20-24-06_393.jpg (270c974391f02bf081038e1064ebc6b7ffaba5cfc4660af08d807b73d7bc880d)
(missing) static/images/uploads/2020-03-23_20-24-08_235.jpg (17669b583dff420e3a8871b8e94b8ddf1f46c3a2b327063e64a66dd3f16ea464)
(missing) static/images/uploads/img_7108.jpg (1a81e61af8c48f16d774f93e77182eeec282ab5de5473f4e895035972a111190)
(missing) static/images/uploads/img_7116.jpg (53159f319a0f006239a6fb2e21534838f9ae311fed6d6fa9664ef77c1588b2fc)

View File

@ -1,6 +1,7 @@
use axum::{self};
use tower_http::services::ServeDir;
use tower_livereload::LiveReloadLayer;
use tracing::info;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
mod blog_posts;
@ -34,6 +35,7 @@ async fn main() {
.nest_service("/fonts", ServeDir::new("../static/fonts"))
.nest_service("/generated_images", ServeDir::new("generated_images"))
.nest_service("/svg", ServeDir::new("../static/svg"))
// TODO manifest logos have bad link, #directory-swap
.nest_service(
"/config.yml",
ServeDir::new("../static/resources/config.yml"),
@ -45,18 +47,18 @@ async fn main() {
// run our app with hyper, listening globally on port 3080
let port = std::option_env!("PORT").unwrap_or("3080");
let addr = format!("0.0.0.0:{}", port);
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
info!("axum_server listening on http://{}", &addr);
axum::serve(listener, app).await.unwrap();
}
// TODO Socials
// TODO ul li article styles
// TODO header height difference
// - fotos
// TODO Colors
// TODO print css and other 404 css linked in base.html
// TODO go live pipeline
// background gradient color
// TODO Change DNS system
// THINK deploy to alula? rather then katelyn? can be change whenever
// TODO after release
// - contact
// OG tags
// Remove old web completely
// Restructure repository
// - projects page
// - linktree page

View File

@ -64,7 +64,7 @@ pub async fn render_blog_post_list(
};
Ok(PostListTemplate {
title: "Posts".to_owned(),
title: "Blog posts".to_owned(),
posts,
tag,
header_props,

View File

@ -3,3 +3,4 @@ pub mod blog_post_list;
pub mod blog_post_page;
pub mod contact;
pub mod index;
pub mod project_list;

View File

@ -0,0 +1,30 @@
use askama::Template;
use axum::http::StatusCode;
use crate::{
components::site_header::HeaderProps,
post_utils::{post_listing::get_post_list, post_parser::ParseResult},
projects::project_model::ProjectMetadata,
};
#[derive(Template)]
#[template(path = "project_list.html")]
pub struct ProjectListTemplate {
pub title: String,
pub project_list: Vec<ParseResult<ProjectMetadata>>,
pub header_props: HeaderProps,
}
pub async fn render_projects_list() -> Result<ProjectListTemplate, StatusCode> {
let mut project_list = get_post_list::<ProjectMetadata>("../_projects").await?;
project_list.sort_by_key(|post| post.slug.to_string());
project_list.retain(|project| project.metadata.displayed);
project_list.reverse();
Ok(ProjectListTemplate {
title: "Showcase".to_owned(),
header_props: HeaderProps::default(),
project_list,
})
}

View File

@ -5,6 +5,7 @@ use std::{
use anyhow::Context;
use image::{image_dimensions, ImageReader};
use indoc::formatdoc;
use super::{
export_format::ExportFormat, image_generator::generate_images,
@ -18,16 +19,34 @@ pub fn generate_picture_markup(
width: u32,
height: u32,
alt_text: &str,
class_name: Option<&str>,
generate_image: bool,
) -> Result<String, anyhow::Error> {
let exported_formats = get_export_formats(orig_img_path);
let class_attr = if let Some(class) = class_name {
format!(r#"class="{class}""#)
} else {
"".to_string()
};
if exported_formats.is_empty() {
return Ok(formatdoc!(
r#"<img
src="{orig_img_path}"
width="{width}"
height="{height}"
{class_attr}
alt="{alt_text}"
>"#
));
}
let path_to_generated = get_generated_file_name(orig_img_path);
// TODO This should get removed when we move the project structure #move
let dev_only_img_path =
// TODO This should get removed when we move the project structure #directory-swap
let disk_img_path =
Path::new("../static/").join(orig_img_path.strip_prefix("/").unwrap_or(orig_img_path));
let orig_img_dimensions = image_dimensions(&dev_only_img_path)?;
let orig_img_dimensions = image_dimensions(&disk_img_path)?;
let resolutions = get_resolutions(orig_img_dimensions, width, height);
let path_to_generated_arc = Arc::new(path_to_generated);
@ -39,8 +58,8 @@ pub fn generate_picture_markup(
if generate_image {
rayon::spawn(move || {
let orig_img = ImageReader::open(&dev_only_img_path)
.with_context(|| format!("Failed to read instrs from {:?}", &dev_only_img_path))
let orig_img = ImageReader::open(&disk_img_path)
.with_context(|| format!("Failed to read instrs from {:?}", &disk_img_path))
.unwrap()
.decode()
.unwrap();
@ -66,7 +85,7 @@ pub fn generate_picture_markup(
.map(|format| {
let srcset = generate_srcset(&path_to_generated, format, &resolutions);
let format_type = format.get_type();
format!(
formatdoc!(
r#"<source
srcset="{srcset}"
type="{format_type}"
@ -81,16 +100,17 @@ pub fn generate_picture_markup(
resolutions.first().expect("Should this error ever happen?"),
exported_formats.last().expect("Can this one ever happen?"),
);
let image_tag = format!(
let image_tag = formatdoc!(
r#"<img
src="{image_path}"
width="{width}"
height="{height}"
alt="{alt_text}"
{class_attr}
>"#
);
let result = format!(
let result = formatdoc!(
r#"<picture>
{source_tags}
{image_tag}
@ -272,10 +292,12 @@ fn test_generate_srcset() {
#[test]
fn test_generate_picture_markup() {
use indoc::indoc;
let width = 300;
let height = 200;
let orig_img_path = "/images/uploads/2020-03-23_20-24-06_393.jpg";
let result = r#"<picture>
let result = indoc! {
r#"<picture>
<source
srcset="/generated_images/images/uploads/2020-03-23_20-24-06_393_300x200.avif 1x, /generated_images/images/uploads/2020-03-23_20-24-06_393_450x300.avif 1.5x, /generated_images/images/uploads/2020-03-23_20-24-06_393_600x400.avif 2x, /generated_images/images/uploads/2020-03-23_20-24-06_393_900x600.avif 3x, /generated_images/images/uploads/2020-03-23_20-24-06_393_1200x800.avif 4x"
type="image/avif"
@ -290,10 +312,18 @@ fn test_generate_picture_markup() {
height="200"
alt="Testing image alt"
>
</picture>"#;
</picture>"#,
};
assert_eq!(
generate_picture_markup(orig_img_path, width, height, "Testing image alt", false)
.expect("picture markup has to be generated"),
generate_picture_markup(
orig_img_path,
width,
height,
"Testing image alt",
None,
false
)
.expect("picture markup has to be generated"),
result
);
}

View File

@ -1,14 +1,16 @@
use core::panic;
use std::path::Path;
use axum::http::StatusCode;
use chrono::{DateTime, Utc};
use gray_matter::{engine::YAML, Matter};
use image::image_dimensions;
use indoc::formatdoc;
use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag, TagEnd};
use serde::{de::DeserializeOwned, Deserialize, Deserializer};
use syntect::{highlighting::ThemeSet, html::highlighted_html_for_string, parsing::SyntaxSet};
use tokio::fs;
use tracing::debug;
use tracing::{debug, error, info};
use crate::picture_generator::{
picture_markup_generator::generate_picture_markup, resolutions::get_max_resolution,
@ -71,6 +73,7 @@ pub async fn parse_post<'de, Metadata: DeserializeOwned>(
enum TextKind {
Text,
Heading(Option<String>),
Code(String),
}
@ -87,6 +90,7 @@ pub fn parse_html(markdown: &str, generate_images: bool) -> String {
let syntax_set = SyntaxSet::load_defaults_newlines();
let theme_set = ThemeSet::load_defaults();
let theme = theme_set.themes.get("InspiredGitHub").unwrap();
let mut heading_ended: Option<bool> = None;
let parser = Parser::new_ext(markdown, options).map(|event| match event {
/*
@ -102,7 +106,7 @@ pub fn parse_html(markdown: &str, generate_images: bool) -> String {
}) => {
if !dest_url.starts_with("/") {
return Event::Html(
format!(
formatdoc!(
r#"<img
alt="{title}"
src="{dest_url}"
@ -123,23 +127,29 @@ pub fn parse_html(markdown: &str, generate_images: bool) -> String {
);
// Place image into the content with scaled reso to a boundary
let picture_markup =
generate_picture_markup(&dest_url, max_width, max_height, &title, generate_images)
.unwrap_or(format!(
r#"
let picture_markup = generate_picture_markup(
&dest_url,
max_width,
max_height,
&title,
None,
generate_images,
)
.unwrap_or(formatdoc!(
r#"
<img
alt="{alt}"
src="{src}"
/>"#,
alt = title,
src = dest_url,
));
alt = title,
src = dest_url,
));
debug!(
"Image link_type: {:?} url: {} title: {} id: {}",
link_type, dest_url, title, id
);
Event::Html(
format!(
formatdoc!(
r#"<figure>
{picture_markup}
<figcaption>
@ -168,14 +178,55 @@ pub fn parse_html(markdown: &str, generate_images: bool) -> String {
.unwrap();
Event::Html(highlighted.into())
}
TextKind::Heading(provided_id) => {
let heading_id = provided_id.clone().unwrap_or({
text.to_lowercase()
.replace(|c: char| !c.is_alphanumeric(), "-")
});
debug!("heading_id: {}", heading_id.clone());
match heading_ended {
None => {
error!("Heading should have set state");
panic!("Heading should have set state");
}
Some(true) => Event::Html(text),
Some(false) => {
heading_ended = Some(true);
Event::Html(
formatdoc!(
r##"id="{heading_id}">
{text}"##
)
.into(),
)
}
}
}
_ => Event::Text(text),
},
Event::Start(Tag::Heading {
level,
id,
classes: _,
attrs: _,
}) => {
let id_str = id.map(|id| id.to_string());
debug!("heading_start: {:?}, level: {}", &id_str, level);
text_kind = TextKind::Heading(id_str);
heading_ended = Some(false);
Event::Html(format!("<{level} ").into())
}
Event::Start(_) => event,
Event::End(TagEnd::Image) => Event::Html("</figcaption></figure>".into()),
Event::End(TagEnd::CodeBlock) => {
text_kind = TextKind::Text;
Event::End(TagEnd::CodeBlock)
}
Event::End(TagEnd::Heading(heading_level)) => {
text_kind = TextKind::Text;
heading_ended = None;
Event::End(TagEnd::Heading(heading_level))
}
_ => event,
});

View File

@ -1,9 +1,6 @@
use axum::http::StatusCode;
use crate::post_utils::{
post_listing::get_post_list,
post_parser::{parse_html, ParseResult},
};
use crate::post_utils::{post_listing::get_post_list, post_parser::ParseResult};
use super::project_model::ProjectMetadata;
@ -13,10 +10,6 @@ pub async fn get_featured_projects() -> Result<Vec<ParseResult<ProjectMetadata>>
let featured_projects = project_list
.into_iter()
.filter(|post| post.metadata.featured)
.map(|mut post| {
post.metadata.description = parse_html(&post.metadata.description, false);
post
})
.collect();
Ok(featured_projects)

View File

@ -3,7 +3,6 @@ use serde::Deserialize;
#[derive(Deserialize, Debug)]
pub struct ProjectMetadata {
pub title: String,
pub description: String,
pub classification: String,
pub displayed: bool,
pub cover_image: Option<String>,
@ -18,6 +17,7 @@ pub fn translate_classification(classification: &str) -> &str {
"website" => "Web site",
"presentation" => "Presentation",
"videogame" => "Video game",
"embedded" => "Embedded system",
any => any,
}
}

View File

@ -3,6 +3,7 @@ use crate::{
pages::{
admin::render_admin, blog_post_list::render_blog_post_list,
blog_post_page::render_blog_post, contact::render_contact, index::render_index,
project_list::render_projects_list,
},
};
use axum::{extract::MatchedPath, http::Request, routing::get, Router};
@ -16,6 +17,7 @@ pub fn get_router() -> Router {
.route("/blog/tags/:tag", get(render_blog_post_list))
.route("/blog/:post_id", get(render_blog_post))
.route("/contact", get(render_contact))
.route("/showcase", get(render_projects_list))
.route("/admin", get(render_admin))
.route("/feed.xml", get(render_rss_feed))
.layer(

View File

@ -69,11 +69,11 @@
}
a {
@apply text-pink-600 underline underline-offset-2;
@apply text-pink-800 underline underline-offset-2 hover:transition hover:text-blue-500;
}
&:hover {
@apply transition text-blue-400;
}
strong {
@apply font-medium;
}
.article-body {
@ -83,15 +83,23 @@ a {
h2 {
@apply px-4 text-xl font-semibold text-blue-900 mb-3 mt-4 max-w-read mx-auto md:text-2xl md:mb-6 md:mt-8 lg:mb-8 lg:mt-12 lg:text-4xl;
}
h3 {
@apply px-4 text-lg font-semibold text-blue-900 mb-3 mt-4 max-w-read mx-auto md:text-xl md:mb-6 md:mt-8 lg:mb-8 lg:mt-12 lg:text-3xl;
}
h4 {
@apply px-4 text-lg font-medium text-blue-900 mb-2 mt-3 max-w-read mx-auto md:text-lg md:mb-6 md:mt-8 lg:mb-8 lg:mt-12 lg:text-3xl;
}
p {
@apply px-4 my-2 text-slate-950 text-justify mx-auto max-w-read md:text-lg md:my-8 lg:text-readxl;
}
strong {
@apply font-medium;
}
pre {
@apply p-4 my-1 overflow-auto text-sm mx-auto max-w-read;
}
figure {
@apply p-4;
@ -104,7 +112,7 @@ a {
}
table {
@apply text-sm mx-auto my-4 max-w-image table-auto border-collapse border-spacing-12 border border-gray-200 rounded md:text-base lg:text-xl lg:my-8;
@apply text-sm mx-auto my-4 max-w-image table-auto border-collapse border-spacing-12 border border-slate-200 rounded md:text-base lg:text-xl lg:my-8;
}
thead {
@ -125,7 +133,7 @@ a {
}
blockquote {
@apply mx-6 py-1 px-2 bg-pink-50 lg:mx-auto max-w-note border-l-4 border-pink-500;
@apply mx-6 py-1 px-2 bg-pink-50 lg:mx-auto max-w-note border-l-4 border-pink-600;
p {
@apply my-2 md:my-4 text-slate-600 max-w-note;
@ -133,14 +141,150 @@ a {
}
:not(pre) code {
@apply text-pink-950 rounded border border-blue-300 px-1 py-0.5 bg-blue-100 text-sm md:text-base lg:text-xl;
@apply text-pink-900 rounded border border-blue-300 px-1 py-0.5 bg-blue-100 text-sm md:text-base lg:text-xl;
}
pre code pre {
@apply mx-2 rounded lg:mx-auto lg:text-lg shadow-sm lg:max-w-note;
}
ul,
ol {
@apply pl-10 pr-6 my-2 text-slate-950 mx-auto max-w-read md:text-lg md:my-8 lg:text-readxl lg:pl-14;
& p {
@apply px-2;
}
}
ul {
@apply list-disc;
}
ol {
@apply list-decimal;
}
iframe {
@apply rounded shadow-md mx-auto lg:max-w-image;
}
}
article a {
@apply visited:text-purple-700;
}
.video-embed {
@apply m-4 mx-auto max-w-image aspect-video;
}
.social-card-twitch:hover {
transform: translate3d(0.6rem, -0.6rem, 0px);
box-shadow: -3px 3px 0px 3px #6441a5;
transition-delay: 75ms;
}
.social-card-youtube:hover {
@apply rounded-none;
transform: scale(1.02);
transition-delay: 100ms;
}
.social-card-instagram:hover {
filter: brightness(84%);
transition-delay: 100ms;
}
.social-card-tiktok {
position: relative;
&:hover {
animation: tiktok-glitch 1.5s infinite;
animation-delay: 200ms;
}
}
@keyframes tiktok-glitch {
0% {
box-shadow:
0px 0px 0 rgba(0, 255, 255, 0),
0px 0px 0 rgba(255, 0, 255, 0);
transform: translate(0, 0);
}
10% {
box-shadow:
-3px -3px 0 rgba(0, 255, 255, 0.8),
3px 3px 0 rgba(255, 0, 255, 0.8);
transform: translate(-1px, -1px);
}
15% {
box-shadow:
2px -2px 0 rgba(0, 255, 255, 0.6),
-2px 2px 0 rgba(255, 0, 255, 0.6);
transform: translate(2px, -2px);
}
20% {
box-shadow:
-1px 1px 0 rgba(0, 255, 255, 0.4),
1px -1px 0 rgba(255, 0, 255, 0.4);
transform: translate(1px, 1px);
}
25% {
box-shadow:
-4px 4px 0 rgba(0, 255, 255, 1),
4px -4px 0 rgba(255, 0, 255, 1);
transform: translate(-2px, 2px);
}
30% {
box-shadow:
3px -3px 0 rgba(0, 255, 255, 0.5),
-3px 3px 0 rgba(255, 0, 255, 0.5);
transform: translate(3px, -3px);
}
40% {
box-shadow:
-2px 2px 0 rgba(0, 255, 255, 0.9),
2px -2px 0 rgba(255, 0, 255, 0.9);
transform: translate(-1px, 1px);
}
50% {
box-shadow:
-1px -2px 0 rgba(0, 255, 255, 0.7),
2px -1px 0 rgba(255, 0, 255, 0.7);
transform: translate(1px, -1px);
}
60% {
box-shadow:
2px -2px 0 rgba(0, 255, 255, 0.3),
-2px 2px 0 rgba(255, 0, 255, 0.3);
transform: translate(2px, -2px);
}
75% {
box-shadow:
-3px 3px 0 rgba(0, 255, 255, 1),
3px -3px 0 rgba(255, 0, 255, 1);
transform: translate(-3px, 3px);
}
85% {
box-shadow:
-2px -2px 0 rgba(0, 255, 255, 0.2),
2px 2px 0 rgba(255, 0, 255, 0.2);
transform: translate(-2px, -2px);
}
100% {
box-shadow:
0px 0px 0 rgba(0, 255, 255, 0),
0px 0px 0 rgba(255, 0, 255, 0);
transform: translate(0, 0);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,73 @@ module.exports = {
},
],
},
colors: {
// blue: {
// 50: "#ecf6fe",
// 100: "#d9edfc",
// 200: "#b3dbf9",
// 300: "#8ecaf6",
// 400: "#68b8f3",
// 500: "#42a6f0",
// 600: "#3585c0",
// 700: "#286490",
// 800: "#1F4E71",
// 900: "#173A54",
// 950: "#0F2637",
// },
blue: {
50: "#f1f7fe",
100: "#e1effd",
200: "#bddefa",
300: "#82c3f7",
400: "#42a6f0",
500: "#1789e0",
600: "#0a6cbf",
700: "#0a569a",
800: "#0c4980",
900: "#103e6a",
950: "#0b2746",
},
// pink: {
// 50: "#FFFBFE",
// 100: "#FFE4F9",
// 200: "#FECEF4",
// 300: "#FEB8EF",
// 400: "#fea6eb",
// 500: "#D38AC3",
// 600: "#B476A7",
// 700: "#96628B",
// 800: "#774E6E",
// 900: "#593A52",
// 950: "#3A2636",
// },
pink: {
50: "#fff4fd",
100: "#ffe7fb",
200: "#ffcff7",
300: "#fea6eb",
400: "#fc76dd",
500: "#f342ca",
600: "#d722a9",
700: "#b31889",
800: "#92166e",
900: "#771859",
950: "#500238",
},
purple: {
50: "#F8F5FC",
100: "#D5C2ED",
200: "#B28EDE",
300: "#8F5BCF",
400: "#6D30B9",
500: "#5F2AA2",
600: "#52248A",
700: "#441E73",
800: "#36185C",
900: "#281244",
950: "#1A0C2D",
},
},
},
},
plugins: [],

View File

@ -1,7 +1,7 @@
<!doctype html>
<html lang="en">
<head>
<title>{% block title %} {{title}} @michalvankodev {% endblock %}</title>
<title>{% block title %} {{title}} {% endblock %} @michalvankodev</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<meta name="theme-color" content="#333333" />
@ -13,19 +13,16 @@
rel="alternate"
type="application/rss+xml"
title="RSS feed for latest posts"
href="https://michalvanko.dev/feed.xml"
href="/feed.xml"
/>
<!-- Tailwind output file -->
<link rel="stylesheet" href="/styles/output.css" />
<link rel="stylesheet" href="/print.css" media="print" />
<link rel="stylesheet" href="/fonts.css" />
<link rel="manifest" href="/manifest.json" />
<link rel="stylesheet" href="/prism.css" />
<link rel="icon" type="image/svg+xml" href="/m-logo.svg" />
<link rel="icon" type="image/png" href="/m-logo-192.png" />
<link rel="icon" type="image/svg+xml" href="/images/m-logo.svg" />
<link rel="icon" type="image/png" href="/images/m-logo-192.png" />
</head>
<body class="bg-blue-50">
{% include "site_header.html" %}

View File

@ -5,10 +5,10 @@
{% block content %}
<article class="mb-6">
<header class="px-4 max-w-read mx-auto">
<h1 class="text-3xl md:text-4xl lg:text-6xl lg:mt-20 text-blue-900 mb-3 font-semibold">{{title}}</h1>
<h1 class="text-3xl md:text-4xl lg:text-6xl lg:mt-20 text-blue-900 mb-3 font-bold">{{title}}</h1>
<aside class="flex justify-between flex-row">
{% include "post_tag_list.html" %}
<section class="created-at m-1 text-right text-sm text-gray-600 md:text-lg">
<section class="created-at m-1 text-right text-sm text-slate-600 md:text-lg">
<span>Published on</span>
<time datetime="{date}"> {{date|pretty_date}} </time>
</section>
@ -21,6 +21,7 @@
</article>
<!-- TODO: Next recommendations for reading -->
<!-- TODO: Bact to all posts -->
{# footer #}
{% endblock %}

View File

@ -9,7 +9,7 @@
{% else %}
<h1 class="m-5 text-4xl text-blue-950 font-extrabold md:text-6xl">
{% if let Some(t) = tag %}
<em>{{t}}</em>
#{{t}}
{% else %}
Blog posts
{% endif %}
@ -25,13 +25,13 @@
</ul>
</section>
<hr class="border-blue-950 m-5 md:my-8">
<hr class="border-slate-300 m-5 md:my-8">
<ul class="mx-5">
{% for post in posts %}
<li>
{% include "components/blog_post_preview.html" %}
<hr class="border-blue-950 my-5 md:my-8">
<hr class="border-slate-300 my-5 md:my-8">
</li>
{% endfor %}
</ul>
@ -42,15 +42,18 @@
</section> <!-- /#socials -->
<section id="showcase" class="hidden lg:block">
<h2 class="text-blue-950 font-semibold text-2xl m-5 md:text-4xl">Showcase</h2>
<h2 class="text-blue-950 font-bold text-2xl m-5 md:text-4xl"><a href="/showcase" class="text-blue-950 no-underline">Showcase</a></h2>
<ul class="">
<ul class="mx-6">
{% for project in featured_projects %}
<li class="my-2">
<li class="my-4">
{% include "components/project_preview_card.html" %}
</li>
{% endfor %}
</ul>
<section class="text-center my-3 md:text-lg">
<a href="/showcase">check out more projects</a>
</section>
</section> <!-- /#showcase -->
</section> <!-- /#blog-container -->
{% endblock %}

View File

@ -1,3 +1,3 @@
<div class="rounded-2xl w-[180px] h-[240px] bg-blue-100 border-4 border-blue-500 flex justify-center items-center">
<div class="w-[180px] h-[240px] bg-blue-100 flex justify-center items-center">
<span class="text-blue-500 text-8xl -translate-y-1.5">{{post.metadata.title|fmt("{:.1}")|lower}}</span>
</div>

View File

@ -1,8 +1,8 @@
<article class="grid grid-cols-[max-content_1fr] grid-rows-[max-content_1fr_max-content] grid-flow-col gap-4 md:gap-x-8">
<aside class="row-span-3 self-center">
<article class="sm:grid sm:grid-cols-[max-content_1fr] sm:grid-rows-[max-content_1fr_max-content] sm:grid-flow-col sm:gap-4 md:gap-x-8 break-inside-avoid clear-both sm:clear-none">
<aside class="row-span-3 self-center float-start sm:float-none mr-3 mb-3 sm:ml-0 sm:mb-0">
{% match post.metadata.thumbnail %}
{% when Some with (orig_path) %}
{{ crate::picture_generator::picture_markup_generator::generate_picture_markup(orig_path, 180, 240, "Article thumbnail", true).unwrap_or("thumbnail not found".to_string())|safe }}
{{ crate::picture_generator::picture_markup_generator::generate_picture_markup(orig_path, 180, 240, "Article thumbnail", None, true).unwrap_or("thumbnail not found".to_string())|safe }}
{% when None %}
<div>
{% include "components/blog_post_default_thumbnail.html" %}
@ -11,11 +11,11 @@
</aside>
<header>
<h3 class="text-lg font-bold mb-1 md:text-3xl">
<a rel="prefetch" href="/blog/{{post.slug}}" class="text-blue-950 no-underline">{{post.metadata.title}}</a>
<a rel="prefetch" href="/blog/{{post.slug}}" class="text-blue-950 visited:text-purple-700 no-underline">{{post.metadata.title}}</a>
</h3>
</header>
<section class="text-base leading-5 text-gray-800 md:text-xl text-justify">{{post.body|description_filter|safe}}</section>
<footer class="text-sm md:text-base lg:text-lg">
<section class="text-base leading-5 text-slate-800 md:text-xl text-justify">{{post.body|description_filter|safe}}</section>
<footer class="text-sm md:text-base lg:text-lg mt-3 sm:mt-0 clear-both sm:clear-none">
<ul class="inline-block">
{% for tag in post.metadata.tags %}
<li class="inline-block">

View File

@ -1,4 +1,4 @@
<article class="border rounded-md bg-white m-4 p-4">
<section class="border rounded-md bg-white p-4 break-inside-avoid">
<header class="px-4 mb-3">
<h2 class="text-xl font-semibold text-blue-900 md:text-2xl">
{% match project.metadata.link %}
@ -11,23 +11,24 @@
{% endmatch %}
</h2>
<section class="description text-slate-800 my-2 md:text-xl text-justify">
{{project.metadata.description|safe}}
{{project.body|safe}}
</section>
</header>
<!-- <hr class="border-blue-950 my-5"> -->
{% match project.metadata.cover_image %}
{% when Some with (source) %}
<figure class="mx-4 my-2">
{% let picture = crate::picture_generator::picture_markup_generator::generate_picture_markup(source, 420, 236, "Project cover", Some("max-h-[236px]"), true).unwrap_or("cover not found".to_string()) %}
<figure class="mx-4 my-2 flex justify-center">
{% match project.metadata.link %}
{% when Some with (href) %}
<a href="{{href}}">
<img src="{{source}}" class="object-contain w-full aspect-video"/>
{{picture|safe}}
</a>
{% when None %}
<img src="{{source}}" />
{{picture|safe}}
{% endmatch %}
<!-- TODO <figure> -->
<!-- TODO <figure> generate_image -->
</figure>
{% when None %}
{% endmatch %}
@ -45,4 +46,4 @@
{% endfor %}
</ul>
</footer>
</article>
</section>

View File

@ -1,15 +1,14 @@
{% macro social_card_start(svg, heading) %}
{% macro social_card_start(svg, url, heading, img, class) %}
<section class="border rounded-md bg-pink-200 m-4 p-4">
<a href="{{url}}" class="block no-underline border rounded-md bg-pink-200 m-4 p-4 max-w-[392px] {{class}}">
<header class="flex text-center justify-center items-center gap-2 mb-2">
<svg aria-hidden="true" class="h-7 w-7 fill-blue-950">
<use xlink:href="/svg/icons-sprite.svg#{{svg}}" />
</svg>
<h3 class="text-lg font-medium mb-1">{{heading|safe}}</h3>
<h3 class="text-lg font-medium mb-1 text-blue-950 visited:text-blue-950">{{heading|safe}}</h3>
</header>
{% let alt_text = format!("{svg} thumbnail") %}
{% endmacro %}
{% macro social_card_end() %}
</section>
{{ crate::picture_generator::picture_markup_generator::generate_picture_markup(img, 360, 128, alt_text, Some("h-auto mx-auto rounded-sm"), true).unwrap_or("thumbnail not found".to_string())|safe }}
</a>
{% endmacro %}

View File

@ -1,6 +1,6 @@
{% macro talent_card(svg, heading, description) %}
<section class="flex border rounded bg-white m-4 p-3">
<section class="flex border rounded bg-white m-4 p-3 max-w-[32rem]">
<aside class="flex justify-center items-center pr-3">
<svg aria-hidden="true" class="fill-blue-950 h-12 w-12 md:h-16 md:w-16">
<use xlink:href="/svg/icons-sprite.svg#{{svg}}" />
@ -10,7 +10,7 @@
<header>
<h3 class="text-lg font-medium mb-1 md:text-2xl">{{heading}}</h3>
</header>
<p class="text-sm leading-5 text-gray-800 md:text-lg">{{description|safe}}</p>
<p class="text-sm leading-5 text-slate-800 md:text-lg">{{description|safe}}</p>
</section>
</section>

View File

@ -1,25 +1,27 @@
{% extends "base.html" %}
{% block content %}
<h1 class="mx-6 mt-3 text-4xl text-blue-950 font-extrabold">
Contact
</h1>
<section id="contact-page">
<h1 class="mx-6 mt-3 text-4xl text-blue-950 font-extrabold lg:mx-auto max-w-read">
Contact
</h1>
<ul class="mx-6">
{% for link in links %}
<li class="my-6">
<a
class="flex border-2 place-content-center items-center rounded-full border-blue-500 py-5 hover:bg-pink-200 transition-colors"
href="{{link.href}}"
title="{{link.title}}"
>
<svg aria-hidden="true" class="h-6 w-6 fill-blue-950 mx-2">
<use xlink:href="/svg/icons-sprite.svg#{{link.svg}}" />
</svg>
<span class="text-lg font-semibold">{{link.label}}</span>
</a>
</li>
{% endfor %}
</ul>
<ul class="mx-6">
{% for link in links %}
<li class="my-2 sm:my-4 lg:my-6 max-w-[32rem] mx-auto">
<a
class="flex border-2 place-content-center items-center rounded-full text-blue-900 border-blue-500 py-2 sm:py-4 hover:bg-pink-200 fill-blue-900 hover:fill-blue-400 transition-colors no-underline"
href="{{link.href}}"
title="{{link.title}}"
>
<svg aria-hidden="true" class="h-6 w-6 mx-2 self-start">
<use xlink:href="/svg/icons-sprite.svg#{{link.svg}}" />
</svg>
<span class="text-lg font-semibold">{{link.label}}</span>
</a>
</li>
{% endfor %}
</ul>
</section>
{% endblock %}

View File

@ -7,25 +7,24 @@
{% block content %}
<section class="index-container lg:grid lg:grid-cols-2 xl:grid-cols-[1fr_2fr] lg:gap-y-8 lg:gap-x-32 max-w-maxindex mx-auto">
<section id="about-me">
<header class="index-header hidden">
<figure class="profile-pic">
<picture>
<img
alt="Portrait"
{# TODO generate `srcset` for optimal image #}
{# TODO Take a new photo #}
src="/images/profile-portugal-landscape.jpg"
/>
</picture>
</figure>
<!-- <header class="index-header hidden"> -->
<!-- <figure class="profile-pic"> -->
<!-- <picture> -->
<!-- <img -->
<!-- alt="Portrait" -->
<!-- {# TODO Take a new photo #} -->
<!-- src="/images/profile-portugal-landscape.jpg" -->
<!-- /> -->
<!-- </picture> -->
<!-- </figure> -->
<p class="motto">
<cite>“Let your ambition carry you.”</cite>
<span class="cite-owner">- La Flame</span>
</p>
</header>
<!-- <p class="motto"> -->
<!-- <cite>“Let your ambition carry you.”</cite> -->
<!-- <span class="cite-owner">- La Flame</span> -->
<!-- </p> -->
<!-- </header> -->
<h2 class="text-blue-950 font-semibold text-2xl m-5 md:text-4xl">About me</h2>
<h2 class="text-blue-950 font-bold text-2xl m-5 md:text-4xl">About me</h2>
<p class="mx-5 md:text-xl text-justify">
Welcome to my personal website. My name is
@ -34,15 +33,15 @@
<em> <a href="https://en.wikipedia.org/wiki/Programmer">programmer</a> </em>
. I am developing software for more than half of my life and <strong>I love it!</strong> Sometimes I stream working on my side projects and building a <a href="https://discord.gg/2cGg7kwZEh">community of like minded people</a>. Here you can find blogs of my thoughts and journeys, as well as links to my socials where you can see other content.</p>
<section id="talent-cards">
<section id="talent-cards" class="flex flex-col items-center">
{% call tc::talent_card("code", "Web development", "Extensive expertise in creating performant, live web applications and websites") %}
{% call tc::talent_card("gamepad", "Game development", "Extensive expertise in creating performant, live web applications and websites") %}
{% call tc::talent_card("person-chalkboard", "Mentoring & Consulting", "I offer consulting sessions to assist you in developing <strong>higher-quality software</strong> and share insights from crafting robust, professional web applications. <a href=\"TODO callendly\">Schedule a session with me</a> and elevate your projects together.") %}
{% call tc::talent_card("person-chalkboard", "Mentoring & Consulting", "I offer consulting sessions to assist you in developing <strong>higher-quality software</strong> and share insights from crafting robust, professional web applications. <a href=\"https://calendly.com/michalvankosk/30min\">Schedule a session with me</a> and elevate your projects together.") %}
</section>
</section>
<section id="blog" class="lg:col-span-2 lg:row-start-2 xl:col-auto xl:row-start-auto xl:row-span-2">
<h2 class="text-blue-950 font-semibold text-2xl md:text-4xl m-5"><a href="/blog" class="text-blue-950 no-underline">Blog</a></h2>
<h2 class="text-blue-950 font-bold text-2xl md:text-4xl m-5"><a href="/blog" class="text-blue-950 no-underline">Blog</a></h2>
<section id="blog-tags">
<ul class="mx-5">
{% for tag in blog_tags %}
@ -52,23 +51,26 @@
{% endfor %}
</ul>
</section>
<hr class="border-blue-950 m-5">
<hr class="border-slate-300 m-5">
<ul class="mx-5">
{% for post in featured_blog_posts %}
<li>
{% include "components/blog_post_preview.html" %}
<hr class="border-blue-950 my-5 md:my-8">
<hr class="border-slate-300 my-5 md:my-8">
</li>
{% endfor %}
</ul>
<section class="text-center my-3 md:text-lg">
<a href="/blog">see all blog posts</a>
</section>
</section>
<section id="socials">
{% include "sections/social.html" %}
</section>
<hr class="border-blue-950 m-5 lg:hidden">
<hr class="border-slate-300 m-5 lg:hidden">
<section id="showcase" class="col-span-2">
{% include "sections/showcase.html" %}

View File

@ -0,0 +1,24 @@
{% extends "base.html" %}
{% block content %}
<section id="project-list-container" class="max-w-maxindex mx-auto">
<section id="project-list">
{% if project_list.len() == 0 %}
<p class="no-posts">You've found void in the space.</p>
{% else %}
<h1 class="m-5 text-4xl text-blue-950 font-extrabold md:text-6xl">
Showcase
</h1>
<ul class="m-6 grid grid-flow-row gap-6 md:grid-cols-2 md:grid-rows-[masonry] md:justify-stretch md:items-stretch xl:grid-cols-3">
{% for project in project_list %}
<li>
{% include "components/project_preview_card.html" %}
</li>
{% endfor %}
</ul>
{% endif %}
</section> <!-- /#project-list -->
</section> <!-- /#project-list-container -->
{% endblock %}

View File

@ -1,9 +1,13 @@
<h2 class="text-blue-950 font-semibold text-2xl m-5 md:text-4xl">Showcase</h2>
<h2 class="text-blue-950 font-bold text-2xl m-5 md:text-4xl"><a href="/showcase" class="text-blue-950 no-underline">Showcase</a></h2>
<ul class="mx-5 md:grid md:grid-cols-2 md:grid-rows-[masonry] md:justify-stretch md:items-stretch xl:grid-cols-3">
<ul class="mx-6 grid grid-flow-row gap-6 md:grid-cols-2 md:grid-rows-[masonry] md:justify-stretch md:items-stretch xl:grid-cols-3">
{% for project in featured_projects %}
<li class="my-2">
<li>
{% include "components/project_preview_card.html" %}
</li>
{% endfor %}
</ul>
<section class="text-center my-3 md:text-lg">
<a href="/showcase">check out more projects</a>
</section>

View File

@ -1,52 +1,14 @@
<h2 class="text-blue-950 font-semibold text-2xl m-5 md:text-4xl">Socials</h2>
{% call sc::social_card_start("twitch", "I stream (almost) regularly on <em>twitch.tv</em>") %}
<!-- <script src= "https://player.twitch.tv/js/embed/v1.js"></script> -->
<!-- <div id="twitch-player" class="h-64 aspect-video rounded overflow-hidden"></div> -->
<!-- <script type="text/javascript"> -->
<!-- var options = { -->
<!-- width: "100%", -->
<!-- height: "100%", -->
<!-- channel: "michalvankodev", -->
<!-- parent: ["localhost"] -->
<!-- }; -->
<!-- var player = new Twitch.Player("twitch-player", options); -->
<!-- player.setVolume(0.5); -->
</script>
{% call sc::social_card_end() %}
<h2 class="text-blue-950 font-bold text-2xl m-5 md:text-4xl">Socials</h2>
{% call sc::social_card_start("tiktok", "Highlights can be found on <em>TikTok</em>") %}
<!-- STYLES needed to overwrite tiktok embed css -->
<!-- <blockquote -->
<!-- class="h-64 aspect-video overflow-hidden p-0 m-0 tiktok-embed bg-pink-200" -->
<!-- cite="https://www.tiktok.com/@michalvankodev" -->
<!-- data-unique-id="michalvankodev" -->
<!-- data-embed-from="embed_page" -->
<!-- data-embed-type="creator" -->
<!-- style="max-width:780px; min-width:288px; margin: 0; padding: 0; border-radius: 8px" -->
<!-- > -->
<!-- <section> -->
<!-- <a target="_blank" href="https://www.tiktok.com/@michalvankodev?refer=creator_embed">@michalvankodev</a> -->
<!-- </section> -->
<!-- </blockquote> -->
<!-- <script async src="https://www.tiktok.com/embed.js"></script> -->
{% call sc::social_card_end() %}
<section class="grid grid-flow-row justify-center">
{% call sc::social_card_start("twitch", "https://twitch.tv/michalvankodev", "I stream (almost) regularly on <em>twitch.tv</em>", "images/social/twitch_wo.png", "social-card-twitch") %}
{% call sc::social_card_start("youtube", "Vlogs and highlights can be found on <em>YouTube</em>") %}
<!-- TODO create our own youtube widget which will populate this window on build -->
<!-- <iframe -->
<!-- class="h-64 aspect-video" -->
<!-- id="ytplayer" -->
<!-- type="text/html" -->
<!-- width="100%" -->
<!-- height="100%" -->
<!-- src="https://www.youtube.com/embed/?listType=playlist&list=PLjUl8tFKyR8rCsckLn93PAwQg6tf0cyBl&enablejsapi=1&color=white" -->
<!-- frameborder="0" -->
<!-- allowfullscreen -->
<!-- ></iframe> -->
{% call sc::social_card_end() %}
{% call sc::social_card_start("tiktok", "https://www.tiktok.com/@michalvankodev","Highlights can be found on <em>TikTok</em>", "images/social/tiktok_wo.png", "social-card-tiktok") %}
{% call sc::social_card_start("youtube", "https://www.youtube.com/@michalvankodev", "Videos and vlogs posted on <em>YouTube</em>", "images/social/youtube_wo.png", "social-card-youtube") %}
{% call sc::social_card_start("instagram", "Photos and stories shared on <em>Instagram</em>") %}
<!-- <blockquote class="instagram-media aspect-video h-64" data-instgrm-permalink="https://www.instagram.com/michalvankodev/" data-instgrm-version="12" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:540px; min-width:326px; padding:0; width:99.375%; height:256px; max-height:100%;"></blockquote><script async src="https://www.instagram.com/embed.js"></script> -->
{% call sc::social_card_end() %}
<div class="lg:hidden xl:block">
{% call sc::social_card_start("instagram", "https://www.instagram.com/michalvankodev/", "Photos and stories shared on <em>Instagram</em>", "images/social/instagram_plain.png", "social-card-instagram") %}
</div>
</section>

View File

@ -1,4 +1,5 @@
<footer>
<footer class="my-4">
<hr class="mb-4 border-slate-300 mx-5">
<p
class="text-center"
xmlns:cc="http://creativecommons.org/ns#"
@ -14,7 +15,7 @@
<a
rel="cc:attributionURL dct:creator"
property="cc:attributionName"
href="https://michalvanko.dev/"
href="/contact"
>Michal Vanko</a
>
is licensed under
@ -26,16 +27,24 @@
>CC BY-NC-ND 4.0<img
src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"
alt="cc"
class="inline-block h-6 mx-0.5" /><img
class="inline-block h-6 mx-0.5"
height="24"
width="24" /><img
src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"
alt="by"
class="inline-block h-6 mx-0.5" /><img
class="inline-block h-6 mx-0.5"
height="24"
width="24" /><img
src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"
alt="nc"
class="inline-block h-6 mx-0.5" /><img
class="inline-block h-6 mx-0.5"
height="24"
width="24" /><img
src="https://mirrors.creativecommons.org/presskit/icons/nd.svg?ref=chooser-v1"
alt="nd"
class="inline-block h-6 mx-0.5"
height="24"
width="24"
/></a>
<!-- TODO Display link to feed with icon -->
<a href="/feed.xml" class="hidden">RSS feed</a>

View File

@ -1,20 +1,20 @@
<header class="min-h-full bg-blue-50 mb-5">
<nav class="flex">
{% match header_props.back_link %}
{% when Some with (link) %}
<a
class="p-3 text-lg font-medium drop-shadow-md"
href="{{link.href}}"
>
{{link.label}}
</a>
{% when None %}
{% endmatch %}
<aside class="flex logo-section flex-grow justify-end content-end">
<a class="logo p-3 text-base" href="/">
@michalvankodev
</a>
</aside>
</nav>
<hr class="border-blue-950 mx-5">
<nav class="flex">
{% match header_props.back_link %}
{% when Some with (link) %}
<a
class="px-3 py-2 text-lg font-medium print:hidden"
href="{{link.href}}"
>
{{link.label}}
</a>
{% when None %}
{% endmatch %}
<aside class="flex logo-section flex-grow justify-end content-end">
<a class="logo p-3 text-base" href="/">
@michalvankodev
</a>
</aside>
</nav>
<hr class="border-slate-300 mx-5">
</header>

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
static/images/social/instagram_plain.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
static/images/social/tiktok_wo.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
static/images/social/twitch_wo.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
static/images/social/youtube_wo.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

View File

@ -96,7 +96,7 @@ collections:
widget: boolean,
default: true,
}
- { label: Description, name: description, widget: markdown }
- { label: Description, name: body, widget: markdown }
- {
label: Cover image,
name: cover_image,
@ -141,7 +141,7 @@ collections:
widget: boolean,
default: true,
}
- { label: Description, name: description, widget: markdown }
- { label: Description, name: body, widget: markdown }
- {
label: Link,
name: link,