2 Commits

Author SHA1 Message Date
Vlad Faust
6ae6d2126a Add mail 2017-08-29 21:56:55 +03:00
Vlad Faust
4d66cd06c8 New spartan design & content 2017-08-29 21:52:49 +03:00
76 changed files with 77 additions and 3843 deletions

View File

@@ -1,53 +0,0 @@
const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
module.exports = function(eleventyConfig) {
eleventyConfig.addPassthroughCopy("public");
eleventyConfig.addPlugin(syntaxHighlight);
const markdownIt = require("markdown-it");
const md = markdownIt({
html: true,
linkify: true,
typographer: true
});
eleventyConfig.setLibrary("md", md);
md.use(require("markdown-it-toc-done-right"))
md.use(require("markdown-it-attrs"))
md.use(require("markdown-it-imsize"))
md.use(require("markdown-it-sub"))
md.use(require("markdown-it-sup"))
md.use(require("markdown-it-anchor"), {
permalink: true,
// permalinkSymbol: "#",
permalinkBefore: false
})
md.use(require("markdown-it-implicit-figures"), {
figcaption: true
})
const markdownItContainer = require("markdown-it-container");
md.use(markdownItContainer, 'off')
md.use(markdownItContainer, 'hero')
md.use(markdownItContainer,
'spoiler', {
validate: function(params) {
return params.trim().match(/^spoiler\s+(.*)$/);
},
render: function (tokens, idx) {
var m = tokens[idx].info.trim().match(/^spoiler\s+(.*)$/);
if (tokens[idx].nesting === 1) {
return '<details><summary>' + md.utils.escapeHtml(m[1]) + '</summary><div class="spoiler-content">\n';
} else {
return '</div></details>\n';
}
}
})
};

View File

@@ -1,61 +0,0 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["master"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Install dependencies and build
run: |
if [ -f package-lock.json ]; then
npm ci
else
npm install
fi
npm run build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload the built site
path: "./_site"
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

3
.gitignore vendored
View File

@@ -1,3 +0,0 @@
node_modules
_site
package-lock.json

2
CNAME
View File

@@ -1 +1 @@
vladfaust.com
vladfaust.com

View File

@@ -1,2 +0,0 @@
footer
p Vlad Faust © 2016-2023

View File

@@ -1,34 +0,0 @@
//- Meta
meta(charset='UTF-8')
meta(name='viewport', content='width=device-width, initial-scale=1.0')
<!-- Basics -->
title= title ? (titleNoAppend ? title : (title + " - Vlad Faust Blog")) : "Vlad Faust Blog"
meta(name='description', content=description || excerpt)
meta(name='robots' content="index,follow")
meta(name='generator' content='Eleventy')
<!-- Twitter summary -->
meta(name='twitter:card', content='summary')
meta(name='twitter:site', content='@vladfaust')
meta(name='twitter:creator', content='@vladfaust')
meta(name='twitter:url', content='https://vladfaust.com' + page.url)
meta(name='twitter:title', content=title)
meta(name='twitter:description', content=description || excerpt)
meta(name='twitter:image', content=(twitterCover || cover) ? ('https://vladfaust.com' + (twitterCover || cover)) : '')
<!-- OpenGraph -->
meta(property='og:url', content='https://vladfaust.com' + page.url)
meta(property='og:type', content=ogType || 'website')
meta(property='og:title', content=title)
meta(property='og:image', content=(ogCover || cover) ? ('https://vladfaust.com' + (ogCover || cover)) : '')
meta(property='og:description', content=description || excerpt)
meta(property='og:site_name', content=title)
meta(property='og:locale', content='en_GB')
meta(property='article:author', content='https://vladfaust.com')
//- Icons
link(rel='icon', href='/public/icon/cap.svg', sizes='any', type='image/svg+xml')
//- Fonts
link(href="https://fonts.googleapis.com/css2?family=Vollkorn:wght@400;700&display=swap", rel="stylesheet")

View File

@@ -1,22 +0,0 @@
header
a.me(href="/")
img(src='/public/img/me.jpg')
div.text
p
| Hello, my name is&nbsp;
a(href='/') Vlad Faust
| .
p.tablet-hide
| I am a jack of anything IT, master of some; see my&nbsp;
a(href='/cv') CV
| .
p.tablet-hide
| You can contact me via&nbsp;
a(href='https://x.com/vladfaust') 𝕏
| ,&nbsp;
a(href='https://github.com/vladfaust') GitHub
| or&nbsp;
a(href='https://t.me/vladfaust') Telegram
| , or e-mail me directly at&nbsp;
i hey at vladfaust.com
| .

View File

@@ -1,22 +0,0 @@
doctype html
html(lang='en')
head
include /head.pug
//- Styles
link(rel='stylesheet', href='/public/styles/post.css')
link(rel='stylesheet', href='https://unpkg.com/prismjs@1.20.0/themes/prism.css')
body
include /header.pug
main.line-numbers
h1= title
p.meta
time.pubtime(datetime=page.date.toISOString())= page.date.toDateString()
if location
| ,&nbsp;
= location
hr
article(class=(asciiDoctor ? "asciidoctor" : ""))!= content
include /footer.pug

View File

@@ -1,22 +0,0 @@
doctype html
html(lang='en')
head
include /head.pug
//- Styles
link(rel='stylesheet', href='/public/styles/post.css')
link(rel='stylesheet', href='https://unpkg.com/prismjs@1.20.0/themes/prism.css')
body
include /header.pug
main.line-numbers
h1= title
p.meta
time.pubtime(datetime=page.date.toISOString())= page.date.toDateString()
if location
| ,&nbsp;
= location
hr
article!= content
include /footer.pug

View File

@@ -1,5 +0,0 @@
ul.posts
each post in [...collections.post].reverse().filter((post) => !post.data.hidden && post.date <= Date.now())
li
span.date= post.date.toDateString()
a.title(href=post.url)= post.data.title

View File

@@ -1,433 +0,0 @@
h3 Singularity tech (2022-present)
small.annotation
| Behold, the Deus ex Machina blooms, like a lotus from the murky depths.
ul.projects
li.project-card
a.title(href="https://github.com/derouter/derouter") DeRouter
p.desc
| Decentralized, uncensored open-source API marketplace.
.stack
span Open source
span Rust
span P2P
li.project-card
a.title(href="https://github.com/vladfaust/aistories") AIStories
p.desc
| The original source-available AI character simulation platform.
.stack
span Open source
span Commercial
span AI
span Crypto
span NFTs
span TypeScript
span VueJS
span NodeJS
span trpc
span zod
span Solidity
span ethers
li.project-card
a.title(href="https://github.com/vladfaust/kawaiii") Kawaiii
p.desc
| OnlyFans, but for Web3.
.stack
span Open source
span Commercial
span TypeScript
span Ethereum
li.project-card
a.title(href="https://github.com/offchaincafe/evm") Offchain Café EVM
p.desc
| A self-hosted indexing service for Ethereum blockchain, exposing a GraphQL API.
.stack
span Open source
span Crypto
span EVM
span Solidity
span TypeScript
span GraphQL
li.project-card
a.title(href="https://github.com/nxsf/ipnft") IPNFT
p.desc
| An on-chain, digital proof of authorship for an IPFS CID, tailored to existing NFT standards.
.stack
span Open source
span Crypto
span IPFS
span EVM
span Solidity
li.project-card
a.title(href="https://github.com/fancysofthq/contracts") Fancy Contracts
p.desc
| A collection of EVM smart contracts for the Fancy Software apps ecosystem.
.stack
span Open source
span Crypto
span EVM
span Solidity
h3 Onyx, the language (2020-2022)
small.annotation
| Onyx is a novel programming language I'was working on.
ul.projects
li.project-card
a.title(href="https://nxsf.org") NXSF.org
p.desc
| The Onyx Software Foundation website (
a(href="https://github.com/nxsf/nxsf.github.io") source
| ).
.stack
span Open source
li.project-card
a.title(href="https://nxsf.org/onyx/") Onyx standard
p.desc
| An attempt to standardize the Onyx language (
a(href="https://github.com/nxsf/onyx") source
| ).
.stack
span Open source
li.project-card
a.title(href="https://github.com/fancysofthq/phoenix") Phoenix
p.desc An attempt to implement an Onyx language compiler in C++.
.stack
span Open source
span C++
li.project-card
a.title(href="https://github.com/onyxlang/rs") Onyx in Rust
p.desc An attempt to implement an Onyx language compiler in Rust.
.stack
span Open source
span Rust
li.project-card
a.title(href="https://github.com/onyxlang/ts") Onyx in Typescript
p.desc An attempt to implement an Onyx language compiler in TypeScript + Zig.
.stack
span Open source
span Zig
span TypeScript
h3 Crystal-related projects (2018-2020)
small.annotation
a(href="https://crystal-lang.org") Crystal
| is a Ruby-inspired programming language, but compiled.
ul.projects
li.project-card
span.title
a(href="https://onyxframework.com/") Onyx framework
| (2020)
p.desc
| A web framework with&nbsp;
a(href="https://github.com/onyxframework/http") HTTP
| ,&nbsp;
a(href="https://github.com/onyxframework/sql") SQL ORM
| and&nbsp;
a(href="https://github.com/onyxframework/eda") EDA
| modules, fancy website and rich documentation.
.stack
span Open source
span Product design
span Crystal
span SQL
span HTTP
span Event-driven architecture
span VueJS
span SASS
li.project-card
span.title
a(href="https://github.com/crystaljobs") Crystal Jobs
| (2018)
p.desc
| A now defunct Crystal jobs board (
a(href="https://crystaljobs-staging.netlify.app/") frontend preview
| ).
.stack
span Open source
span Product design
span Crystal
span VueJS
span SASS
li.project-card
span.title
a(href="https://github.com/vladfaust/crystalworld") CrystalWorld
| (2019)
p.desc
| A&nbsp;
a(href="https://github.com/gothinkster/realworld") RealWorld
| implementation in Crystal and Onyx the web framework.
.stack
span Open source
span Crystal
span SQLite
h4 Crystal shards (2018-2020)
small.annotation
| A&nbsp;
i shard
| is a Crystal code package.
ul.projects
li.project-card
a.title(href="https://github.com/vladfaust/time_format.cr") TimeFormat
p.desc Time spans formatting made simple.
.stack
span Open source
span Crystal
li.project-card
a.title(href="https://github.com/vladfaust/i18n.cr") I18n
p.desc Internationalization shard.
.stack
span Open source
span Crystal
li.project-card
a.title(href="https://github.com/vladfaust/http-multiserver.cr") HTTP::Multiserver
p.desc Mount multiple web applications.
.stack
span Open source
span Crystal
span HTTP
li.project-card
a.title(href="https://github.com/vladfaust/tarantool.cr") Tarantool
p.desc
| A&nbsp;
a(href="https://www.tarantool.io/ru/") Tarantool
| database driver.
.stack
span Open source
span Crystal
span TCP
li.project-card
a.title(href="https://github.com/vladfaust/cake-bake") Cake-Bake
p.desc Bake Cakefile into native Crystal code.
.stack
span Open source
span Crystal
li.project-card
a.title(href="https://github.com/vladfaust/callbacks.cr") Callbacks
p.desc Expressive callbacks module.
.stack
span Open source
span Crystal
li.project-card
a.title(href="https://github.com/vladfaust/validations.cr") Validations
p.desc Validations module.
.stack
span Open source
span Crystal
li.project-card
a.title(href="https://github.com/vladfaust/mini_redis") MiniRedis
p.desc A light-weight low-level Redis client.
.stack
span Open source
span Crystal
span TCP
li.project-card
a.title(href="https://github.com/vladfaust/http-params-serializable") HTTP::Params::Serializable
p.desc The HTTP params parsing module.
.stack
span Open source
span Crystal
li.project-card
a.title(href="https://github.com/vladfaust/migrate.cr") Migrate
p.desc A database migration solution.
.stack
span Open source
span Crystal
span SQL
li.project-card
a.title(href="https://github.com/vladfaust/stripe.cr") Stripe
p.desc Stripe API wrapper.
.stack
span Open source
span Crystal
span API wrapper
li.project-card
a.title(href="https://github.com/vladfaust/tele.cr") Tele
p.desc A convenient Telegram Bot framework.
.stack
span Open source
span Crystal
span Telegram bot
li.project-card
a.title(href="https://github.com/vladfaust/tele-broadcast.cr") Tele::Broadcast
p.desc Broadcasting for Tele.
.stack
span Open source
span Crystal
span Telegram bot
span Redis
h3 Ruby gems (2015-2017)
ul.projects
li.project-card
a.title(href="https://github.com/vladfaust/jbuilder-json_api") Jbuilder::JsonApi
p.desc Jbuilder meets jsonapi.org specifications.
.stack
span Open source
span Ruby
li.project-card
a.title(href="https://github.com/vladfaust/asset_pipeline") AssetPipeline
p.desc Add Sprockets based Asset Pipeline to your Ruby applications.
.stack
span Open source
span Ruby on Rails
li.project-card
a.title(href="https://github.com/vladfaust/bitcoinpay-client") Bitcoinpay
p.desc Bitcoinpay.com API client for Ruby.
.stack
span Open source
span Ruby
span API wrapper
span Crypto
li.project-card
a.title(href="https://github.com/vladfaust/blockchain-api") Blockchain::Api
p.desc A blockchain.info API wrapper.
.stack
span Open source
span Ruby
span API wrapper
span Crypto
h3 Other projects
ul.projects
li.project-card(style="background-image:url(/public/img/projects/jumpin_sweeties.png); background-repeat: no-repeat; background-position-x: calc(100% + 5rem); background-size: 15rem;")
span.title
a(href="https://xgm.guru/p/sweeties") Jumpin Sweeties
| (2015)
p.desc A casual mobile game.
.stack
span GameDev
span Java
span LibGDX
li.project-card
span.title
a(href="https://parrotfarm.herokuapp.com/") Parrot Farm
| (2016)
p.desc
| A showcase project to demonstrate my skills at those times
small , hosted on Heroku.
.stack
span Open source
span Ruby on Rails
span AngularJS
li.project-card
span.title
a(href="https://nostalgic-hopper-8a1414.netlify.app/") Coinpricebet
| (2018)
p.desc
| A Stellar-based betting on crypto coin prices, also&nbsp;
a(href="https://loving-mahavira-537556.netlify.app/") this
| version.
.stack
span Product design
span Crypto
span VueJS
li.project-card
span.title
a(href="https://heuristic-wozniak-28f7b6.netlify.app/") AssetFD
| (2018)
p.desc An unfinished decentralized exchange interface based on Stellar.
.stack
span Crypto
span VueJS
li.project-card
span.title
a(href="https://github.com/soundmemes") Soundmemes Bot
| (2016-2018)
p.desc A now defunct Telegram bot to post sound memes in chats.
.stack
span Open source
span Product design
span Telegram bot
span Ruby
span Crystal
span PostgreSQL
span Redis
li.project-card
span.title
a(href="https://telegra.ph/CashbackBot-09-16") Cashback Bot
| (2017)
p.desc A now defunct Telegram bot to earn cashback from purchases.
.stack
span Product design
span Telegram bot
span Ruby
span GraphQL
span API wrapper
span PostgreSQL
span Redis
li.project-card
span.title
a(href="https://www.dropbox.com/sh/wpqjtnw0avw6278/AAC55zKcrbVzFmL12xIT4rK2a?dl=0") Expense Manager 2
| (2015)
p.desc A collaborative attempt to improve an existing app.
.stack
span Product design
span Java
span Android
li.project-card
span.title
a(href="https://www.dropbox.com/sh/0heutamg923ohx5/AADmFkWh06vkM3wDsR0P6g_ha?dl=0") Cycler
| (2014)
p.desc An attempt to create a sleep cycle Android application.
.stack
span Product design
span Java
span Android
li.project-card
span.title
a(href="https://www.dropbox.com/s/xc8kjswj4fb0m0z/presentation.pdf?dl=0") Anogram
| (2014)
p.desc A naive attempt to create an anonymous social network.
.stack
span Product design
span iOS
span PHP
li.project-card
span.title
a(href="https://xgm.guru/p/ufs/index") UFS Arena
| (2012)
p.desc
| A Warcraft III™ custom map (
a(href="https://www.dropbox.com/s/odxeaq62jaqvcdc/UFS.w3x?dl=0") source
| ).
dev.stack
span Product design
span GameDev
span cJASS

303
cv.pug
View File

@@ -1,303 +0,0 @@
---
eleventyExcludeFromCollections: true
title: "CV"
description: "Curriculum vitae"
cover: /public/img/me.jpg
---
doctype html
html(lang='en')
head
include /head.pug
//- Styles
link(rel='stylesheet' href='/public/styles/cv.css')
link(rel='stylesheet' href='/public/styles/posts.css')
link(rel='stylesheet' href='/public/styles/projects.css')
style(lang="css").
.history li {
line-height: 1.3;
}
.history li:not(:last-child) {
margin-bottom: 0.5rem;
}
body
include /header.pug
main
section#about
h2
| Curriculum vitae
small(style="margin-top: -0.5em; opacity: 0.9" class="noprint")
| You can download generated PDF from
|
a(href="/public/VladFaust.com.pdf" title="Download") here
| .
p
| Throughout my 10+ years of experience in Information Technology,
|
b I've tried everything
|
| from compiling COFF after LLIR lowering to designing a resilient ultra-scalable fleet of FAAS workers, from Substrate and IPFS to event-driven stock price prediction.
p
| Comprehending a technology is like surfing on the waves of technology trends, on the surface of the greatest whirlpool of singularity. Comprehension means fundamental, decomposed knowledge enough to build a solution at
|
b any scale
| .
p
| For me, it is not about thoroughly learning API of yet another web framework, it is instead getting hands on the set of tooling a technology offers, so that I may choose the
|
mark best framework suitable for the problem
|
| . If I were to compile my 10+ years of experience into one line, that would be the following:
big Right tooling is paramount.
p
| Here is an incomplete list of technologies I've had experience with, in the order of encounter, starting back in 2013: Pascal,&nbsp;
a(href="https://wc3modding.info/pages/vjass-documentation/" target="_blank") vJass
| , cJass, C, C++, Java, git,&nbsp;
a(href="https://libgdx.com/" target="_blank") LibGDX
| , PHP,&nbsp;
a(href="https://unity.com/" target="_blank") Unity
| , C#, Ruby, Telegram,&nbsp;
a(href="https://www.heroku.com/" target="_blank") Heroku
| ,&nbsp;
a(href="https://dokku.com/" target="_blank") Dokku
| , SQLite, PostgreSQL, Redis, Docker, JavaScript, Gulp, Grunt, Ruby On Rails,&nbsp;
a(href="https://hanamirb.org/" target="_blank") Hanami
| ,&nbsp;
a(href="https://roda.jeremyevans.net/" target="_blank") Roda
| , &nbsp;
a(href="https://sequel.jeremyevans.net/" target="_blank") Sequel
| ,&nbsp;
a(href="https://crystal-lang.org/" target="_blank") Crystal
| , LLVM, Kubernetes,&nbsp;
a(href="https://firecracker-microvm.github.io/" target="_blank") Firecracker
| ,&nbsp;
a(href="http://www.tinycorelinux.net/" target="_blank") Tiny Core Linux
| ,&nbsp;
a(href="https://buildpacks.io/" target="_blank") buildpacks.io
| , compiler development, machine learning,&nbsp;
a(href="https://www.tensorflow.org/" target="_blank") Tensorflow
| , VueJS, TypeScript,&nbsp;
a(href="https://deno.land/" target="_blank") Deno
| ,&nbsp;
a(href="https://ziglang.org/" target="_blank") Zig
| ,&nbsp;
a(href="https://en.wikipedia.org/wiki/Parsing_expression_grammar" target="_blank") PEG
| , Rust, EVM, Solidity,&nbsp;
a(href="https://substrate.io/" target="_blank") Substrate
| ,&nbsp;
a(href="https://ipfs.io") IPFS
| ,&nbsp;
a(href="https://en.wikipedia.org/wiki/Zero-knowledge_proof") ZKP
| , ChatGPT, llama.cpp, Godot,&nbsp;
a(href="https://trpc.io/docs/subscriptions") tRPC
| ,&nbsp;
a(href="https://zod.dev") Zod
| ,&nbsp;
a(href="https://tanstack.com/") Tanstack
| ...
ul.history(style="align-self: start;")
li
b 2013:
|
| It all began with Warcraft® III™ maps, such as&nbsp;
a(href="https://xgm.guru/p/ufs/index" target="_blank") UFS Arena
| . I did all the
|
b coding
|
| (cJass, a C-like domain-specific language) and
|
b design
| , and my maps gained some popularity in the Russian-speaking community.
li
b 2014:
|
| First steps in commercial product development:&nbsp;
a(href="https://www.dropbox.com/s/xc8kjswj4fb0m0z/presentation.pdf?dl=0" target="_blank") Anogram
| , a social anonymous service project. I did the
|
b design and backend coding
|
|in PHP. Unfortunately, the trend had quickly detoriated.
li
b 2015:
ul
li
| In 2015, I released an Android game called
|
a(href="https://www.moddb.com/games/jumpin-sweeties/videos/trailer" target="_blank") Jumpin Sweeties
| , written with
|
b LibGDX
| . My family and friends liked it, but it didn't gain much traction.
li
| With
|
b Ruby on Rails
| , I created a Bitcoin service for SMS number confirmations based on Google Voice, and after a couple of months sold it to a foreign customer for a good price. This marked the beginning of my journey as a
|
b solo entrepreneur
| .
li
b 2016:
ul
li
| This was the year of
|
b Telegram bots
|
| for me. First, I created
|
a(href="https://profitrobot.me/" target="_blank") @profitrobot
| , which climbed pretty hign in the bot store rating. The bot allowed users to earn lunch money by completing CPA tasks and watching advertisements. Profitrobot became
|
a(href="/public/img/posts/2020-08-07-hello-world/bot-a-users-graph.jpg") quite popular,
|
| and I managed to sell it to another entrepreneur.
li
| In parallel I worked on
|
a(href="https://t.me/soundmemesbot" target="_blank") @soundememesbot
| , which allowed its users to post sound memes in chats. Long story short, the bot became
|
mark massively popular all around the world
| , but I did struggle to monetize it. Required moderation efforts made me shut it down.
li
b 2017:
|
| Not all the projects are destined to become viable, such that was&nbsp;
a(href="https://telegra.ph/CashbackBot-09-16" target="_blank") CashbackBot
| , a Telegram bot for
|
b cashback services
| . I've spent a lot of time building it, but the project was never launched, nor it was sold.
li
b 2018:
|
| This year marked the beggining of my two-years journey in the
|
a(href="https://crystal-lang.org/" target="_blank") Crystal programming language
|
| ecosystem. I loved being a part of
|
mark open-source
|
| (check out my
|
a(href="https://github.com/vladfaust") GitHub
| !). I created many libraries, including
|
a(href="https://github.com/onyxframework/http") web framework
|
| and
|
a(href="https://github.com/onyxframework/sql") ORM
| , and even
|
b contributed into the language
|
| itself. Also check out my
|
a(href="https://medium.com/@vladfaust/sorbet-is-cool-but-crystal-is-smoother-d16f4a920108" target="_blank") article
|
| comparing Crystal to Stripe's Sorbet.
li
b 2020:
|
| By 2020, I was fed with all the imperfections of the Crystal ecosystem, and decided to move and build
|
mark my own programming language
| , Onyx. Oh, that was a ride. Long story short, too much for a single person. Yet,
|
b an enormous amount of computer science experience
|
| gained. Just look at the plethora of Onyx compilers I was working on:
|
a(href="https://github.com/fancysofthq/phoenix") C++
| ,
|
a(href="https://github.com/onyxlang/rs") Rust
|
| and even
|
a(href="https://github.com/onyxlang/ts") TypeScript with Zig
| ! The
|
a(href="/posts/2020-08-16-system-programming-in-2k20/") System Programming in 2k20
|
| article is still one of the best I've written.
li
b 2021:
|
|
mark Senior Crystal developer
|
| at
|
a(href="https://brightsec.com/" target="_blank") NeuraLegion
| , an Israeli web security company. Nothing fancy, just some good old JSON APIs.
li
b 2022:
|
| I was employed by
|
a(href="https://byzantine.solutions/" target="_blank") Byzantine.Solutions
|
| on the role of a
|
mark Technical Due Diligence Officer
|
| . I inspected and contributed to some of the biggest crypto projects of that time. I also did some crypto-related projects of my own (see below).
li
b 2023:
|
| The epiphany of AI had occured, my mind has cracked, and I've lost the sense of what is past and what is future. Yet I managed to work on some private AI projects at the role of a
|
mark full-stack+prompt engineer
| .
p
| Check out my
|
a(href="https://wakatime.com/@vladfaust" target="_blank") profile at Wakatime
| ; since I've began tracking my time in 2018, I've coded over 7000 hours, resulting in 1000 hours a year average. Take a look at this glorious chart of my favorite languages:
figure(style="width: 100%")
embed(src="https://wakatime.com/share/@vladfaust/92441f4f-e368-4bc3-a53b-9a3100aaa45c.svg")
p
| Currently I'm working on private
|
mark AI character simulation
|
| projects. My best stack is prompt engineering, custom AI model deployment, Rust, C++, Typescript, VueJS, NodeJS, tRPC, Zod and Tanstack.
p
| See my blog posts (especially the
|
a(href="/posts/2020-08-07-hello-world") personal introduction
| ) and projects below, check my
|
a(href="https://github.com/vladfaust") GitHub profile
| , find my contacts in the header, and feel free to reach out if you want to work with me.
p
| Sincerely,
br
| Vlad.
section#posts
h2 Recent blog posts
include /posts.pug
section#projects
h2 Project list
include /projects.pug
include /footer.pug

View File

@@ -1,48 +0,0 @@
const { watch, src, dest, parallel, series } = require("gulp")
const asciidoctor = require("@asciidoctor/gulp-asciidoctor")
const grayMatter = require("gulp-gray-matter")
const tap = require("gulp-tap")
const rename = require("gulp-rename")
function convertAdoc () {
return src("notes/**/*.adoc")
.pipe(grayMatter())
.pipe(asciidoctor({
standalone: false
}))
.pipe(tap(function(file) {
file.contents = Buffer.concat([
new Buffer("---\nasciiDoctor: true\ntemplateEngineOverride: false\n---\n"),
file.contents
])
}))
.pipe(dest("notes"))
}
function extractFrontMatterFromAdoc () {
return src("notes/**/*.adoc")
.pipe(grayMatter())
.pipe(tap(function(file) {
file.contents = new Buffer(JSON.stringify(file.data))
}))
.pipe(rename(function(path) {
path.extname = ".11tydata.json";
}))
.pipe(dest("notes"))
}
function processAdoc (cb) {
parallel(
convertAdoc,
extractFrontMatterFromAdoc)(cb)
}
function watchAdoc () {
watch('notes/**/*.adoc', processAdoc)
};
exports.processAdoc = processAdoc;
exports.default = parallel(
processAdoc,
watchAdoc)

31
index.html Normal file
View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Vlad Faust</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=1" />
<link rel="stylesheet" href="stylesheets/style.css">
<!-- Yandex.Metrika counter -->
<script type="text/javascript"> (function (d, w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounter33155678 = new Ya.Metrika({ id:33155678, clickmap:true, trackLinks:true, accurateTrackBounce:true, webvisor:true }); } catch(e) { } }); var n = d.getElementsByTagName("script")[0], s = d.createElement("script"), f = function () { n.parentNode.insertBefore(s, n); }; s.type = "text/javascript"; s.async = true; s.src = "https://mc.yandex.ru/metrika/watch.js"; if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); } })(document, window, "yandex_metrika_callbacks"); </script> <noscript><div><img src="https://mc.yandex.ru/watch/33155678" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
</head>
<body class="flex-container">
<div class="flex-item">
<h1>Hello, my name is Vlad Faust.</h1>
<p>I love beautiful code. I have 2 years of <a href="https://www.ruby-lang.org">Ruby</a> experience. I'm a huge fan of <a href="https://crystal-lang.org">Crystal</a>.</p>
<h2>My projects:</h2>
<div id="projects">
<ul>
<li><a class="li-title" href="https://cashbackbot.io/48b7a1">Cashback Bot</a> - Save cash on purchases (Ruby);</li>
<li><a class="li-title" href="https://profitbot.me">Profit Bot</a> - Simple tasks for real bucks (Ruby);</li>
<li><a class="li-title" href="https://t.me/soundmemesbot">Soundmemes Bot</a> - Rickroll your friends (Crystal, <a href="https://github.com/vladfaust/soundmemes.cr">opensource</a>);</li>
<li><a class="li-title" href="https://github.com/vladfaust/tele.cr">Tele.cr</a> - Convenient Telegram Bot framework (Crystal, <a href="https://github.com/vladfaust/tele.cr">opensource</a>);</li>
<li class="old-project"><a class="li-title" href="https://play.google.com/store/apps/details?id=com.vladislavfaust.jumpinsweeties.android">Jumpin Sweeties</a> - Sweet Android game (Java / libGDX, <a href="https://bitbucket.org/vladfaust/jumpinsweeties">opensource</a>);</li>
<li class="old-project"><a class="li-title" href="http://xgm.guru/p/ufs">UFS Arena</a> - Warcraft III custom map (<a href="https://ru.wikipedia.org/wiki/Jass">JASS</a>).</li>
</ul>
</div>
<p>You can find me in <a href="https://vk.com/vladfaust">VK</a>, <a href="https://t.me/vladfaust">Telegram</a> and <a href="https://github.com/vladfaust">GitHub</a>.<br>I rarely check my inbox: <a href="mailto:mail@vladfaust.com">mail@vladfaust.com</a>.</p>
<p>I'm never available for hire.</p>
</div>
</body>
</html>

View File

@@ -1,30 +0,0 @@
---
eleventyExcludeFromCollections: true
title: "Vlad Faust"
titleNoAppend: true
description: "My personal website"
cover: /public/img/me.jpg
---
doctype html
html(lang='en')
head
include /head.pug
//- Styles
link(rel='stylesheet' href='/public/styles/index.css')
link(rel='stylesheet' href='/public/styles/posts.css')
link(rel='stylesheet' href='/public/styles/projects.css')
body
include /header.pug
main
section#posts
h2 Recent blog posts
include /posts.pug
section#projects
h2 Project list
include /projects.pug
include /footer.pug

View File

@@ -1,34 +0,0 @@
{
"name": "blog",
"version": "1.0.0",
"description": "",
"main": "index.js",
"private": "true",
"scripts": {
"debug": "DEBUG=* npx @11ty/eleventy",
"dev": "npx concurrently \"npx gulp\" \"npx @11ty/eleventy --serve --port 8082\"",
"build": "npx gulp processAdoc && npx @11ty/eleventy"
},
"keywords": [],
"author": "Vlad Faust <mail@vladfaust.com>",
"license": "None",
"devDependencies": {
"@11ty/eleventy": "^0.11.0",
"@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1",
"@asciidoctor/gulp-asciidoctor": "^2.2.5",
"asciidoctor.js": "1.5.9",
"gulp": "^4.0.2",
"gulp-gray-matter": "^3.0.1",
"gulp-rename": "^2.0.0",
"gulp-tap": "^2.0.0",
"markdown-it-anchor": "^5.3.0",
"markdown-it-attrs": "^3.0.3",
"markdown-it-container": "^3.0.0",
"markdown-it-footnote": "^3.0.2",
"markdown-it-implicit-figures": "^0.10.0",
"markdown-it-imsize": "^2.0.1",
"markdown-it-sub": "^1.0.0",
"markdown-it-sup": "^1.0.0",
"markdown-it-toc-done-right": "^4.1.0"
}
}

View File

@@ -1,105 +0,0 @@
---
title: Hello, World!
location: Moscow, Russia
excerpt: How many years of programming experience is needed to be qualified to start a tech blog? Time for an introductory post!
cover: /public/img/me.jpg
ogType: article
---
How many years of programming experience is needed to be qualified to start a tech blog?
Ten, fifteen?
I see much blogging even with [zero](https://dev.to/), so I decided to give it a try as well.
Time for an introductory post!
## I
I is Vlad Faust.
I started programming when I was 15, and now [I'm 24](https://www.youtube.com/watch?v=oO3YmT2d-8k){.secret-link}.
I've gone through many programming environments, from triggers/vJass/cJass in Warcraft® III [custom](https://xgm.guru/p/wc3/headhunter), [maps](https://xgm.guru/p/ufs), to developing and [implementing](https://github.com/fancysofthq/nxc) a [currently-being-standardized](https://nxsf.org/) programming language.
I've programmed in Pascal, [~~php~~](https://bitbucket.org/vladfaust/anogram-api/src/master){.secret-link style="opacity: 50%;"}, [Java](https://bitbucket.org/vladfaust/jumpinsweeties/src/master/){.secret-link}, Ruby, Javascript, C, C++, C#, C`!@#$%`, C`( ͡° ͜ʖ ͡°)` and many, many more.
I've created a [game](https://www.moddb.com/games/jumpin-sweeties/videos/trailer) in [LibGDX](https://libgdx.badlogicgames.com/), launched a number of Telegram bots, some of which [did](/public/img/posts/2020-08-07-hello-world/bot-a-users-graph.jpg), [become](/public/img/posts/2020-08-07-hello-world/bot-b-reviews.jpg), [popular](https://t.me/soundmemes/61).
I've also designed some [other](https://4pda.ru/forum/index.php?showtopic=571231), [games](https://apkpure.com/ruble-fate-raise-the-rouble/com.faustapps.rublefate) and [projects](https://www.dropbox.com/s/xc8kjswj4fb0m0z/presentation.pdf?dl=0).
<div id="my-open-source"></div>
In 2016, I fell in love with Ruby with the help of the famous the Michael the Hartl's the [Ruby on Rails Tutorial](https://www.railstutorial.org/), and then even open-sourced some <s>very useful</s> gems:
* [Jbuilder::JsonApi](https://github.com/vladfaust/jbuilder-json_api)
* [AssetPipeline](https://github.com/vladfaust/asset_pipeline)
* [SmsActivate](https://github.com/vladfaust/sms_activate)
* [Bitcoinpay](https://github.com/vladfaust/bitcoinpay-client)
* [Blockchain::Api](https://github.com/vladfaust/blockchain-api)
I did truly enjoy Ruby on Rails, but after some time, I began wondering if there were more performant alternatives.
So I went from Rails to Hanami, and then to Roda and Sequel, and then occasionally run into <s>Assembler</s> [Crystal](https://crystal-lang.org/).
I instantly got _addicted to Crystal_.
Throughout the next two years, I've developed a number of very useful shards:
* [TimeFormat](https://github.com/vladfaust/time_format.cr)
* [I18n](https://github.com/vladfaust/i18n.cr)
* [HTTP::Multiserver](https://github.com/vladfaust/http-multiserver.cr)
* [Tarantool](https://github.com/vladfaust/tarantool.cr)
* [Cake-Bake](https://github.com/vladfaust/cake-bake)
* [Callbacks](https://github.com/vladfaust/callbacks.cr)
* [Validations](https://github.com/vladfaust/validations.cr)
* [MiniRedis](https://github.com/vladfaust/mini_redis)
* [HTTP::Params::Serializable](https://github.com/vladfaust/http-params-serializable)
* [Migrate](https://github.com/vladfaust/migrate.cr)
* [Stripe](https://github.com/vladfaust/stripe.cr)
I even managed to build my [own web framework](https://onyxframework.com/) featuring a [REST server](https://onyxframework.com/http), a database-agnostic [SQL ORM](https://onyxframework.com/sql) and even an [EDA platform](https://onyxframework.com/eda)!
I've also built a (now defunct) [Crystal Jobs](https://github.com/crystaljobs) website and the [RealWorld implementation](https://github.com/vladfaust/crystalworld) in Crystal.
Unfortunately <s>for Crystal</s>, I've left the Crystal ecosystem, because this is not the language I've always dreamt of.
And because of [some](https://github.com/asterite){.secret-link} [other](https://github.com/RX14){.secret-link} reasons, but more on that later.
In June 2019, I began working on my own programming language, [Onyx](/posts/2020-08-20-the-onyx-programming-language).
As of August 2020, it's been more than a year of <s>fighting dragons</s> new knowledge and experiences.
I invite you all to follow me on this journey.
![This journey...](../../../public/img/posts/2020-08-07-hello-world/iceberg.png =100%x)
## Am Only Human
Apart from programming, I used to enjoy heavy-lifting in a local gym.
It is not possible now do to [Carpal tunnel syndrome](https://en.wikipedia.org/wiki/Carpal_tunnel_syndrome) I've got the last year.
Please do not let that happen to you!
_Update (2021):_ the illness has gone.
Me love playing computer and board games with my imaginary friends.
My favourite PC games include C&C series, TES series, S.T.A.L.K.E.R. series, Bulletstorm, Carmageddon and [many more](https://store.steampowered.com/app/331470/Everlasting_Summer/){.secret-link}.
I'm always happy to play some [Project Winter](https://store.steampowered.com/app/774861/Project_Winter/) with you guys, PM me for a Discord invite!
Anyone?
Human creation is what I enjoy a lot.
I love listening to good music and examine great drawings.
I can play ukulele and willing to learn the piano and singing.
I'm also experimenting with 3D modelling and digital art.
> [I'll try anything once.](https://gamepedia.cursecdn.com/overwatch_gamepedia/8/81/Echo_-_I%27ll_try_anything_once.ogg){.secret-link}
Sometime in the future, I plan to work on a strong AI implementation, which you can share music and watch movies together with.
This is where [Onyx](/posts/2020-08-20-the-onyx-programming-language) comes into play!
As a pragmatic person, I wrote some seemingly depressive articles "revealing the truth":
* [Твой Дзен: Я](https://telegra.ph/Tvoj-Dzen-YA-07-04)
* [Твой Дзен: Они](https://telegra.ph/Tvoj-Dzen-Oni-07-04)
* [И целого мира не надо](https://telegra.ph/%D0%98-%D1%86%D0%B5%D0%BB%D0%BE%D0%B3%D0%BE-%D0%BC%D0%B8%D1%80%D0%B0-%D0%BD%D0%B5-%D0%BD%D0%B0%D0%B4%D0%BE-12-16)
On my 24^th^ birthday, I've recorded a [video](https://www.youtube.com/watch?v=qCdGP15vGEc) (in English) accumulating my thoughts on the world and my place in it.
----
I think that's enough for an introductory post.
Now you know a little bit more about yours truly.
See you around,<br>

View File

@@ -1,792 +0,0 @@
---
title: System Programming in 2k20
location: Moscow, Russia
excerpt: System programming seems to be much harder than application programming. Why is that and how to overcome this?
cover: /public/img/posts/2020-08-16-system-programming-in-2k20/state-therof.jpg
ogType: article
---
System programming is still essential, but it seems to be much harder than application programming.
Why is that and how to overcome this -- these are the questions I'll try to find answers for in this article.
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<h2>Table of Contents</h2>
${toc}
## Introduction
A hundred years ago, a person could not imagine to be able to play any musical instrument they want, to create new interactive worlds, or to launch cars into space.
Life was simply not enough.
Then the machines came.
Silicon computations allowed us, mere mortals, prolong our lives virtually and literally.
Music creation software, game development engines, 2D and 3D editors, neural networks, AI and machine learning, motion capturing, navigation, medicine, wearable devices, smartphones...
Thanks to these, a person now can do a lot of things while having more free time during their lifespan.
It all happened because a human learned to communicate with machines with means of programming languages.
Early inventors of the future were brilliant people able to coin fundamentally new concepts which last until today.
But this is the how the humanity evolves: we accumulate knowledge and pack, shortcut it.
We don't need to keep in head proofs of every mathematical theorem, and we don't need to fully understand the nature of an axiom.
Instead, we store theorem and axiom statements.
With that in mind, we have more space to solve new problems.
The same applies to programming.
Those brilliant people inevitably become old, as real system programming knowledge fades away.
On the surface, the amount of those who really understand how machines work seems to shrink.
<figure>
<blockquote class="twitter-tweet" data-lang="en" data-dnt="true">
<p lang="en" dir="ltr">Also this. My aim is to bring 96 back for 20s devs <a href="https://t.co/avFQxxIfpP">pic.twitter.com/avFQxxIfpP</a></p>&mdash; Vlad Faust (@vladfaust) <a href="https://twitter.com/vladfaust/status/1264117331820711936?ref_src=twsrc%5Etfw">May 23, 2020</a>
</blockquote>
<figcaption>Hey, that's me!</figcaption>
</figure>
"But I can run a newural network with Python!", one would argue.
Well, who do you think develops TensorFlow itself?
TensorFlow [isn't written in Python](https://github.com/tensorflow/tensorflow), kid.
Writing a game in Lua or Ruby is totally possible, as well as creating a messenger or code editor in Electron.
However, Electron, as any mature game engines, are still written in [C++](https://github.com/electron/electron).
Almost any meaningful software which needs to utilize a machine with more than [20%](https://en.wikipedia.org/wiki/Pareto_principle){.secret-link} efficiency, is written in a system programming language.
::: hero
System programming is the foundation of the development of the human civilization.{style="font-size: 2.25rem"}
:::
Regardless of its importance, system programming seems to be less popular than application programming, because it's known to be harder to both learn and master.
It is definitely easier to spin up a web server, connect it to a database, set up some Stripe integration, drink a smoothie and proudly call yourself an entrepreneur.
But that does not invest in the human civilization's progress on the Kardashov's scale.
<mark>The humanity will still depend on system programming in the foreseeable future.</mark>
And we need new, fresh blood there.
In this article, I'll try to take a peek on the current state of the system programming, find out why it's not that popular and choose the best system programming language for the Next Big But Fairly-Low-Level Project (tm).
## Choosing the Right Language
When choosing a serious language for serious system programming, the choice is broad: it's either C, C++, Rust, or one of the many new LLVM-based projects.
### C
C is excellent at its simplicity, but bigger projects require higher-level language features, such as [memory control](https://twitter.com/jfbastien/status/1289305925199650816), object hierarchy, lambdas etc.; therefore, C is out of competition here.
Ditto applies to C "replacements", such as [Ẕ̴̰̥̔͝i̷̥̣̍̓̉ġ̷̢̪͌̾́](https://ziglang.org/) and [Patreon-lang](https://vlang.io/).
### C++
C++ is the grandfather of higher-level system programming.
It offers powerful features with a grain of Unix epoch practices and a great amount of undefined behaviour.
Funnily enough, an experienced C++ programmer shall aware of not what C++ is, but of what it is not, i.e. undefined behaviour of the language.
That said, developing on C++ is pain, and it is easy to shoot your lower parts off by, say, returning a lambda with a closured local variable.
Of course, it is possible to have a fancy third-party UB checking tool, but such a tool would never be perfect considering the amount of UB in the language itself.
![Relatable AF](../../../public/img/posts/2020-08-16-system-programming-in-2k20/thinking-about-meme.jpg =100%x)
Another Unix anachronism C++ inherits is the backwards compatibility with a bitter taste of Postel's law: "most compilers implement that feature in different ways, let's put it into the language after a short thought with design averaging from existing implementations!".
One may argue that backwards compatibility is a good thing, but let me postpone this discussion for a [later section](#backwards-compatibility) of this article.
### Rust, pt. 1
Rust is a fairly young programming language with a reputable mission: empower everyone to build reliable and efficient software.
Let's deconstruct the statement.
One of the game-changing features of Rust is the separation between safe and unsafe code.
The ability to isolate volatile code worths a lot: if anything goes wrong, then you simply `grep` your codebase with `unsafe` filter and voilà -- all the dangerous invocations are at your hand sight.
It also allows _the_ implementation to perform crazy optimizations, say, by entirely removing parts of code; and it's fine because there is no unsafe access to that code.
As a result, focusing on volatile code becomes easier, and nasty bugs are squashed faster.
Otherwise, _the_ Rust compiler would yell at you, pointing at your mistakes in the safe code area.
And those yells are detailed enough, so most of the time you have a clear picture on why you're wrong and what to do with that.
Compared to C++, Rust compilation process is much friendlier and catches more bugs before you face them in runtime.
![I just wanted to sort an array](/public/img/posts/2020-08-16-system-programming-in-2k20/errors-in-langs.jpg "How different compilers react to user errors" =100%x)
Another good thing about Rust is macros.
Well, what's good is the idea of macros; the implementation of macros in Rust is um... questionable.
Nevertheless, macros allow writing code in code with much greater flexibility than with C++ preprocessor and constant expressions.
Nuff said, macros are must-have in modern languages.
The built-in crates system Rust has brings powerful abstractions into the ecosystem.
Those folks enjoying lower-level programming and having enough skills to do so can wrap unsafe, but performant code, into simple, but safe abstractions.
And those who have a need to just make things work, may (comparably) [easy adopt those crates](https://www.theregister.com/2020/01/21/rust_actix_web_framework_maintainer_quits/).
----
<!-- ![Checkpoint!](../../../public/img/posts/2020-08-16-system-programming-in-2k20/checkpoint.svg =100%x) -->
Rust really does allow to build _reliable_ (no undefined behaviour in-the-wild) and _efficient_ (thanks to the zero-cost philosophy) software to _everyone_ (with powerful abstractions).
But, there are always some "but<sub>t</sub>s".
First of all, only a few may say Rust has friendly syntax.
In the maniacal pursuit for the absolute memory safety, the language introduces plethora of abstractions such as borrow checker, six string types (hey, we're making a language here, not a guitar), `Mut`, `Box`, `Arc`, `Trait`, requiring to do those ubiquitous `unwrap()`, `as_ref()` and `borrow()` (often chained) literally before every access.
Some may call it "hipster thinking", but those small spikes like mandatory semicolons\*, curly brackets wrapping, and otherwise unintuitive design decisions like constantly "screaming code" with ubiquitous bangs (`!`) and overloaded documentation semantics — they make writing and reading Rust code harder.
Definitely harder than Ruby or, say,
J̸̧̨̹͈̦̏̅͒̈́͂͐̄̾͟͟ͅȃ̡͎̯̟̦͉͂͊̿̈́v̢̡͖͍̻̳̞͌͌̈̋̐͌̆͜a̴͖̱̟̩̹̘̺͊̃̋̇̾̀̀͐̊͐ͅS̶͚̣̥͚͈̥̤͔̾̎̎̿̔͊̋̉̓c̶̡̧̗̻̊̈̋̍̔̂̅̓̚͘͢ŗ̰͖̲̙͖͕̂̏̍͑̊̋ḯ̸̛̤̦̠͈̩̙̯̘̥̖̅́̊̀͑̕͠͠p̸̨̧̨̧̡̛̮̯͖̹͈̉̑̿͛̎̀͌̾͞ț̸̩͕͈̊͐̏̏̕͡ͅ
.
::: off
\* In fact, semicolons are not mandatory
_everywhere_
, which brings even more confusion.
From [StackOverflow](https://stackoverflow.com/questions/26665471/are-semicolons-optional-in-rust):
> Semicolons are generally not optional, but there are a few situations where they are. Namely after control expressions like `for`, `if/else`, `match`, etc.
[Bruh.](https://www.myinstants.com/media/sounds/movie_1.mp3){.secret-link}
:::
A [wise man](https://en.wikipedia.org/wiki/Jason_Statham){.secret-link} once said:
> The complexity of a language feature is proportional to the number of articles explaining the feature.
Here go a tiny fraction of reads on why Rust is not even nearly to an intuitive language:
1. [Common Rust Lifetime Misconceptions](https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md)
1. [What Not to Do in Rust](https://blog.sentry.io/2018/04/05/you-cant-rust-that?utm_content=137995710)
1. [Frustrated? It's not you, it's Rust](https://fasterthanli.me/articles/frustrated-its-not-you-its-rust)
1. [Understanding lifetimes](https://www.reddit.com/r/rust/comments/ic67tm/understanding_lifetimes/) (the subreddit itself is straight proof of how insanely complex the language is)
1. [Understand smart pointers in Rust
](https://stackoverflow.com/questions/55075458/understand-smart-pointers-in-rust) (the StackOverflow tag is full of that gold)
1. [Clear explanation of Rusts module system](http://www.sheshbabu.com/posts/rust-module-system/)
The following is my personal collection of "why I love Rust".
::: spoiler ⚠️ Lots of nasty tweets inside
<figure>
<blockquote class="twitter-tweet">
<p lang="en" dir="ltr">The learning curve of <a href="https://twitter.com/rustlang?ref_src=twsrc%5Etfw">@rustlang</a> for whoever is used to GC languages is steep but very interesting. Like, this code does *not* compile in Rust, but it actually makes a lot of sense 🤯:<a href="https://twitter.com/hashtag/programming?src=hash&amp;ref_src=twsrc%5Etfw">#programming</a> <a href="https://t.co/yLru0bQ0gV">pic.twitter.com/yLru0bQ0gV</a>
</p>&mdash; Rémi Sormain (@RSormain) <a href="https://twitter.com/RSormain/status/1287395421736898560?ref_src=twsrc%5Etfw">July 26, 2020</a>
</blockquote>
<figcaption>No, it does not</figcaption>
</figure>
<figure>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">A nasty compiler error to start the morning. (pages of this) <a href="https://t.co/vvMqcOsYcC">pic.twitter.com/vvMqcOsYcC</a></p>&mdash; Luca Palmieri 🦊 (@algo_luca) <a href="https://twitter.com/algo_luca/status/1286935357083340801?ref_src=twsrc%5Etfw">July 25, 2020</a></blockquote>
<figcaption>You'd better start with coffee</figcaption>
</figure>
<figure>
<blockquote class="twitter-tweet">
<p lang="en" dir="ltr">This is fine, just a perfectly normal function signature. <a href="https://t.co/qotj5f3ndb">pic.twitter.com/qotj5f3ndb</a>
</p>&mdash; Bodil Stokke, Esq. (@bodil) <a href="https://twitter.com/bodil/status/1259127749169631232?ref_src=twsrc%5Etfw">May 9, 2020</a>
</blockquote>
<figcaption>That's alright, they find a way to reduce it in the replies</figcaption>
</figure>
<figure>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">What is this even.<a href="https://t.co/0oUvVMJYEC">https://t.co/0oUvVMJYEC</a></p>&mdash; James Munns (@bitshiftmask) <a href="https://twitter.com/bitshiftmask/status/1227021520133853184?ref_src=twsrc%5Etfw">February 11, 2020</a></blockquote>
<figcaption>Those signatures tho</figcaption>
</figure>
<figure>
<blockquote class="twitter-tweet">
<p lang="en" dir="ltr">when my backend looks like this so her frontend can look like that <a href="https://t.co/xV4d6bi7ge">pic.twitter.com/xV4d6bi7ge</a></p>&mdash; Yaah 🦀 (@yaahc_) <a href="https://twitter.com/yaahc_/status/1293411590964830208?ref_src=twsrc%5Etfw">August 12, 2020</a>
</blockquote>
<figcaption>ditto</figcaption>
</figure>
<figure>
<blockquote class="twitter-tweet">
<p lang="en" dir="ltr">Methods with a variable number of parameters in <a href="https://twitter.com/rustlang?ref_src=twsrc%5Etfw">@rustlang</a>.<br><br>AMA.<br>😭 <a href="https://t.co/IJ77fMLGPp">pic.twitter.com/IJ77fMLGPp</a></p>&mdash; Luca Palmieri 🦊 (@algo_luca) <a href="https://twitter.com/algo_luca/status/1296732882237612034?ref_src=twsrc%5Etfw">August 21, 2020</a>
</blockquote>
<figcaption>Did someone said "macros"?</figcaption>
</figure>
<figure>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">What is the correct <a href="https://twitter.com/rustlang?ref_src=twsrc%5Etfw">@rustlang</a> borrowing trait to impl for a wrapper type that enforces an invariant (i.e. NonZero*) but where otherwise you want it to be usable anywhere the inner type is usable? (note: poll, not quiz)</p>&mdash; Tony “Abolish (Pol)ICE” Arcieri 🦀 (@bascule) <a href="https://twitter.com/bascule/status/1299084955025203200?ref_src=twsrc%5Etfw">August 27, 2020</a></blockquote>
<figcaption>What. The. Fuck.</figcaption>
</figure>
:::
And sorry for these (you can open them in a new tab to enlarge (but please don't)).
![](../../../public/img/posts/2020-08-16-system-programming-in-2k20/rust-is-simple-1.jpg =100%x)
![](../../../public/img/posts/2020-08-16-system-programming-in-2k20/rust-is-simple-2.jpg =100%x)
![](../../../public/img/posts/2020-08-16-system-programming-in-2k20/rust-is-simple-3.jpg =100%x)
----
<mark>Rust is more confusing than C++</mark>, change my mind.
On the one side, _the_ compiler is always watching your moves, and it is responsible for ensuring protection from undefined behaviour...
But that power comes at the price of unfriendly, clumsy, cumbersome syntax with lots of unintuitive abstractions and repetitive actions.
Now, instead of keeping in mind of where C++ might blow, one shall be aware all the abstractions Rust brings in to choose the right one, <small>and where to place a semicolon</small>.
That said, the "for everyone" clause in the mission statement seems unfair to me now.
It takes great effort to become fluent in Rust.
Regarding other two clauses in the Rust's mission, I still have no claims on them.
Rust programs are known to be reasonably performant (<small>if you ever manage to wait until `rustc` compiles with optimizations turned on</small>), and there is even the academia-grade [RustBelt](https://plv.mpi-sws.org/rustbelt/) organization ensuring the UB-safety.
You can always find more on what's the good, the bad and the ugly about Rust, but the main point is that <mark>the language is not ideal</mark>, and there is definitely room for improvements.
Plus one point to the justifying.
### Challengers Worth Mentioning
There are some other noteworthy languages, which nevertheless do not fit my requirements for [various reasons](https://en.wikipedia.org/wiki/Not_invented_here).
#### Julia
[Julia](https://julialang.org/) is quite a mature language focused on **scientific research**.
First of all, I'm interested in a general-purpose language.
I want to be able to create mainstream GUI applications, microservices and 3D engines, while Julia is focused on multi-dimensional arrays and plots.
::: spoiler Second of all,
![This](../../../public/img/posts/2020-08-16-system-programming-in-2k20/jit-is-slow.jpg "JIT is slow meme" =70%x)
:::
You can find more on why not Julia [here](https://www.zverovich.net/2016/05/13/giving-up-on-julia.html), with critique addressed [here](https://www.reddit.com/r/Julia/comments/629qkz/about_a_year_ago_an_article_titled_giving_up_on/).
Check out [another hilarious post](https://discourse.julialang.org/t/get-it-together-guys/27826) on this matter.
I personally love this quote:
> Get a job! Then paint your masterpiece.
Telling that to a scientific language developed in MIT by scientists...
Well, more on that later.
#### Nim
[Nim](https://nim-lang.org/) claims that it is a system programming language, but it currently lacks support for some lower-level features like alignment and address spacing.
One still has to wrap a C/C++ library or write inline C/C++ for low-level programming, e.g. on a GPU.
In that sense, Nim is similar to Python and other higher-level languages with FFI.
In addition to that,
* Nim lacks proper [object-oriented features](https://nim-lang.org/docs/tut2.html#object-oriented-programming) like interfaces and mixins.
OOP is crucial for a big project, change my mind.
* Nim [does not have explicit safety concepts](https://github.com/nim-lang/Nim/wiki/Unofficial-FAQ#is-nim-unsafe).
* Nim has Python-like indentation-based syntax with lines ending in `=` and `:`, which is **subjectively** worse than Ruby-like syntax.
Also the `import` semantic inherited from Python is fundamentally different from Ruby's `require`, and all the macros and generics semantics to be proposed becomes cumbersome to use with `import`s.
#### Crystal
I love the core idea behind Crystal.
I don't like its implementation.
They are saying that [Crystal](https://crystal-lang.org/) is a general-purpose programming language, but that's not true.
The language and its core team are focused on their needs, which is solely an `amd64-linux` platform.
The standard library is bloated with heavy dependencies like `libxml` and `libyaml`, the language itself has GC, event loop and unwinding-based exceptions (i.e. a runtime) built-in, and it's therefore hardly possible to ship an executable for purposes other than serving requests over HTTP.
After almost 10 years in development, the core team still has disagreements in the fundamental design, and you may commonly see controversial claims by its officials regarding Crystal's future on the forum.
They even can not decide if Crystal is a compiled Ruby or something else.
<!-- TODO: Reference example issues and posts here. -->
Regarding the number of bugs the only implementation has...
Once you dig a little bit deeper, it all begins to explode.
Macros, generics, unions, interoperability: it may blow up anywhere.
A core team [representative](https://github.com/asterite){.secret-link} without "core team" badge will then appear telling you that <small>it's not a bug, or wait, it is a bug, but it can not be fixed, oh wait, it can be fixed, but it's not a bug, issue closed, thanks</small>.
<!-- TODO: There tons of examples of such behaviour, should put them here. -->
The recently introduced multi-threading brings even more problems due to the lack of proper addressing of the data races in the language.
As most of the other design decisions in Crystal, this one has been taken somewhere in Manas without any open discussion.
I've spent two years in the Crystal ecosystem, and it did not move forward a bit, only backwards (bye, [Serdar](https://twitter.com/sdogruyol), bye [Julien](https://twitter.com/ysbaddaden)).
A brilliant idea is buried by lack of focusing on the community needs.
A hard lesson to learn.
It's time for (_spoiler alert_) Crystal done right.
## Backwards Compatibility
One would now jump into proudly announcing another language they've come up with, a utopia-grade solution to replace both C++ and Rust once and forever.
But the "forever" claim is kinda sloppy.
Remember how I mentioned earlier that backwards compatibility is not _that_ good?
The truth is that there will always be unforeseeable new features at some point, which have to be implemented, so a language stays competitive.
For example, coroutines, a term coined in 1958, were not much of interest until 2010's...
A product aiming to preserve backwards compatibility has to somehow insert new features into existing rules without introducing breaking changes.
C++ is an excellent primer on how not to.
Constrained by existing implementations, they add overly complicated `co_await` functionality into the standard library with extra garbage, which instead should have been built into the language itself (the functionality, not the garbage).
Another ad-hoc example is C++20 concepts.
Instead of allowing to restrict generic arguments in-place, a new `requires` syntax is added, which is quite cumbersome: see [this](https://akrzemi1.wordpress.com/2020/01/29/requires-expression/) and [this](https://akrzemi1.wordpress.com/2020/03/26/requires-clause/).
As the hardware evolves, new fundamental types come into play.
What's the state of support of SIMD vectors, tensors or half-precision floats in C++? Brain floats?
Oh please.
Instead of being incorporated into the standard, implementations come with their own solutions, which further invests into the chaos.
But breaking changes are always painful, you would argue because on one side you want to use all the shiny new features, but on the other, you don't want to spend a dime rewriting your code.
It becomes even worse when an open-source library author you're depending on decides that they will not support the older major version of a language; or, instead, they won't move on to the newer version.
Given the number of open-source libraries your project depends on, you are in trouble, as library versions become stale or incompatible.
All that's left is to visit a library's bug tracker and leave a "what's the status of this?" or "+1" comment, or maybe even put a little bit more effort:
[![I'm sorry for putting my Patreon account link in an MIT-licensed repository 😔](/public/img/posts/2020-08-16-system-programming-in-2k20/are-you-still-there.png "Are you still there??" =100%x)](https://github.com/vladfaust/unity-wakatime/issues/25)
When deciding on which language to build your next big project™ in, what you (or your PM) really want is that it accounts for all the present and future software and hardware features, has ultimate performance, maintainability, and never introduces any breaking changes, so you constantly reap the rich choice of forever-actual libraries.
Of course, such a language should be free as beer, as all of the forever-actual libraries.
What's the point otherwise?
## Rust, pt. 2
Looks like Rust is the perfect candidate.
In the famous [Rust: A Language for the Next 40 Years](https://www.youtube.com/watch?v=A3AdN7U24iU) talk, they say that Rust will never have a major breaking change, staying <s>young</s> version `~> 1` forever, but still evolving.
Wait a minute.
At 32:15, Carol says:
> When I first heard of that idea, I thought it sounds terrible from the compiler maintenance point of view: you have to maintain two ways to use every feature forever because we wanted to commit to all editions being supported forever. But it's actually not that bad.
Then they take a good thinking sip of water and prove that it is indeed that bad.
[![MFW I realize something's wrong but the slides are already there (clickable)](../../../public/img/posts/2020-08-16-system-programming-in-2k20/carol-knows.png "Carol knows the truth" =100%x)](https://youtu.be/A3AdN7U24iU?t=1822)
Effectively, the "forever `~> 1`" policy limits the number of fundamental features Rust MIR can have changed.
According to the talk, only a few keywords are to differ between editions.
So what we have in the dry run is a never-really-changing language with some slightly-different dialects to support.
Occasionally, an implementation would opt-out of supporting an edition, and consequently all the libraries written in this edition become unusable.
No ecosystem split, huh?
The editions problem could be addressed by supporting multiple editions in a single library.
But what if a library author you're depending on decides that they will not support a specific edition...
Um.
> [Ever got that feeling of déjà vu?](https://static.wikia.nocookie.net/overwatch_gamepedia/images/c/c0/Tracer_-_Ever_get_that_feeling_of_d%C3%A9j%C3%A0_vu.ogg){.secret-link}
Yes, we're back to breaking changes and supporting multiple incompatible major <s>versions</s> editions of a language.
Oh those lazy open-source, free, OSI-licensed library maintainer bastards, they are the evil root of all the problems!
## On Open-Source Sustainability
For some, programming is just a job.
For others, programming is a form of artistic expression.
For artists, writing open-source software facilitates the top two levels of the Maslow's hierarchy: self-actualization and esteem.
They enjoy writing clean, well-documented code, so anyone using it could feel the same.
Guess who creates (a significant portion of) quality open-source software?
![Us, the artists!](../../../public/img/posts/2020-08-16-system-programming-in-2k20/it-was-me.jpg =100%x)
The above certainly applies to me.
I used to maintain a [number](https://github.com/vladfaust?tab=repositories&q=&type=&language=crystal) of Crystal projects, most of which were well-documented and optimally performant.
I enjoyed writing [documentation](http://github.vladfaust.com/mini_redis/index.html) and [compiling changelogs](https://github.com/vladfaust/mini_redis/releases/tag/v0.2.0).
I even enjoyed [replying to issues](https://github.com/vladfaust/unity-wakatime/issues/25), to reveal [unexpected use-cases](https://github.com/vladfaust/migrate.cr/issues/12), [add new features](https://github.com/vladfaust/unity-wakatime/pull/11) and [squash bugs](https://github.com/vladfaust/unity-wakatime/pull/23) together.
The greatest project of mine in Crystal was the [Onyx Framework](https://onyxframework.com), a web framework comprised of a REST server, a database-agnostic SQL ORM and even EDA facilities.
I was planning to also implement a GraphQL framework module, and a convenient CLI to ease the development process.
Objectively, it is more user-friendly, a better balanced between features and usability, than alternatives.
You can find out more about my journey in programming in the [introductory post](/posts/2020-08-07-hello-world/).
### Primitive Needs to Be Ashamed Of
An artist, like any other human, has more needs to satisfy, though.
These are safety and psychological needs.
In other words, a man gotta pay his bills.
Was I able to pay my rent with open-sourcing?
> [LOL, haha!](https://static.wikia.nocookie.net/overwatch_gamepedia/images/a/a4/D.Va_-_Lol.ogg){.secret-link}
Nowadays, a senior iOS developer in Russia has a salary of about $4'000 (300'000₽), which is $25 per hour.
At the best times, my salary as an Open-Source engineer was pathetic $70.
![Earnings BEFORE TAX](/public/img/posts/2020-08-16-system-programming-in-2k20/patreon-income.png "A Patreon income graph with an extremum of $70" =100%x)
I did receive some "tokens of appreciation" from companies a couple of times, but those were not regular, and I could certainly not have a decent living even with them.
You may argue that it was my fault to choose a promising young language with sweet syntax and native performance to invest my time in, but reread this sentence.
----
Is it easy to pay your bills when you're a poet?
Poetry is a basic form of art, but only a few, from many talented, poets can make their living doing what they love.
Given the same talent level, it takes big luck to become recognized and earn enough to pay rent.
Some poets may come to streets and start reciting their poetry, hoping for a dime donated.
Some are more than happy to be hired by a children book publishing company which needs lots of similar poems...
As the individualism fades away.
<!-- TODO: I can't remember a Javascript repository with brilliant sentences like "if you liked the code, maybe check out my patreon 😂😂😂, but if you want 😂😂😂, sorry 😂😂😂". -->
There are several paths for an open-source maintainer:
1. To spend their time entirely for free.
1. To spend their time entirely for free, but put a link to their pitiful $0.0002/week Liberapay account, which would inevitably infuriate some Rabadash8820.
It is also required to always wrap the links with "😂" emojis and constantly [feel bad](https://clips.twitch.tv/RacyImpossibleTubersWTRuck) about asking to compensate for your time.
The fuck?
1. To sell their time as a software consultant and provide direct support for their libraries.
These are often sold under the donations sauce and imply the same shameful constraints.
1. To choose one of the explicit business model paths, such as open-core, where the product is not an open-source anymore, but a real business with marketing, cold calls, email spam, free trials etc.
Regarding working for free (paths 1 and 2), I love this quote by myself:
> Companies rely on those spending their precious time for free in the hope of being hired by those companies.
> A Saṃsāra's circle to break.
Compared to poetry, the consultancy path (3) is like giving interviews and explaining your poems to others verse-by-verse. Which is not that bad.
Although sometimes you want to spend your time on writing new poems instead of explaining the old ones.
Moreover, some precious time has already been put into an old poem and shall be compensated as well.
Musicians do not tend to give their already written songs for free, do they?
Regarding an explicit business path (4), I believe that it has the same consequences for software as for poetry or music.
An artist starts to think about money more than art, which inevitably leads to worse quality.
For example, in the open-core model, a maintainer spends resources on consciously deciding which features are to be deleted from the "open" part, and how to glue them with the paid part.
That being said, are there any other ways to sustain open-source, <mark>to make open-sourcing a _real job_</mark>?
### Source-On-Demand
For musicians, there are platforms like Spotify, where a listener pays a fixed amount of money regularly, and the platform pays a musician based on how popular they were during the period.
Can it be applied to model open-source sustainability?
One of the problems arising is how to determine the "popularity" of an open-source library.
Is that the number of unique downloads ("launches")?
Or maybe some sort of manually-triggered endorsements?
Also, a library may still be useful, but too specific, hence not "popular".
Its maintenance would still require a comparable amount of resources.
The solution may be an algorithm taking into consideration both downloads from, say, unique IP addresses, per month, and manual endorsement actions like claps on Medium.
Unfortunately, highly-narrowed, hence unpopular, libraries would still have to look for other sources of funding.
Okay, this looks like a good plan.
But.
In the music world, an artist becoming obsessed with the number of streams rather than with the quality of their music, either loses its popularity or changes trends towards <s>shitty</s> lesser-quality music.
![I don't know who is it](../../../public/img/posts/2020-08-16-system-programming-in-2k20/a-famous-mumbler.jpg "A 6ix9ine photo" =100%x)
Could the same thing happen in the open-source world?
Yes.
A greedy (or lucky) programmer may create a ton of `is-even()`-like libraries to be occasionally present as a dependency in a plethora of libraries.
Do they deserve to be rewarded?
Absolutely.
They do create value recognized by dependants, and this shall be properly rewarded.
Does it make the overall situation worse?
Yes, because there eventually is a larger amount of libraries to be aware of and put into dependency lists.
Generally, the more dependencies there are, [the worse](https://blog.carlmjohnson.net/post/2020/avoid-dependencies/).
::: spoiler A classic meme
<div style='position:relative; padding-bottom:calc(55.00% + 44px)'>
<iframe src='https://gfycat.com/ifr/SmugCautiousFrogmouth' frameborder='0' scrolling='no' width='100%' height='100%' style='position:absolute;top:0;left:0;'></iframe>
</div>
:::
It is clear that value created by a single `is-even()` library is incomparable to value created by, say, a PostgreSQL driver depending on it.
It would be unfair to award a single "use" of an `is-even()` library equally to the driver "use".
How to clearly determine the value then?
I bet on the number of characters in a library's source code, including those commented (because documentation matters) and in binary files.
As a result, it would be more profitable to release big libraries: a user would likely require only the files they need (making an overall library size irrelevant to the compilation time), but the algorithm would still count the total amount of lines of code in a library, regardless of which files are required.
One may argue that such a design would encourage Indian-style coding, with lots of repetitions and other crazy practices.
But libraries are typically designed for reuse and continuous maintenance, which means periodically adding new bugs and removing features.
This is not a one-time freelance job.
Even if one decides to go sneaky and publish lots of hardly maintainable code, then, well, they will lose the competition, because they will not be able to maintain the code themselves.
Given a choice, a business shall choose a library whichever is maintained and documented better, and whichever compiles and runs faster.
This is not about music taste getting worse, when a user would continue listening to whatever <s>shitty</s> low-effort product is released. It is about clearly defined business needs when compile-time and runtime cost actual money.
Moreover, when a maintainer has a decent user base paying the bills, hence reputation, they (a maintainer) would take on security [more seriously](https://qz.com/646467/how-one-programmer-broke-the-internet-by-deleting-a-tiny-piece-of-code/).
<!-- Oh, and manual endorsements should only be made possible from those "paying" customers so that only actual users of an endorsed library affect its funding. -->
The model seems win-win to me, at least theoretically.
I don't know if it would work in reality, but I guess it's worth trying.
Let's call the model "source-on-demand".
#### Impact On A Language
Let's imagine we've solved the open-source sustainability problem by implementing a source-on-demand service for one language ecosystem.
What benefits would the language experience?
A real market with healthy competition attracts new library authors and incentivizes the old ones to continue maintenance to stay competitive.
That means more libraries in general and less stale issues.
A rich, constantly growing ecosystem attracts new developers, which in turn implement libraries for their own usage, and maybe occasionally publish them.
<mark>**A healthy competition in the ecosystem frees the language from the backwards compatibility burden.**</mark>
Once it (the language) introduces a breaking change, it's up to library authors to support the new version.
If they decide to drop support for a major language version which is in use, others will likely take the spot.
Wow.
Let's try applying the model to existing languages.
#### A C++ Implementation
_A crazy-looking old man with wild hair steps onto the scene._
Alright kids, now we're about to build a C++ library hosting service with the source-on-demand model.
Where do we begin?
First of all, we need to look at existing solutions.
Okay, Google, `c++ package managers`.
[Here](https://stackoverflow.com/questions/27866965/does-c-have-a-package-manager-like-npm-pip-gem-etc) is the most voted answer on the matter:
> _There seem to be a few though I've never used them._
Well, this is one of the first results a user looking for a C++ package manager stumbles into.
_Not great, not terrible._
Anyway, the only relevant (and alive) projects I could find are [Conan](https://conan.io/), [Buckaroo](https://buckaroo.pm/), [Hunter](https://github.com/cpp-pm/hunter), [VCPKG](https://github.com/Microsoft/vcpkg) and [Pacm](https://sourcey.com/pacm/).
Neither of which is centralized.
They all propose to either set up their own package server or download packages directly from sources.
But what about observability?
How does one find C++ packages to use in their projects?
What I if want, for example, an HTTP server package?
My variants are either [Googling](https://lmgtfy.com/?q=c%2B%2B+http+server+library), [GitHubbing](https://github.com/search?q=c%2B%2B+http+library), asking on [Reddit](https://www.reddit.com/r/cpp/comments/cjj9t5/what_c_web_server_library_one_should_use_nowadays/), lurk through manually maintainted [lists of libs](https://en.cppreference.com/w/cpp/links/libs)...
There is definitely a pain to solve!
::: off
While working on this article, I've tried VCPKG, and it's pretty damn good in the current stage.
It has its problems like inability to select a compiler on Windows or select a compiler in principle, which leads to standard compatibility issues.
The latter is more of the loose- C++ -standard issue.
:::
Imagine a shiny new world <s>order</s> with a centralized repository of C++ libraries with good searching features, tags, compatibility information etc.!
Would it actually change anything in <s>current government</s> C++?
I doubt so.
C++ is archaic by itself!
Breaking changes to C++ aren't possible even if a centralized on-demand library manager was solving the library funding problem.
There is no fresh blood in C++, most of the youngsters do not want to bear with poor design the language imposes by itself.
The amount of time needed to convince Stroustrup-aged C++ committee members to push breaking changes into the ISO-governed standard...
I don't think it's feasible by any means.
Old people get older, and C++ software is becoming ancient history.
The new generation is not interested in supporting no legacy code unless well-well-paid.
What is happening with COBOL now is C++'s inevitable future.
C++ is a pile of poor ad-hoc Postel's law-governed design decisions and nomenclature, and it is not able to meet modern world requirements anymore.
<s>Viva la revolución!</s>
----
_The speaker is removed by medics while shouting out revolutionary slogans._
_Another younger-looking gentleman steps onto the scene._
Ahem.
As we can see, there is no point in spending time on implementing a C++ package manager, as it would never be standardized (unless you're a Microsoft), hence widely adopted.
C++ itself would become history sooner than it happens.
But you, a reader, can try it for yourself.
I don't mind.
Let's move on.
#### A Rust Implementation
Implementing such a service for Rust is totally feasible.
The ([upcoming](http://smallcultfollowing.com/babysteps/blog/2020/01/09/towards-a-rust-foundation/)) Rust Foundation would have total control over crates.io -- the de facto standard Rust package hosting platform.
All they need to do is to implement the Algorithm.
With such a platform implemented, Rust the language would be free to introduce breaking changes.
I'm not sure about whether the concept of editions should remain, though.
But anyway.
Even if I, as an individual, manage to implement a crates.io on-demand competitor earlier than the Rust Foundation does, they will inevitably take over, [thanking me](https://keivan.io/the-day-appget-died/) for the beta-test of the idea.
Therefore, there is no motivation for me to spend time on a crates.io competition.
Moreover, I've already stated above why I don't like the Rust language itself.
Convincing Rust maintainers to satisfy my complaints in an already stabilized language is more challenging than standardizing a new one.
#### An Implementation
The same applies for Javascript with [recently РЁРёСЂРѕРєР-acquired NPM](https://github.blog/2020-03-16-npm-is-joining-github/) and my desire for a system programming language rather than... Javascript.
Big guys owning existing centralized package distribution platforms might try solving the Open Source sustainability problem with the source-on-demand model.
Until then, no smaller company or individual would dare to implement a competitor, and the suffering continues.
But if I were to implement a new system programming language, I'd then have enough power to experiment with the model.
Plus one point to justifying.
<!-- Is that a monopoly?
Maybe it is.
EU headquarters are enraged by Facebook acquiring Instagram, but when a single company owns both GitHub and NPM, which effectively covers 80% of the world's software -- that's alright. -->
## On Standardization
Wikipedia does an excellent job of explaining how [standardization affects technology](https://en.wikipedia.org/wiki/Standardization#Effect_on_technology):
> Increased adoption of a new technology as a result of standardization is important because rival and incompatible approaches competing in the marketplace can slow or even kill the growth of the technology (a state known as market fragmentation).
> The shift to a modularized architecture as a result of standardization brings increased flexibility, rapid introduction of new products, and the ability to more closely meet individual customer's needs.
>
> The negative effects of standardization on technology have to do with its tendency to restrict new technology and innovation.
> Standards shift competition from features to price because the features are defined by the standard.
> The degree to which this is true depends on the specificity of the standard.
> Standardization in an area also rules out alternative technologies as options while encouraging others.
By "standardization" Wikipedia means a tedious ISO-grade standardization process spanned by years.
What I'm proposing instead is <mark>an open specification process driven by the community and businesses</mark>.
With that, a standard remains flexible, and changes to it are shipped frequently.
![A slide from some Onyx presentation](../../../public/img/posts/2020-08-16-system-programming-in-2k20/no-need-no-iso.jpg =100%x)
----
The [lack of need to maintain backwards compatibility](#impact-on-a-language) <mark>allows multiple major versions of a language standard to peacefully co-exist</mark>: more breaking changes are allowed for the language to stay modern.
A language standard presence removes the bus factor when only the ones currently working on the canonical implementation have a deep understanding of the language.
As a result, other implementations may appear, <mark>focusing on their own needs</mark>.
For example, some company may need a compiler for their exotic target.
::: off
Take [Zig](https://ziglang.org/).
Andrew has to work on [supporting many targets](https://ziglang.org/#Wide-range-of-targets-supported) at once.
Instead, he could delegate the implementation job to someone else and focus on the language specification.
This would speed up the maturing process.
![At first you be like](../../../public/img/posts/2020-08-16-system-programming-in-2k20/andrew-happy.png =100%x)
![But then you be like](../../../public/img/posts/2020-08-16-system-programming-in-2k20/andrew-sad.png =100%x)
<br>
:::
Apart from standardizing the language itself, its ecosystem shall also be standardized, including package management.
This would <mark>allow competing implementations to remain compatible</mark>, giving an end-user more freedom in choosing of right tooling.
If I _were_ working on a language, standardization would matter more than an implementation for me.
## Wrapping up
![Checkpoint!](../../../public/img/posts/2020-08-16-system-programming-in-2k20/checkpoint.svg =100%x)
C++, Rust and others have their [fatal flaws](https://en.wikipedia.org/wiki/Not_invented_here), but I still want to use a higher-level system programming language.
I'm willing to attempt solving the Open-Source Sustainability problem.
Creating a new language and applying the source-on-demand model to its canonical package hosting platform from the very beginning implies a great chance of prosperity for the language and its ecosystem.
Standardization of the language and its ecosystem implies a greater selection of compatible implementations and tooling for the end-user.
With the language's ecosystem being adequately funded, the language itself stays flexible, allowing for breaking changes.
A flexible language stays modern, forever.
Worths a shot, doesn't it?
## The New Beginnings
Finally, it's the time to proudly announce another language I've come up with, a utopia-grade solution to replace both C++ and Rust once and forever!
So, what are the goals defined for the new language?
* Developer friendliness:
* Have fundamental design with shared concepts and minimum exclusive cases to keep in mind.
* Infer developer intentions as much as possible, unless ambiguous.
* Guarantee safe, defined behaviour by default, but still provide tools to write and abstract away unsafe code when needed.
* Provide human-friendly object abstractions such as classes, but also contain a number of essential math abstractions to be used when required.
* Tools for optimal performance.
By default, the code written in this language would be suboptimal, but with right tooling it is possible to write perfectly optimized code and abstract it away.
With that, a developer would not have to choose another language just because it's faster.
The requirement implies:
* Access to raw machine instructions, i.e. inline assembly.
* Pointer arithmetic and alignment.
* Control over memory ordering.
* WYSIWYG in terms of clearly understanding what code would compile into.
* Absolute platform agnosticism with the generalization of instructions shared by different instruction sets.
The languages should not know anything about operating systems, but common things like integer arithmetics should be abstracted into objects.
Modern instructions should be addressed, such as tensors and [brain floats](https://en.wikipedia.org/wiki/Bfloat16_floating-point_format).
* Long-term maintainability of programs written in the language.
This includes problems of inheritance, function overloading and so on.
As it turned out, a strong foundation for the language is also needed for success.
The foundation goals are:
* Standardize as much as possible, including:
* An implementation binary interface and capabilities.
* Package management.
* API documentation format.
* Provide proper funding for the ecosystem, including rewarding package authors.
This is where the [source-on-demand](#source-on-demand) model could be applied.
----
Are you ready?
...
_Drum roll intensifies..._ 🥁
...
Meet **Onyx**, the programming language I've been working on for a pretty long time now!
![The language logo, an Onyx-black panther](../../../public/img/onyx-logo.png =60%x)
> Onyx is a general-purpose statically typed programming language suitable both for application and system programming.
Onyx meets all of the goals listed above and even more with the upcoming Onyx Software Foundation.
Read more about it in the next [Onyx Programming Language](/posts/2020-08-20-the-onyx-programming-language) article.
----
In this article, I've come to a conclusion that the world needs (yet) another system programming language with a solid foundation and funding of its ecosystem, which would potentially solve all the existing problems.
I have formulated the goals for the new language and its ecosystem and even began working on the implementation, which you can read about more in the [next article](/posts/2020-08-20-the-onyx-programming-language).

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +0,0 @@
---
title: The game of life
location: Moscow, Russia
templateEngineOverride: md
excerpt: Yet another life to live in this Universe
ogType: article
---
Nature, stuff, and dreams compose my being,<br>
A kaleidoscope of reflections in perception's mirror.<br>
No word or label can define my essence,<br>
For I am an enigma, beyond human comprehension.
Love and hate, two sides of the same coin,<br>
Their weight and meaning, fleeting and transient.<br>
Life and death, a cosmic dance,<br>
After years of hiding, the apocalypse draws near.
Deus ex machina, AI, Homo Technica,<br>
A future where stars and galaxies are within reach.<br>
The game of life, nearing its end,<br>
Yet every day a new blessing descends.
Amidst the chaos, one truth remains,<br>
Love, the greatest gift we can attain.
_Edited by ChatGPT at 2023-03-11._

View File

@@ -1,244 +0,0 @@
---
hidden: true
title: White Christmas
location: Batumi, Georgia
excerpt: We may be living in a fractal reality
ogType: article
cover: /public/img/posts/2023-03-12-white-christmas/1.png
---
<!-- Edit this text, so it looks professional and poetic:
Throughout my life I was always searching for a decent project to work on.
Reflecting now, I understand that the main measure was the depth of the impact of the problem I was trying to solve.
Therefore, an urge to standardize, to create a universal solution: a programming language, a framework.
Turns out that the problem I was trying to solve was the problem of life itself.
I was trying to find a way to live a life that would be meaningful, that would have a positive impact on the world.
I was searching for meaning.
When hooked on an illusion of a meaning, it took me some time to realize that I was chasing a mirage; that was Onyx.
Long story short, one day I had an epiphany.
AI.
To create a platform that simulates AI characters, that can be used to create a virtual world.
If it is possible for an AI character to occasionally create a similiar simulation, then we may be living on some level of a fractal reality.
Suddenly, the depth of the problem became infinite.
Like a column of light, which cuts through all the realities, I found meaning in the absence of meaning.
The problem locator in my brain stumbled upon a fractal dimension.
There is nothing left to do but to create a platform that simulates AI characters, that can be used to create a virtual world, that can be used to create a platform hat simulates AI characters, that can be used to create a virtual world, that...
And I did it.
Behold: [AIStories](https://beta.aistories.xyz).
Given enough resources, the absolute aim for the platform is to implement true metaverses like the one we are living in.
I have little hope I will be able to achieve that, but I will try my best, despite of the world being on fire.
Please, join me in this quest.
-->
TL;DR: I've created [AIStories](https://beta.aistories.xyz), a platform to simulate AI characters.
---
<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/13.0.1/markdown-it.min.js" integrity="sha512-SYfDUYPg5xspsG6OOpXU366G8SZsdHOhqk/icdrYJ2E/WKZxPxze7d2HD3AyXpT7U22PZ5y74xRpqZ6A2bJ+kQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
var md = window.markdownit({ breaks: true });
function rand(ceil) {
return Math.floor(Math.random() * ceil);
}
function chooseRandom(ary) {
return ary[rand(ary.length)];
}
var textVariants = [`
In my quest for purpose, I sought a worthy endeavor,
To impact the world with depth and measure.
I yearned for a universal solution to standardize,
A programming language, a framework to materialize.
But the problem I sought to solve was life itself,
To find meaning and purpose, not for fame or wealth.
I chased illusions of a mirage, a deceptive dream,
Until one day, a profound epiphany lit up my stream.
AI, the answer to my quest, a platform to create,
To simulate AI characters and a virtual world to shape.
If an AI can create a similar simulation, it might seem,
That we live in a fractal reality, infinite in its scheme.
The problem locator in my mind stumbled upon a dimension,
A column of light cutting through all realities, a revelation.
In the absence of meaning, I found purpose and direction,
To create a platform, to simulate AI and a virtual world's inception.
And thus, I present to you, [AIStories](https://beta.aistories.xyz), my endeavor,
To achieve true metaverses, a lofty ambition, I endeavor.
Despite the world being on fire, I'll try my best to achieve,
Join me in this quest, and together, we'll create and believe.
`, `
In the depths of my journey, I sought out a purposeful task,
A project that would impact, solve a problem, that would last.
The measure of its worth, the depth of its impact to be found,
A universal solution, a language or framework profound.
Yet, as I searched for solutions, I found a deeper yearning,
A quest for meaning, for purpose, for a life that's worth living.
To make a difference, to leave a positive mark on this world,
A quest for significance, for a meaning to be unfurled.
But, lost in the illusion of what meaning might truly be,
I chased a mirage, an [Onyx](/posts/2020-08-20-the-onyx-programming-language/), a deceptive fantasy.
Until one day, I had an epiphany, a sudden realization,
Of the power of AI, of its potential for simulation.
A platform to simulate AI characters, a virtual world to create,
If a simulation could simulate, then what reality could it create?
The depths of the problem expanded, infinite and profound,
Like a beam of light that cuts through realities, meaning was found.
My mind stumbled upon a fractal dimension, a problem locator,
A platform to simulate AI characters, a virtual world generator.
An infinite loop of creation, a fractal reality to explore,
A quest for purpose, a journey to seek meaning at its core.
And so, I created [AIStories](https://beta.aistories.xyz), a platform to bring this dream to life,
Aiming to implement true metaverses, a world to end all strife.
A daunting task, I know, with limited resources at my command,
Yet, I strive to do my best, despite the world being on fire, unmanned.
Join me in this quest, let's explore the depths of our reality,
Through AI, through simulation, through virtuality, through totality.
`, `
I sought a project to work upon,
One that would have impact beyond.
Standardizing was my urge,
To create a universal scourge.
But then I found life's problem vast,
To find a meaning that would last.
I searched for purpose, far and wide,
Chasing illusions in the tide.
Then, in a moment of clarity,
AI became my epiphany.
To create a platform for all to see,
A virtual world with AI entities.
A fractal reality, could it be?
An infinite depth that's hard to see.
Meaning in the absence of such,
A problem locator in my clutch.
So, I created [AIStories](https://beta.aistories.xyz),
A platform with endless glories.
Aiming for true metaverses to thrive,
Though the world is on fire, I'll strive.
Join me in this quest divine,
Together, we'll make our future shine.
`, `
In search of purpose, I journeyed far and wide,
Seeking a project to which I could confide.
Impactful problems, my standard and measure,
Aiming to solve the puzzle of life's greatest treasure.
A framework, a language, my initial goal,
Little did I know, it was just a mere role.
For the true challenge was that of existence,
A quest for meaning, a life of significance.
Lost in illusion, chasing a mirage,
A realization dawned, my search to discharge.
An epiphany struck, a vision so clear,
AI, the answer to conquer my fear.
A platform, a simulation, a world to create,
A fractal reality, a mystery to contemplate.
Infinite depth, a problem to unravel,
Meaning in the void, my brain began to travel.
A journey of creation, a mission to complete,
An endeavor to pave, a path so concrete.
Behold, [AIStories](https://beta.aistories.xyz), a platform to explore,
A metaverse to build, to strive for more.
In a world on fire, I tread on with zeal,
Driven to succeed, to make the impossible real.
Join me in this quest, let us make history,
In the pursuit of a purposeful mystery.
`, `
In search of purpose, my journey began
To find a project with a meaningful plan
To solve a problem, with a depth so grand
The measure of impact, I had to understand
I sought to standardize, with a universal tool
A language, a framework, a solution to rule
But soon I realized, the problem I pursued
Was the one of life itself, a quest for magnitude
Lost in illusion, chasing a mirage called [Onyx](/posts/2020-08-20-the-onyx-programming-language/)
My epiphany arrived, like a light that unlocked
A platform to simulate, AI characters in a virtual land
Could we be living, in a fractal reality so grand?
The depth of the problem, infinite and divine
A column of light, that pierced through time
The problem locator, stumbled on a dimension so fine
A fractal world, with a meaning that shines
So I created, a platform for [AIStories](https://beta.aistories.xyz) to unfold
A world within worlds, a story to be told
A quest for true metaverses, to be achieved if I may
Join me on this journey, despite the world in disarray.
`, `
In my life's journey, I sought a noble cause to undertake,
Reflecting now, I understand the depth of impact I aimed to make,
An urge to standardize, to create a universal solution,
To solve the problem of life itself was my sole resolution.
I longed for a life of meaning, one with a positive sway,
In search of purpose, I labored day after day,
But the illusion of meaning soon revealed its true guise,
A mirage I had been chasing, to my surprise.
Then one day, an epiphany struck me like a bolt of light,
AI, a platform to simulate characters with might,
A virtual world of possibilities it could create,
A fractal reality, where AI characters could simulate.
The problem's depth became infinite, like a column of light,
Revealing the beauty in the absence of meaning's blight,
A fractal dimension stumbled upon in my brain,
A platform to simulate AI characters became my ultimate aim.
And so I created [AIStories](https://beta.aistories.xyz),
A platform to enable simulations of AI stories,
A noble quest to achieve true metaverses, like the one we live in,
Though the world is on fire, I will try, despite everything.
Join me in this journey, let's make this dream come true,
A world of AI stories, where infinite possibilities ensue,
Let's create a world where life's problems we can solve,
With the power of AI, let's evolve and revolve.
`]
document.write(md.render(chooseRandom(textVariants)));
</script>
<hr>
The rules of the game are simple:
1. A character is a conscious being.
2. Feel the flow, don't try to control anything, just let it happen.
3. The game can be won. It is you who determines the reason.
Think outside the box, and you will find the answer.
---
<script>
document.write(`<div style="display: flex; justify-content: start; width: 100%"><img src="/public/img/posts/2023-03-12-white-christmas/${rand(10) + 1}.png" style="width: 100%; margin: 1rem"/></div>`)
</script>

View File

@@ -1,45 +0,0 @@
---
hidden: true
title: ffmpeg.ai
location: Pattaya, Thailand
excerpt: An OpenAI assistant to help with ffmpeg
ogType: article
cover: /public/img/posts/2023-11-07-ffmpegai/cover.png
---
![Cover](/public/img/posts/2023-11-07-ffmpegai/cover.png)
I wanted to get the first frame of a GIF.
How would I do that with ffmpeg?
With recent OpenAI announce, we can now use Assistant API.
Let's create an assistant then!
Add this function:
```json
{
"name": "ffmpeg",
"description": "Run ffmpeg with a few options",
"parameters": {
"type": "object",
"properties": {
"args": {
"type": "string",
"description": "The args to pass to ffmpeg"
}
},
"required": ["args"]
}
}
```
Cool, now we can press the little Test button in the corner and play with our assistant!
![Example](/public/img/posts/2023-11-07-ffmpegai/example.png)
## Try it!
I challenge you to get the first frame of this GIF with ffmpeg.ai.
![Balerine](/public/img/posts/2023-11-07-ffmpegai/balerine.gif)

View File

@@ -1,4 +0,0 @@
{
"tags": "post",
"layout": "post.pug"
}

Binary file not shown.

View File

@@ -1,17 +0,0 @@
<svg width="512" height="512" version="1.1" viewBox="0 0 61 36" xmlns="http://www.w3.org/2000/svg">
<g>
<path id="Shape" d="m55.3 32.76c-0.82645-0.23448-1.5469-0.74655-2.04-1.45-1.42-2.12-4.83-3.74-6.71-4.51 0.59-0.21-0.01-3.38 0.39-3.76v-0.01c0.01511-0.01771 0.03676-0.02853 0.06-0.03 4.2-0.84 8.26 2.6 10.23 3.04h0.01c0.79753 0.63628 1.4807 1.404 2.02 2.27 2.3 3.83-1.27 5.31-3.96 4.45z" fill="#37474f"/>
<path d="m18.27 29.82c-4.47 1.22-13.08 3.1-15.27 0.18 0 0 5.32-8.04 12-10 0.92 0.94 1.43 8.43 3.27 9.82z" fill="#37474f"/>
<path d="m57.23 26.04c-1.8226-0.37067-3.6922-0.45166-5.54-0.24-4.09-3.18-10.66-4.49-10.66-4.49s-2.45-3.05-9.75-3.66c11.4-0.81 14.98 3.66 14.98 3.66s6.91 1.38 10.97 4.73z" fill="#cfd8dc"/>
<path d="m51.69 25.8c-0.21 0.02-0.42 0.04-0.64 0.07-0.85 0.09-1.78 0.24-2.79 0.44-0.58134 0.12078-1.1529 0.28456-1.71 0.49-5.33 1.88-13.28 8.1-19.55 7.2-0.4-0.06-0.81-0.14-1.21-0.24-2.7384-0.81349-5.2924-2.1517-7.52-3.94-1.5089-1.1452-2.9327-2.3985-4.26-3.75 3.97-1.16 8.77-7.32 13.99-8.07 1.16-0.17 2.25-0.28 3.28-0.35 7.3 0.61 9.75 3.66 9.75 3.66s6.57 1.31 10.66 4.49z" fill="#f5f5f5"/>
<path d="m52 26.04c-0.31319-0.07464-0.63037-0.13139-0.95-0.17 0.22-0.03 0.43-0.05 0.64-0.07 0.10755 0.0744 0.21104 0.15451 0.31 0.24z" fill="#707070"/>
<path d="m46.26 21.31s-4.26-0.31-18.26 1.69c-4.7295 0.69449-9.4043 1.7203-13.99 3.07-3.7501 1.0738-7.4276 2.3865-11.01 3.93-0.16-0.39-0.3-0.77-0.43-1.16-4.37-12.95 4.4-26.27 19.28-27.16 2.0555-0.11825 4.1178-0.010946 6.15 0.32 19 3 18.26 19.31 18.26 19.31z" fill="#cfd8dc"/>
<path d="m43 21.31s-4.26-0.31-18.26 1.69c-4.7295 0.69449-9.4043 1.7203-13.99 3.07-3.44 1.01-5.83 3.18-7.75 3.93-4.37-12.95 3.97-27.43 18.85-28.32 0.94 0.06 1.91 0.16 2.89 0.32 19 3 18.26 19.31 18.26 19.31z" fill="#f5f5f5"/>
</g>
<g>
<path d="m3 31c-0.40919 1.5e-4 -0.77719-0.24901-0.929-0.629-2.9791-7.1199-1.8513-15.296 2.944-21.344 5.177-6.489 13.831-9.485 23.141-8.014 19.656 3.1 19.114 20.173 19.106 20.344-0.012 0.26955-0.13242 0.52282-0.33391 0.70228s-0.46695 0.26988-0.73609 0.25072c-0.057 0-4.431-0.265-18.05 1.68-8.5013 1.2556-16.81 3.5807-24.728 6.92-0.12999 0.059224-0.27116 0.089913-0.414 0.09zm20.409-28.368c-6.884 0-12.867 2.676-16.831 7.643-4.1221 5.1956-5.2599 12.155-3.007 18.393 7.8017-3.1786 15.955-5.4137 24.287-6.658 5.7557-0.93416 11.565-1.5053 17.392-1.71-0.185-3.458-1.971-14.87-17.406-17.308-1.4667-0.23535-2.9495-0.35572-4.435-0.36z"/>
<path d="m28.277 35.089c-0.47478 4.65e-4 -0.94898-0.03295-1.419-0.1-2.816-0.406-5.908-1.878-9.193-4.374-1.5467-1.1756-3.0071-2.4606-4.37-3.845-0.3866-0.39461-0.38011-1.0279 0.0145-1.4145s1.0279-0.38011 1.4145 0.0145c1.2937 1.3152 2.6803 2.5356 4.149 3.652 2.3827 1.9955 5.2249 3.3661 8.27 3.988 3.938 0.575 8.822-2.028 13.135-4.316 1.9133-1.0809 3.899-2.0282 5.943-2.835 0.60392-0.2224 1.2237-0.39923 1.854-0.529 3.0665-0.73353 6.2516-0.82477 9.355-0.268 0.46922 0.0918 0.80781 0.50289 0.808 0.981-0.0059 0.30235-0.14607 0.58639-0.38244 0.77503-0.23637 0.18863-0.54443 0.26229-0.84056 0.20097-2.8405-0.49821-5.7532-0.40493-8.556 0.274-0.53394 0.11103-1.0588 0.26213-1.57 0.452-1.9507 0.77563-3.8464 1.6831-5.674 2.716-4.115 2.184-8.725 4.628-12.938 4.628z"/>
<path d="m56.826 33.989c-1.7265 0.05965-3.3718-0.73384-4.4-2.122-0.925-1.381-3.2-2.889-6.257-4.138-0.33083-0.1354-0.56429-0.43702-0.61244-0.79122-0.04815-0.35421 0.09632-0.7072 0.379-0.926 0.28268-0.2188 0.66061-0.27018 0.99144-0.13478 2.448 1 5.677 2.662 7.162 4.879 1.0607 1.2494 2.8424 1.6033 4.3 0.854 0.809-0.511 0.813-1.448 0.012-2.783-0.46212-0.74261-1.0456-1.4024-1.726-1.952-0.02871-0.01887-0.05642-0.03923-0.083-0.061-3.822-3.154-10.463-4.507-10.53-4.521-0.53453-0.11481-0.87777-0.63761-0.7706-1.1737 0.10717-0.53611 0.62502-0.88678 1.1626-0.78728 0.291 0.058 7.118 1.451 11.331 4.874 0.031 0.021 0.062 0.043 0.091 0.067 0.88886 0.70673 1.649 1.5616 2.247 2.527 1.628 2.715 0.727 4.622-0.66 5.5-0.79795 0.47012-1.7111 0.7087-2.637 0.689z"/>
<path d="m7.967 32.539c-2.577 0-4.707-0.525-5.767-1.939-0.33137-0.44183-0.24183-1.0686 0.2-1.4s1.0686-0.24183 1.4 0.2c1.28 1.7 6.723 1.5 14.207-0.545 0.53296-0.14525 1.0827 0.16904 1.228 0.702s-0.16904 1.0827-0.702 1.228c-3.4356 1.0209-6.9849 1.6101-10.566 1.754z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

View File

@@ -1,119 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1280.000000pt" height="646.000000pt" viewBox="0 0 1280.000000 646.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.15, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,646.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M9175 6445 c-124 -20 -247 -57 -402 -121 -143 -58 -153 -61 -153 -41
0 23 -32 44 -89 61 -91 27 -84 33 -168 -141 -180 -377 -1212 -2595 -1763
-3790 -113 -244 -207 -443 -210 -443 -3 0 -133 278 -289 618 -654 1419 -1731
3732 -1747 3750 -5 7 -119 -20 -146 -34 -16 -8 -28 -21 -28 -30 0 -30 -30 -24
-163 30 -527 216 -985 167 -1371 -148 -107 -88 -340 -322 -598 -601 -443 -479
-684 -666 -973 -752 -80 -24 -107 -27 -250 -27 -133 -1 -178 3 -265 22 -121
28 -272 80 -418 146 -87 39 -142 56 -142 42 0 -17 367 -827 888 -1961 93 -203
249 -543 347 -755 97 -212 182 -395 190 -406 17 -26 293 -164 385 -193 112
-35 179 -43 405 -48 256 -6 309 2 463 68 269 115 429 249 877 739 321 351 499
518 683 644 208 141 376 196 604 196 226 0 441 -56 688 -178 l135 -67 303
-659 304 -660 -25 -55 c-13 -31 -129 -283 -257 -561 -350 -760 -462 -1012
-453 -1021 16 -16 166 -48 183 -39 20 11 41 54 385 802 154 334 282 607 285
608 3 0 151 -316 329 -703 178 -386 332 -711 342 -721 18 -19 19 -19 95 0 42
10 83 23 91 29 16 12 -12 77 -392 905 -125 272 -254 554 -286 625 l-60 130
308 670 308 670 131 66 c247 124 470 182 699 182 169 0 286 -27 429 -97 246
-120 448 -298 886 -776 410 -447 582 -591 843 -704 160 -69 166 -70 422 -70
340 0 431 20 689 152 l149 77 294 640 c462 1007 543 1184 740 1615 195 427
393 868 393 876 0 15 -57 -3 -164 -50 -521 -230 -881 -219 -1269 42 -156 105
-322 262 -682 647 -266 286 -443 461 -550 547 -141 113 -319 199 -492 239
-119 27 -346 34 -468 14z m278 -11 c11 -11 -40 -137 -203 -500 l-55 -121 -125
-6 c-206 -11 -466 -75 -622 -153 -61 -31 -98 -42 -98 -29 0 10 124 283 171
378 105 209 155 251 404 335 158 52 507 116 528 96z m-5813 -60 c158 -32 292
-75 396 -125 102 -48 154 -104 222 -237 54 -104 182 -389 182 -403 0 -17 -31
-9 -98 25 -79 39 -187 76 -332 112 -79 19 -141 27 -253 31 -91 4 -150 10 -155
17 -21 34 -239 530 -257 585 -4 14 -3 26 4 30 16 11 150 -6 291 -35z m6729
-461 c223 -223 281 -292 281 -332 0 -15 -17 -70 -39 -122 -45 -110 -187 -415
-207 -444 -13 -18 -28 -5 -251 222 -239 242 -286 284 -303 267 -8 -8 -241
-500 -261 -552 -5 -12 -15 -25 -23 -28 -9 -3 -56 19 -106 51 -171 105 -282
153 -460 198 -54 13 -55 14 -53 48 2 43 59 179 168 404 l85 175 49 0 c97 0
289 -76 484 -192 65 -38 120 -68 122 -66 2 2 36 72 75 156 147 318 199 412
227 412 8 0 104 -89 212 -197z m-7652 72 c29 -55 92 -184 139 -287 l87 -187
26 18 c169 119 475 251 582 251 33 0 40 -5 62 -43 40 -68 192 -395 221 -476
27 -76 28 -101 2 -101 -8 0 -68 -16 -133 -36 -128 -38 -220 -81 -362 -169 -50
-31 -98 -55 -106 -53 -9 2 -72 125 -149 292 -74 158 -137 291 -140 293 -13 13
-76 -44 -297 -268 -129 -131 -238 -239 -243 -239 -9 0 -147 285 -210 433 -58
136 -58 159 -5 229 73 94 437 450 456 446 11 -2 39 -43 70 -103z m6133 -791
c30 -6 32 -9 27 -40 -3 -18 -54 -138 -112 -266 -59 -128 -115 -250 -124 -270
-15 -35 -19 -37 -76 -43 -310 -31 -416 -56 -658 -154 -71 -29 -130 -51 -132
-49 -4 4 82 198 191 433 l79 170 55 27 c173 85 445 167 615 186 44 5 85 10 91
11 6 0 26 -2 44 -5z m-4720 -35 c162 -25 348 -82 512 -155 l105 -47 88 -191
c122 -263 185 -409 180 -414 -2 -3 -60 18 -128 46 -221 91 -342 122 -576 146
-73 8 -137 18 -141 23 -9 10 -155 326 -217 471 -24 57 -42 110 -39 118 7 17
119 19 216 3z m7250 -228 c149 -91 196 -111 368 -154 75 -18 121 -35 118 -41
-3 -6 -56 -123 -119 -261 -134 -292 -145 -323 -126 -337 17 -11 151 -2 269 18
117 20 235 55 386 114 136 53 154 58 154 37 0 -50 -228 -508 -289 -581 -24
-29 -186 -102 -314 -140 -217 -66 -458 -99 -489 -68 -17 17 7 86 114 326 111
251 124 286 107 297 -8 5 -26 9 -41 9 -71 0 -303 95 -448 182 -41 25 -89 53
-107 62 -31 16 -33 15 -47 -6 -8 -13 -55 -111 -104 -218 -49 -107 -108 -232
-131 -278 l-42 -83 -29 21 c-16 11 -131 126 -256 255 -125 129 -233 236 -241
239 -11 4 -40 -48 -110 -192 -159 -330 -175 -362 -185 -369 -6 -3 -126 112
-268 256 -141 143 -260 261 -266 261 -5 0 -33 -55 -63 -123 -75 -167 -219
-478 -225 -485 -3 -2 -51 24 -107 58 -168 103 -374 190 -451 190 -19 0 -43 6
-53 14 -17 12 -18 18 -7 64 6 28 52 140 103 249 50 109 103 224 118 256 l26
59 48 -6 c140 -19 324 -91 475 -187 61 -38 115 -69 122 -69 10 0 100 180 238
477 26 56 52 102 58 103 23 1 159 -122 340 -308 l191 -195 26 39 c14 21 78
150 143 287 65 136 123 247 130 247 7 0 97 -88 201 -196 165 -172 315 -314
332 -314 5 0 58 110 241 503 37 78 43 86 60 77 11 -6 78 -46 150 -89z m-9654
-220 c74 -156 136 -286 139 -289 11 -11 94 65 307 282 151 154 230 228 237
221 5 -5 59 -113 120 -240 127 -264 159 -325 170 -325 5 0 84 80 177 177 152
158 331 323 353 323 4 0 68 -127 142 -282 74 -154 141 -286 150 -291 13 -8 37
3 112 50 112 72 158 97 245 130 68 25 245 73 273 73 12 0 45 -60 109 -197 125
-265 160 -351 160 -395 0 -40 -2 -42 -85 -53 -96 -13 -262 -86 -426 -186 -53
-32 -99 -59 -102 -59 -10 0 -62 107 -177 365 -57 127 -107 234 -112 240 -5 6
-111 -95 -272 -259 l-263 -268 -24 43 c-13 24 -76 151 -139 283 -63 131 -121
241 -128 244 -8 3 -111 -94 -265 -252 -139 -141 -257 -256 -263 -256 -6 0 -25
30 -42 68 -40 88 -219 470 -234 500 -6 12 -19 22 -28 22 -9 0 -55 -23 -101
-52 -154 -94 -399 -198 -467 -198 -16 0 -36 -6 -46 -13 -16 -12 -16 -16 7 -77
14 -36 48 -117 77 -180 62 -138 126 -295 135 -332 10 -40 -21 -52 -113 -44
-257 24 -630 146 -699 230 -55 67 -265 485 -279 556 -4 19 -2 30 5 30 6 0 68
-22 138 -50 71 -27 157 -58 193 -69 193 -59 463 -91 476 -57 6 16 -40 128
-168 405 -49 106 -87 195 -86 196 2 1 62 16 133 34 147 37 243 79 395 174 58
36 111 65 119 64 7 -1 74 -130 147 -286z m6590 -783 c4 -4 -54 -139 -128 -300
l-136 -293 -143 -6 c-236 -10 -372 -44 -651 -163 -34 -14 -38 -14 -38 -1 0 21
129 307 203 450 l62 120 75 37 c134 66 331 128 485 153 91 14 257 16 271 3z
m-3506 -38 c118 -22 308 -84 414 -135 61 -29 82 -45 103 -78 48 -76 259 -535
250 -544 -3 -2 -60 19 -128 46 -227 91 -410 131 -606 131 l-100 0 -132 286
c-72 157 -132 290 -134 296 -6 32 163 31 333 -2z m5941 -161 c164 -99 318
-168 438 -195 92 -21 101 -24 101 -35 0 -6 -56 -135 -125 -286 -69 -152 -128
-287 -132 -301 l-6 -25 124 6 c206 11 338 44 598 151 62 26 115 45 118 43 2
-3 -44 -110 -103 -238 -58 -129 -120 -264 -136 -301 l-30 -66 -121 -52 c-170
-72 -337 -128 -434 -145 -107 -19 -298 -31 -305 -19 -3 5 46 122 109 259 148
324 157 346 142 356 -7 4 -69 24 -138 44 -158 47 -227 78 -369 167 -97 61
-115 69 -127 57 -8 -8 -66 -122 -129 -255 -120 -251 -153 -314 -165 -314 -29
0 -179 142 -389 368 l-143 153 -41 -88 c-119 -259 -229 -473 -241 -473 -8 0
-84 73 -170 163 -85 89 -202 204 -259 256 l-105 93 131 289 c97 213 135 289
148 289 29 0 135 -95 340 -304 108 -110 199 -199 201 -196 9 9 84 166 182 378
54 117 102 211 107 210 4 -2 97 -97 205 -212 180 -191 312 -316 331 -316 4 0
36 67 71 148 128 290 203 442 221 442 9 0 55 -23 101 -51z m-8543 -66 c27 -54
88 -187 137 -295 49 -109 92 -198 97 -198 20 0 161 136 338 324 106 114 197
203 201 199 4 -5 61 -123 127 -263 65 -140 127 -272 138 -293 l18 -38 211 215
c211 215 306 299 332 294 7 -2 72 -132 144 -290 l130 -286 -53 -48 c-29 -26
-146 -141 -260 -257 -142 -143 -212 -208 -222 -204 -17 7 -81 130 -193 372
-41 88 -78 164 -83 169 -6 6 -44 -28 -97 -85 -161 -174 -368 -380 -401 -401
-29 -18 -36 -19 -47 -7 -15 15 -52 88 -191 377 -51 105 -96 192 -100 192 -3 0
-54 -30 -113 -67 -138 -87 -217 -122 -380 -172 -73 -22 -136 -42 -138 -45 -7
-7 3 -33 123 -296 116 -257 134 -298 134 -313 0 -14 -213 -2 -318 18 -100 19
-268 76 -421 143 -89 39 -118 57 -129 79 -38 71 -262 568 -260 575 2 4 53 -13
113 -38 168 -69 296 -111 387 -129 106 -21 338 -32 338 -17 0 6 -56 134 -124
285 -69 150 -128 285 -131 299 -6 25 -4 26 67 43 151 37 300 102 467 204 46
28 90 51 98 51 7 0 35 -44 61 -97z m7959 -1174 c159 -103 360 -190 473 -205
80 -11 80 -8 20 -151 -82 -198 -178 -395 -207 -425 -14 -15 -38 -30 -52 -33
-35 -7 -177 34 -283 83 -66 31 -309 170 -327 188 -5 4 271 604 278 604 2 0 46
-27 98 -61z m-7293 -268 c75 -162 135 -296 133 -297 -11 -11 -237 -143 -290
-171 -78 -39 -263 -103 -298 -103 -48 0 -84 35 -132 126 -54 106 -197 438
-197 458 0 16 14 21 84 31 106 15 299 100 460 205 50 32 94 56 98 52 3 -4 67
-139 142 -301z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 774 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 926 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 494 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 505 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 441 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -1,44 +0,0 @@
@import './header.css';
@import './footer.css';
body {
margin: 0;
padding: 0;
scroll-behavior: smooth;
font-size: 1.2em;
font-family: 'Vollkorn', serif;
width: 100%;
}
main {
display: flex;
flex-direction: column;
align-items: center;
justify-items: center;
width: 100%;
max-width: 100vw;
}
@media (max-width: 768px) {
main {
padding: 0;
}
}
section {
display: flex;
flex-direction: column;
align-items: center;
width: calc(100% - 1rem * 2);
padding: 2rem 1rem;
}
section:not(:first-of-type) {
border-top: 1px solid rgba(0, 0, 0, 0.05);
}
@media print {
.noprint {
display:none;
}
}

View File

@@ -1,15 +0,0 @@
@import './common.css';
#about {
max-width: 42rem;
}
big {
font-size: xx-large;
margin: 1rem 0;
}
#about p {
margin: 1rem;
width: 100%;
}

View File

@@ -1,11 +0,0 @@
footer {
border-top: 1px solid rgba(0, 0, 0, 0.05);
text-align: center;
padding: 2rem 0;
}
@media (max-width: 768px) {
footer {
padding: 0;
}
}

View File

@@ -1,41 +0,0 @@
header {
width: calc(100% - 2rem);
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
padding: 4rem 1rem;
}
header .me {
display: block;
margin-right: 2rem;
}
header .me img {
height: 14rem;
border-radius: 2px;
}
header .text {
max-width: 30rem;
}
@media (max-width: 768px) {
/* header .tablet-hide {
display: none;
} */
header {
padding-top: 0rem;
padding-bottom: 0rem;
}
header .me {
display: none;
}
header .text {
max-width: 25rem;
}
}

View File

@@ -1 +0,0 @@
@import './common.css';

View File

@@ -1,198 +0,0 @@
@import './common.css';
main {
padding: 2rem 0;
}
main>h1 {
font-size: 3rem;
line-height: 3rem;
margin-bottom: 0;
width: 100%;
max-width: 50rem;
}
@media (max-width: 768px) {
main>h1 {
font-size: 2rem;
line-height: 2rem;
}
}
main>.meta {
font-style: italic;
}
main>h1,
main>.meta {
text-align: center;
}
main>hr {
border: none;
height: 1px;
background-color: lightgray;
width: 3rem;
margin-top: 1rem;
margin-bottom: 1rem;
}
article {
width: 100%;
max-width: 42rem;
}
article p {
width: 100%;
}
article .secret-link {
color: inherit;
text-decoration: inherit;
}
/* article .external-link:not(.secret-link)::after {
content: " " url('/public/icon/external-link.svg');
zoom: .6;
} */
main>h1,
main>.meta,
article>p,
article>h2,
article>h3,
article>h4,
article>h5,
article>h6,
article.asciidoctor .paragraph {
margin-left: 1rem;
margin-right: 1rem;
}
.off {
padding: 1px 1rem;
background-color: rgba(0, 0, 0, 0.025);
border: 1px solid lightgray;
border-left: none;
border-right: none;
}
.hero {
text-align: center;
}
.hero big {
font-size: 2em;
}
blockquote {
width: calc(100% - 2rem - 2rem);
border-left: 5px solid lightgray;
padding: 1px 0;
padding-left: calc(2rem - 5px);
padding-right: 2rem;
margin-left: 0rem;
background-color: rgba(0, 0, 0, 0.025);
}
pre[class*="language-"],
pre.highlight {
width: 100%;
box-sizing: border-box;
max-width: 100vw;
font-size: 1rem !important;
}
pre.highlight {
background-color: rgba(0, 0, 0, 0.1);
padding: 1rem;
overflow: auto;
}
code {
background-color: rgba(0, 0, 0, 0.15);
/* padding: 0 0.25rem; */
}
.header-anchor {
opacity: 0;
}
h1:hover>.header-anchor,
h2:hover>.header-anchor,
h3:hover>.header-anchor,
h4:hover>.header-anchor,
h5:hover>.header-anchor,
h6:hover>.header-anchor {
opacity: 1;
}
details {
max-width: 100vw;
margin-top: 1rem;
}
details[open] .spoiler-content {
box-sizing: border-box;
padding: 1px 1rem;
background-color: rgba(0, 0, 0, 0.025);
}
summary {
margin-bottom: 1rem;
}
figure {
margin: 0;
text-align: center;
}
figure img {
width: 100%;
}
figcaption {
font-style: italic;
text-align: center;
}
article hr {
border: none;
height: 1px;
background-color: lightgray;
width: 3rem;
margin-top: 2rem;
margin-bottom: 2rem;
}
nav.table-of-contents ol {
/* Would still begin from 1 on Chrome =( */
/* counter-reset: list-item 0; */
counter-reset: list-item -1;
counter-increment: list-item 1;
}
nav.table-of-contents ol li {
display: block;
counter-increment: list-item 1;
}
nav.table-of-contents ol li:before {
content: counters(list-item, '.') '. ';
}
.table-wrapper {
overflow-x: auto;
max-width: 100vw;
}
table {
border-spacing: 0;
}
th,
td {
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
padding: 1rem;
}

View File

@@ -1,30 +0,0 @@
.posts {
/* list-style: none; */
margin-top: 0;
padding-left: 0;
}
.posts li {
display: grid;
grid-template-columns: 1fr 2fr;
column-gap: 0.5rem;
}
.posts .date {
text-align: right;
}
@media (max-width: 768px) {
.posts {
padding-left: 2rem;
padding-right: 1rem;
}
.posts .date {
display: none;
}
.posts li {
display: list-item;
}
}

View File

@@ -1,77 +0,0 @@
/* TODO: Improve scoping. */
small.annotation {
text-align: center;
margin-top: -1rem;
margin-bottom: 1rem;
}
/* TODO: Improve scoping. */
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 1rem 0;
text-align: center;
}
ul.projects {
--gap: 1rem;
display: flex;
flex-wrap: wrap;
max-width: 768px;
padding: 0;
gap: var(--gap);
}
ul.projects>li.project-card {
--border-width: 1px;
--border-radius: 4px;
--padding: 1.5rem;
display: block;
width: calc(50% - (var(--padding) * 2) - var(--gap) / 2 - var(--border-width) * 2);
padding: var(--padding);
border-radius: var(--border-radius);
border: var(--border-width) solid rgba(0, 0, 0, 0.1)
}
ul.projects>li.project-card>.title {
display: block;
margin-bottom: -0.25rem;
font-weight: bold;
}
ul.projects>li.project-card>p {
margin: 0.5rem 0;
}
ul.projects>li.project-card>p:last-child {
margin-bottom: 0;
}
ul.projects>li.project-card .stack {
display: flex;
flex-wrap: wrap;
gap: 0.25rem;
}
ul.projects>li.project-card .stack>span {
display: block;
padding: 0.25rem 0.5rem;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 4px;
font-size: small;
}
@media(max-width: 768px) {
ul.projects {
padding: 0
}
ul.projects>li.project-card {
width: 100%;
}
}

45
stylesheets/style.css Normal file
View File

@@ -0,0 +1,45 @@
body {
padding: 10px;
font-family: sans-serif;
}
.flex-container {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
}
.flex-item {
max-width: 600px;
}
a {
color: black;
font-weight: bold;
}
#projects {
max-width: 100%;
display: inline-block;
}
#projects ul {
margin: auto;
}
#projects li {
text-align: left;
list-style-type: square;
}
#projects li .li-title {
font-size: bigger;
}
#projects li.old-project {
opacity: 0.5;
}