Compare commits
55 Commits
developmen
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| df14c99ed5 | |||
| e5949f66e6 | |||
| 51ae296fcc | |||
| 93f32332d2 | |||
| b0a5196e97 | |||
| e2dde6b201 | |||
| b63b71b690 | |||
| f4d535ab0a | |||
| 53128b34ac | |||
| a1300836f4 | |||
| 3238b87b8a | |||
| 8cd08302d5 | |||
|
|
da91f1694a | ||
|
|
3d9a15a633 | ||
|
|
2700706a26 | ||
| 1c2778f0be | |||
| 60c65cb530 | |||
| 63d939666a | |||
| 298c245f50 | |||
| 35cb5b825a | |||
| 4f4e7ad207 | |||
| 4eed7e6ed4 | |||
| 10812eabe1 | |||
| 0b2c6ef680 | |||
| 450e6a72f0 | |||
| ff4f7d4be0 | |||
| 5b0c5cb15d | |||
| 2eb1abd40d | |||
| 00540ac18f | |||
| 2b61407d14 | |||
| ca645d4a47 | |||
| b6e7ea3563 | |||
| 331075dfd2 | |||
| 7ab446a1a2 | |||
| 1ea530da6e | |||
| 4b20168bbb | |||
| e8f63a6fde | |||
| 11bfe701b1 | |||
| 900a7636ef | |||
| 0caf515bf0 | |||
| 576cf836ac | |||
| 49d585e9d3 | |||
| 21e4063af2 | |||
| 88ecac076a | |||
| a2cdcb97c2 | |||
| 9f6c4b5ccd | |||
| fc446a2db5 | |||
| 5b081fb4b5 | |||
| 97d91e9d08 | |||
| 025f98f38c | |||
| 651654bbc5 | |||
| f54a5738ec | |||
| 5cdcd4193d | |||
| 9569deed42 | |||
| 3f59d8582c |
61
.github/workflows/static.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# 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
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
footer
|
footer
|
||||||
p Vlad Faust © 2020
|
p Vlad Faust © 2016-2023
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ meta(charset='UTF-8')
|
|||||||
meta(name='viewport', content='width=device-width, initial-scale=1.0')
|
meta(name='viewport', content='width=device-width, initial-scale=1.0')
|
||||||
|
|
||||||
<!-- Basics -->
|
<!-- Basics -->
|
||||||
title= title ? (titleNoAppend ? title : (title + " | Vlad Faust Blog")) : "Vlad Faust Blog"
|
title= title ? (titleNoAppend ? title : (title + " - Vlad Faust Blog")) : "Vlad Faust Blog"
|
||||||
meta(name='description', content=description || excerpt)
|
meta(name='description', content=description || excerpt)
|
||||||
meta(name='robots' content="index,follow")
|
meta(name='robots' content="index,follow")
|
||||||
meta(name='generator' content='Eleventy')
|
meta(name='generator' content='Eleventy')
|
||||||
|
|||||||
@@ -7,12 +7,16 @@ header
|
|||||||
a(href='/') Vlad Faust
|
a(href='/') Vlad Faust
|
||||||
| .
|
| .
|
||||||
p.tablet-hide
|
p.tablet-hide
|
||||||
| I'm a passionate developer currently working on
|
| I am a jack of anything IT, master of some; see my
|
||||||
a(href='/posts/2020-08-20-the-onyx-programming-language') my own programming language
|
a(href='/cv') CV
|
||||||
| .
|
| .
|
||||||
p.tablet-hide
|
p.tablet-hide
|
||||||
| You can follow me on
|
| You can contact me via
|
||||||
a(href='https://twitter.com/vladfaust') Twitter
|
a(href='https://x.com/vladfaust') 𝕏
|
||||||
| and
|
| ,
|
||||||
a(href='https://github.com/vladfaust') GitHub
|
a(href='https://github.com/vladfaust') GitHub
|
||||||
| and also send nudes to mail at vladfaust.com
|
| or
|
||||||
|
a(href='https://t.me/vladfaust') Telegram
|
||||||
|
| , or e-mail me directly at
|
||||||
|
i hey at vladfaust.com
|
||||||
|
| .
|
||||||
|
|||||||
22
_includes/note.pug
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
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
|
||||||
|
| ,
|
||||||
|
= location
|
||||||
|
hr
|
||||||
|
article(class=(asciiDoctor ? "asciidoctor" : ""))!= content
|
||||||
|
|
||||||
|
include /footer.pug
|
||||||
5
_includes/posts.pug
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
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
|
||||||
433
_includes/projects.pug
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
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
|
||||||
|
a(href="https://github.com/onyxframework/http") HTTP
|
||||||
|
| ,
|
||||||
|
a(href="https://github.com/onyxframework/sql") SQL ORM
|
||||||
|
| and
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
---
|
||||||
|
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,
|
||||||
|
a(href="https://wc3modding.info/pages/vjass-documentation/" target="_blank") vJass
|
||||||
|
| , cJass, C, C++, Java, git,
|
||||||
|
a(href="https://libgdx.com/" target="_blank") LibGDX
|
||||||
|
| , PHP,
|
||||||
|
a(href="https://unity.com/" target="_blank") Unity
|
||||||
|
| , C#, Ruby, Telegram,
|
||||||
|
a(href="https://www.heroku.com/" target="_blank") Heroku
|
||||||
|
| ,
|
||||||
|
a(href="https://dokku.com/" target="_blank") Dokku
|
||||||
|
| , SQLite, PostgreSQL, Redis, Docker, JavaScript, Gulp, Grunt, Ruby On Rails,
|
||||||
|
a(href="https://hanamirb.org/" target="_blank") Hanami
|
||||||
|
| ,
|
||||||
|
a(href="https://roda.jeremyevans.net/" target="_blank") Roda
|
||||||
|
| ,
|
||||||
|
a(href="https://sequel.jeremyevans.net/" target="_blank") Sequel
|
||||||
|
| ,
|
||||||
|
a(href="https://crystal-lang.org/" target="_blank") Crystal
|
||||||
|
| , LLVM, Kubernetes,
|
||||||
|
a(href="https://firecracker-microvm.github.io/" target="_blank") Firecracker
|
||||||
|
| ,
|
||||||
|
a(href="http://www.tinycorelinux.net/" target="_blank") Tiny Core Linux
|
||||||
|
| ,
|
||||||
|
a(href="https://buildpacks.io/" target="_blank") buildpacks.io
|
||||||
|
| , compiler development, machine learning,
|
||||||
|
a(href="https://www.tensorflow.org/" target="_blank") Tensorflow
|
||||||
|
| , VueJS, TypeScript,
|
||||||
|
a(href="https://deno.land/" target="_blank") Deno
|
||||||
|
| ,
|
||||||
|
a(href="https://ziglang.org/" target="_blank") Zig
|
||||||
|
| ,
|
||||||
|
a(href="https://en.wikipedia.org/wiki/Parsing_expression_grammar" target="_blank") PEG
|
||||||
|
| , Rust, EVM, Solidity,
|
||||||
|
a(href="https://substrate.io/" target="_blank") Substrate
|
||||||
|
| ,
|
||||||
|
a(href="https://ipfs.io") IPFS
|
||||||
|
| ,
|
||||||
|
a(href="https://en.wikipedia.org/wiki/Zero-knowledge_proof") ZKP
|
||||||
|
| , ChatGPT, llama.cpp, Godot,
|
||||||
|
a(href="https://trpc.io/docs/subscriptions") tRPC
|
||||||
|
| ,
|
||||||
|
a(href="https://zod.dev") Zod
|
||||||
|
| ,
|
||||||
|
a(href="https://tanstack.com/") Tanstack
|
||||||
|
| ...
|
||||||
|
ul.history(style="align-self: start;")
|
||||||
|
li
|
||||||
|
b 2013:
|
||||||
|
|
|
||||||
|
| It all began with Warcraft®️ III™️ maps, such as
|
||||||
|
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:
|
||||||
|
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
|
||||||
|
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
|
||||||
48
gulpfile.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
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)
|
||||||
24
index.pug
@@ -1,11 +1,8 @@
|
|||||||
---
|
---
|
||||||
eleventyExcludeFromCollections: true
|
eleventyExcludeFromCollections: true
|
||||||
pagination:
|
title: "Vlad Faust"
|
||||||
data: collections.all
|
|
||||||
size: 2
|
|
||||||
title: "Vlad Faust Blog"
|
|
||||||
titleNoAppend: true
|
titleNoAppend: true
|
||||||
description: "Vlad Faust's personal blog"
|
description: "My personal website"
|
||||||
cover: /public/img/me.jpg
|
cover: /public/img/me.jpg
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -15,16 +12,19 @@ html(lang='en')
|
|||||||
include /head.pug
|
include /head.pug
|
||||||
|
|
||||||
//- Styles
|
//- Styles
|
||||||
link(rel='stylesheet', href='/public/styles/index.css')
|
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
|
body
|
||||||
include /header.pug
|
include /header.pug
|
||||||
|
|
||||||
main
|
main
|
||||||
h2 Recent posts
|
section#posts
|
||||||
ul.posts
|
h2 Recent blog posts
|
||||||
each post in collections.all.reverse().filter((post) => !post.data.hidden)
|
include /posts.pug
|
||||||
li
|
|
||||||
span.date= post.date.toDateString()
|
section#projects
|
||||||
a.title(href=post.url)= post.data.title
|
h2 Project list
|
||||||
|
include /projects.pug
|
||||||
|
|
||||||
include /footer.pug
|
include /footer.pug
|
||||||
|
|||||||
10
package.json
@@ -6,8 +6,8 @@
|
|||||||
"private": "true",
|
"private": "true",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"debug": "DEBUG=* npx @11ty/eleventy",
|
"debug": "DEBUG=* npx @11ty/eleventy",
|
||||||
"dev": "npx @11ty/eleventy --serve",
|
"dev": "npx concurrently \"npx gulp\" \"npx @11ty/eleventy --serve --port 8082\"",
|
||||||
"build": "npx @11ty/eleventy"
|
"build": "npx gulp processAdoc && npx @11ty/eleventy"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Vlad Faust <mail@vladfaust.com>",
|
"author": "Vlad Faust <mail@vladfaust.com>",
|
||||||
@@ -15,6 +15,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@11ty/eleventy": "^0.11.0",
|
"@11ty/eleventy": "^0.11.0",
|
||||||
"@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1",
|
"@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-anchor": "^5.3.0",
|
||||||
"markdown-it-attrs": "^3.0.3",
|
"markdown-it-attrs": "^3.0.3",
|
||||||
"markdown-it-container": "^3.0.0",
|
"markdown-it-container": "^3.0.0",
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ Throughout the next two years, I've developed a number of very useful shards:
|
|||||||
* [Migrate](https://github.com/vladfaust/migrate.cr)
|
* [Migrate](https://github.com/vladfaust/migrate.cr)
|
||||||
* [Stripe](https://github.com/vladfaust/stripe.cr)
|
* [Stripe](https://github.com/vladfaust/stripe.cr)
|
||||||
|
|
||||||
I even managed to build my [own web framework](https://onyxframework.org/) featuring a [REST server](https://onyxframework.org/http), a database-agnostic [SQL ORM](https://onyxframework.org/sql) and even an [EDA platform](https://onyxframework.org/eda)!
|
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.
|
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.
|
Unfortunately <s>for Crystal</s>, I've left the Crystal ecosystem, because this is not the language I've always dreamt of.
|
||||||
@@ -72,6 +72,7 @@ I invite you all to follow me on this journey.
|
|||||||
Apart from programming, I used to enjoy heavy-lifting in a local gym.
|
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.
|
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!
|
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.
|
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}.
|
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}.
|
||||||
@@ -99,7 +100,6 @@ On my 24^th^ birthday, I've recorded a [video](https://www.youtube.com/watch?v=q
|
|||||||
----
|
----
|
||||||
|
|
||||||
I think that's enough for an introductory post.
|
I think that's enough for an introductory post.
|
||||||
Now you know a little bit more about yourself.
|
Now you know a little bit more about yours truly.
|
||||||
|
|
||||||
See you around,<br>
|
See you around,<br>
|
||||||
Vlad.
|
|
||||||
|
|||||||
@@ -280,11 +280,19 @@ Well, more on that later.
|
|||||||
|
|
||||||
#### Nim
|
#### Nim
|
||||||
|
|
||||||
[Nim](https://nim-lang.org/) is a magnificent piece of art.
|
[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.
|
||||||
|
|
||||||
But it has a Python-like indentation-based syntax with less flexible `import` semantics.
|
In addition to that,
|
||||||
It lacks proper object-oriented features like interfaces and mixins.
|
|
||||||
And it does not have lower-level features like pointer arithmetics, address spaces etc.
|
* 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
|
#### Crystal
|
||||||
|
|
||||||
@@ -403,7 +411,7 @@ I used to maintain a [number](https://github.com/vladfaust?tab=repositories&q=&t
|
|||||||
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 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.
|
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.org), a web framework comprised of a REST server, a database-agnostic SQL ORM and even EDA facilities.
|
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.
|
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.
|
Objectively, it is more user-friendly, a better balanced between features and usability, than alternatives.
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
title: The Onyx Programming Language
|
title: The Onyx Programming Language
|
||||||
location: Moscow, Russia
|
location: Moscow, Russia
|
||||||
templateEngineOverride: md
|
templateEngineOverride: md
|
||||||
excerpt: System programming seems to be much harder than application programming. Why is that and how to overcome this?
|
excerpt: In the previous article I successfully justified my desire to build yet another system programming language. Unlike others, I want to do it right from the very beginning.
|
||||||
cover: /public/img/onyx-logo-white-background.png
|
cover: /public/img/onyx-logo-white-background.png
|
||||||
ogType: article
|
ogType: article
|
||||||
---
|
---
|
||||||
@@ -51,7 +51,7 @@ Instead of fighting with a borrow checker, simply get an address of a variable:
|
|||||||
|
|
||||||
Classes may have a finalizer defined and thus have **automatic resource control**.
|
Classes may have a finalizer defined and thus have **automatic resource control**.
|
||||||
|
|
||||||
Onyx implements real **traits** as [composable units of behaviour](https://en.wikipedia.org/wiki/Trait_(computer_programming)) thanks to powerful function management tools like aliasing, implementation transferring, un-declaring and renaming.
|
Onyx implements real **traits** as [composable units of behaviour](<https://en.wikipedia.org/wiki/Trait_(computer_programming)>) thanks to powerful function management tools like aliasing, implementation transferring, un-declaring and renaming.
|
||||||
|
|
||||||
Classes and traits together impose **object-oriented** capabilities of the language.
|
Classes and traits together impose **object-oriented** capabilities of the language.
|
||||||
|
|
||||||
@@ -348,7 +348,7 @@ export int main () {
|
|||||||
|
|
||||||
server.listen("localost", 3000)
|
server.listen("localost", 3000)
|
||||||
catch |e|
|
catch |e|
|
||||||
Std.puts("Caught \@{{ e }}\n")
|
Std.puts("Caught \@{{ e }}\n")
|
||||||
|
|
||||||
while final loc = backtrace.pop?()
|
while final loc = backtrace.pop?()
|
||||||
Std.cout << "At " <<
|
Std.cout << "At " <<
|
||||||
@@ -367,7 +367,7 @@ export int main () {
|
|||||||
|
|
||||||
Thanks to powerful abstractions and type inference, you won't need to manually use `socket` each time you want to spin up a web server on Linux!
|
Thanks to powerful abstractions and type inference, you won't need to manually use `socket` each time you want to spin up a web server on Linux!
|
||||||
|
|
||||||
Oh, by the way, did you notice the `\@{{ e }}` thing?
|
Oh, by the way, did you notice the `\@{{ e }}` thing?
|
||||||
It was me, <s>Dio</s> macro!
|
It was me, <s>Dio</s> macro!
|
||||||
|
|
||||||
### Macros
|
### Macros
|
||||||
@@ -382,9 +382,9 @@ Let's examine a straightforward macro example.
|
|||||||
import "stdio.h"
|
import "stdio.h"
|
||||||
|
|
||||||
export void main() {
|
export void main() {
|
||||||
{% for i = 0, 2 do %}
|
{% for i = 0, 2 do %}
|
||||||
unsafe! $puts("i = {{ i }}")
|
unsafe! $puts("i = {{ i }}")
|
||||||
{% end %}
|
{% end %}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -397,7 +397,7 @@ export void main() {
|
|||||||
unsafe! $puts("i = 0")
|
unsafe! $puts("i = 0")
|
||||||
unsafe! $puts("i = 1")
|
unsafe! $puts("i = 1")
|
||||||
unsafe! $puts("i = 2")
|
unsafe! $puts("i = 2")
|
||||||
end
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
That simple: the Lua code runs during compilation.
|
That simple: the Lua code runs during compilation.
|
||||||
@@ -411,11 +411,11 @@ Well, yes, you have to trust the code you run.
|
|||||||
You do trust C libraries you link to your programs, right?
|
You do trust C libraries you link to your programs, right?
|
||||||
|
|
||||||
However, you won't trust an NPM package, because an NPM package author does not care about their reputation, and because NPM does not have auditing features.
|
However, you won't trust an NPM package, because an NPM package author does not care about their reputation, and because NPM does not have auditing features.
|
||||||
This is the Open-Source sustainability problem addresses in the [previous article]((/posts/2020-08-16-system-programming-in-2k20)) and potentially solved by the aforementioned [Onyx Software Foundation](#the-onyx-software-foundation).
|
This is the Open-Source sustainability problem addresses in the [previous article](<(/posts/2020-08-16-system-programming-in-2k20)>) and potentially solved by the aforementioned [Onyx Software Foundation](#the-onyx-software-foundation).
|
||||||
|
|
||||||
As a result, given that you do have access to code you require, authors of packages your program depends on are appropriately rewarded for their work, and the Foundation sponsors audition of selected packages, you should be safe.
|
As a result, given that you do have access to code you require, authors of packages your program depends on are appropriately rewarded for their work, and the Foundation sponsors audition of selected packages, you should be safe.
|
||||||
|
|
||||||
----
|
---
|
||||||
|
|
||||||
Back to the possibilities.
|
Back to the possibilities.
|
||||||
Macro use-cases include:
|
Macro use-cases include:
|
||||||
@@ -430,7 +430,7 @@ For example, you can compute a Fibonacci number sequence in a macro, and output
|
|||||||
Let's examine the following small snippet:
|
Let's examine the following small snippet:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
{%
|
{%
|
||||||
-- Local context is preserved
|
-- Local context is preserved
|
||||||
-- during this file compilation
|
-- during this file compilation
|
||||||
local function fib(n)
|
local function fib(n)
|
||||||
@@ -449,21 +449,21 @@ Let's examine the following small snippet:
|
|||||||
# This is a macro "function", which
|
# This is a macro "function", which
|
||||||
# may be used directly from Onyx code.
|
# may be used directly from Onyx code.
|
||||||
macro @fib(n)
|
macro @fib(n)
|
||||||
{{ fib(n) }}
|
{{ fib(n) }}
|
||||||
end
|
end
|
||||||
|
|
||||||
import "stdio.h"
|
import "stdio.h"
|
||||||
|
|
||||||
export void main() {
|
export void main() {
|
||||||
unsafe! $printf(&"%d\n", @fib(10))
|
unsafe! $printf(&"%d\n", @fib(10))
|
||||||
end
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, `@fib(10)` would evaluate during compilation and emit a number literal `55`, so the code turns into simple `$printf(&"%d\n", 55)`.
|
In this example, `@fib(10)` would evaluate during compilation and emit a number literal `55`, so the code turns into simple `$printf(&"%d\n", 55)`.
|
||||||
|
|
||||||
Of course, this would increase compilation times, and it is your responsibility to find the right balance based on your needs.
|
Of course, this would increase compilation times, and it is your responsibility to find the right balance based on your needs.
|
||||||
|
|
||||||
----
|
---
|
||||||
|
|
||||||
::: hero
|
::: hero
|
||||||
|
|
||||||
@@ -475,7 +475,7 @@ This is how it might look like:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
macro @gen_class(name)
|
macro @gen_class(name)
|
||||||
{%
|
{%
|
||||||
-- Accessing system configuration
|
-- Accessing system configuration
|
||||||
local db_path = os.getenv("DB_PATH")
|
local db_path = os.getenv("DB_PATH")
|
||||||
|
|
||||||
@@ -529,7 +529,7 @@ class User
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
----
|
---
|
||||||
|
|
||||||
::: hero
|
::: hero
|
||||||
|
|
||||||
@@ -541,14 +541,14 @@ Nuff said.
|
|||||||
For example:
|
For example:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
{% if nx.target.isa.id == "amd64" then %}
|
{% if nx.target.isa.id == "amd64" then %}
|
||||||
$printf("This is amd64")
|
$printf("This is amd64")
|
||||||
{% else %}
|
{% else %}
|
||||||
$printf("This is not amd64")
|
$printf("This is not amd64")
|
||||||
{% end %}
|
{% end %}
|
||||||
```
|
```
|
||||||
|
|
||||||
----
|
---
|
||||||
|
|
||||||
::: hero
|
::: hero
|
||||||
|
|
||||||
@@ -568,16 +568,16 @@ reopen Int<Base: 2, Signed: S, Size: Z> forall S, Z
|
|||||||
final result = unsafe! uninitialized self
|
final result = unsafe! uninitialized self
|
||||||
final overflowed? = unsafe! uninitialized Bit
|
final overflowed? = unsafe! uninitialized Bit
|
||||||
|
|
||||||
\{%
|
\{%
|
||||||
local s = nx.scope.S.val and "s" or "u"
|
local s = nx.scope.S.val and "s" or "u"
|
||||||
local t = "i" .. nx.scope.Z.val
|
local t = "i" .. nx.scope.Z.val
|
||||||
%}
|
%}
|
||||||
|
|
||||||
unsafe! asm
|
unsafe! asm
|
||||||
template llvm
|
template llvm
|
||||||
%res = call {\{{ t }}, i1} @llvm.\{{ s }}add.\
|
%res = call {\{{ t }}, i1} @llvm.\{{ s }}add.\
|
||||||
with.overflow.\{{ t }}(\{{ t }} $0, \{{ t }} $1)
|
with.overflow.\{{ t }}(\{{ t }} $0, \{{ t }} $1)
|
||||||
$2 = extractvalue {\{{ t }}, i1} %res, 1
|
$2 = extractvalue {\{{ t }}, i1} %res, 1
|
||||||
in r(this), r(another)
|
in r(this), r(another)
|
||||||
out =r(overflowed?)
|
out =r(overflowed?)
|
||||||
end
|
end
|
||||||
@@ -587,7 +587,7 @@ reopen Int<Base: 2, Signed: S, Size: Z> forall S, Z
|
|||||||
else
|
else
|
||||||
unsafe! asm
|
unsafe! asm
|
||||||
template llvm
|
template llvm
|
||||||
$0 = extractvalue {\{{ t }}, i1} %res, 0
|
$0 = extractvalue {\{{ t }}, i1} %res, 0
|
||||||
out =r(result)
|
out =r(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -600,7 +600,7 @@ end
|
|||||||
This is a fairly complex example making use of the inline assembly feature.
|
This is a fairly complex example making use of the inline assembly feature.
|
||||||
But this is what the language is capable of.
|
But this is what the language is capable of.
|
||||||
|
|
||||||
Notice that delayed macro blocks, i.e. those beginning with `{{`, are evaluated on every specialization, so the contents of the `add` function would be different for `Int<Base: 2, Signed: true, Size: 16>` (a.k.a. `SBin16`) and `Int<Base: 2, Signed: false, Size: 32>` (a.k.a. `UBin32`).
|
Notice that delayed macro blocks, i.e. those beginning with `{{`, are evaluated on every specialization, so the contents of the `add` function would be different for `Int<Base: 2, Signed: true, Size: 16>` (a.k.a. `SBin16`) and `Int<Base: 2, Signed: false, Size: 32>` (a.k.a. `UBin32`).
|
||||||
|
|
||||||
There were other features of Onyx mentioned in the example: 1) reopening certain or broad (the `forall` thing), specializations, 2) aliasing.
|
There were other features of Onyx mentioned in the example: 1) reopening certain or broad (the `forall` thing), specializations, 2) aliasing.
|
||||||
In fact, this is how integer aliasing looks like in the Core API:
|
In fact, this is how integer aliasing looks like in the Core API:
|
||||||
@@ -612,11 +612,11 @@ alias IBin<*>, Bin<*> = Int<2, *>
|
|||||||
|
|
||||||
# Use a macro to DRY the code.
|
# Use a macro to DRY the code.
|
||||||
private macro @alias_binary_sizes(id)
|
private macro @alias_binary_sizes(id)
|
||||||
alias \{{ id }}8 = \{{ id }}<8>
|
alias \{{ id }}8 = \{{ id }}<8>
|
||||||
alias \{{ id }}16 = \{{ id }}<16>
|
alias \{{ id }}16 = \{{ id }}<16>
|
||||||
alias \{{ id }}32 = \{{ id }}<32>
|
alias \{{ id }}32 = \{{ id }}<32>
|
||||||
alias \{{ id }}64 = \{{ id }}<64>
|
alias \{{ id }}64 = \{{ id }}<64>
|
||||||
alias \{{ id }}128 = \{{ id }}<128>
|
alias \{{ id }}128 = \{{ id }}<128>
|
||||||
end
|
end
|
||||||
|
|
||||||
# Signed binary integers.
|
# Signed binary integers.
|
||||||
@@ -630,10 +630,12 @@ alias UIBin<*>, UBin<*> = IBin<false, *>
|
|||||||
@alias_binary_sizes("UBin")
|
@alias_binary_sizes("UBin")
|
||||||
```
|
```
|
||||||
|
|
||||||
----
|
---
|
||||||
|
|
||||||
Macro code can generate other macro code.
|
Macro code can generate other macro code.
|
||||||
The algorithm is to evaluate immediate macros (e.g. `{% %}`) immediately once they are met in the code by some lexer, but evaluate delayed macros (e.g. `\{% %}`) only when the time is right, for example, per specialization.
|
The algorithm is to evaluate immediate macros (e.g. `{% %}`) immediately once they are met in the code by some lexer, but evaluate delayed macros (e.g. `\{% %}`) only when the time is right, for example, per specialization.
|
||||||
|
|
||||||
|
This allows to avoid embarrassing situations like [this](https://github.com/diesel-rs/diesel/blob/master/diesel/src/macros/tuples.rs) in Rust.
|
||||||
|
|
||||||
Apart from simply `print "Debug"`, Lua contains powerful debugging facilities, e.g. `debug()`.
|
Apart from simply `print "Debug"`, Lua contains powerful debugging facilities, e.g. `debug()`.
|
||||||
This means that you can debug your compilation, even with breakpoints from an IDE!
|
This means that you can debug your compilation, even with breakpoints from an IDE!
|
||||||
@@ -683,10 +685,10 @@ Let's modify the function a bit:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
def do_draw(x ~ Drawable2D)
|
def do_draw(x ~ Drawable2D)
|
||||||
{% print("Immediate: " ..
|
{% print("Immediate: " ..
|
||||||
nx.ctx.x.real_type:dump()) %}
|
nx.ctx.x.real_type:dump()) %}
|
||||||
|
|
||||||
\{% print("Specialized: " ..
|
\{% print("Specialized: " ..
|
||||||
nx.ctx.x.real_type:dump()) %}
|
nx.ctx.x.real_type:dump()) %}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -712,11 +714,11 @@ It is still possible to operate on a real type in this case thanks to type infor
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
def do_draw(x ~ Drawable2D)
|
def do_draw(x ~ Drawable2D)
|
||||||
\{% if nx.ctx.x.real_type == nx.lkp("Point") %}
|
\{% if nx.ctx.x.real_type == nx.lkp("Point") %}
|
||||||
# x : Point # Panic! It is still `Undef`
|
# x : Point # Panic! It is still `Undef`
|
||||||
# x.point_specific_method # Panic!
|
# x.point_specific_method # Panic!
|
||||||
(unsafe! x as Point).point_specific_method
|
(unsafe! x as Point).point_specific_method
|
||||||
\{% end %}
|
\{% end %}
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -761,14 +763,32 @@ end
|
|||||||
```
|
```
|
||||||
|
|
||||||
Luckily, no changes have to be made to the `do_draw()` function, because the compiler treats the argument solely as `Drawable2D`, and calling `draw()` on it always calls `Drawable2D:draw()`!
|
Luckily, no changes have to be made to the `do_draw()` function, because the compiler treats the argument solely as `Drawable2D`, and calling `draw()` on it always calls `Drawable2D:draw()`!
|
||||||
Again, changing the type from outside would not break a callee.
|
Thus, changing the type from outside would not break a callee.
|
||||||
|
|
||||||
|
The `Point` type now has `draw2d` and `draw3d` methods.
|
||||||
|
Of course, calling `Point:draw()` would not work anymore, because we've moved the implementation.
|
||||||
|
But it is still possible to restrict a `Point` to the required trait and call `draw()` on it.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
final p = Point()
|
||||||
|
|
||||||
|
# p.draw() # Panic! Ambiguity
|
||||||
|
|
||||||
|
p.draw2d() # OK, draw 2D
|
||||||
|
p~Drawable2D.draw() # OK, draw 2D
|
||||||
|
|
||||||
|
p.draw3d() # OK, draw 3D
|
||||||
|
p~Drawable3D.draw() # OK, draw 3D
|
||||||
|
```
|
||||||
|
|
||||||
Incapsulation at its finest!
|
Incapsulation at its finest!
|
||||||
|
|
||||||
### More Highlights
|
### More Highlights
|
||||||
|
|
||||||
Some more highlights of the language's features:
|
Some more highlights of the language's features:
|
||||||
|
|
||||||
* SIMD vectors and matrices built-in with literals.
|
- SIMD vectors and matrices built-in with literals.
|
||||||
It looks like this:
|
It looks like this:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -802,7 +822,7 @@ Some more highlights of the language's features:
|
|||||||
> = Tensor<T, Z, 0>
|
> = Tensor<T, Z, 0>
|
||||||
```
|
```
|
||||||
|
|
||||||
* "Magic" literals inspired by Ruby:
|
- "Magic" literals inspired by Ruby:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
let vec = %i<1 2 3 4>
|
let vec = %i<1 2 3 4>
|
||||||
@@ -810,7 +830,7 @@ Some more highlights of the language's features:
|
|||||||
let ary = %f64[1 2 3]
|
let ary = %f64[1 2 3]
|
||||||
```
|
```
|
||||||
|
|
||||||
* [IEC](https://en.wikipedia.org/wiki/Kibibyte) and [SI](https://en.wikipedia.org/wiki/Kilobyte) numerical literal prefixes:
|
- [IEC](https://en.wikipedia.org/wiki/Kibibyte) and [SI](https://en.wikipedia.org/wiki/Kilobyte) numerical literal prefixes:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
# Kibi
|
# Kibi
|
||||||
@@ -825,7 +845,7 @@ Some more highlights of the language's features:
|
|||||||
42_000_000.017)
|
42_000_000.017)
|
||||||
```
|
```
|
||||||
|
|
||||||
* String and character literals with default UTF-8 encoding and UCS charset.
|
- String and character literals with default UTF-8 encoding and UCS charset.
|
||||||
The language allows custom string and character literal suffixes for custom encodings.
|
The language allows custom string and character literal suffixes for custom encodings.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -847,7 +867,7 @@ Some more highlights of the language's features:
|
|||||||
@assert(@sizeof(c) == 4)
|
@assert(@sizeof(c) == 4)
|
||||||
```
|
```
|
||||||
|
|
||||||
* Distinct aliasing allows having a type with different methods, but the same layout.
|
- Distinct aliasing allows having a type with different methods, but the same layout.
|
||||||
For example, the `String` type is a distinct alias to an array of codeunits:
|
For example, the `String` type is a distinct alias to an array of codeunits:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -861,7 +881,7 @@ Some more highlights of the language's features:
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
* `Any` real type implies a variant of all possible types.
|
- `Any` real type implies a variant of all possible types.
|
||||||
In practice, it is often constrained by an imaginary type to reduce the number of contained options and define behaviour.
|
In practice, it is often constrained by an imaginary type to reduce the number of contained options and define behaviour.
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
@@ -894,7 +914,7 @@ Some more highlights of the language's features:
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
----
|
---
|
||||||
|
|
||||||
I could continue digging into Onyx features and examples, but for an introductory post, that should be enough.
|
I could continue digging into Onyx features and examples, but for an introductory post, that should be enough.
|
||||||
|
|
||||||
@@ -960,7 +980,7 @@ In addition to monetary funding, NXSF would also sponsor recurring security audi
|
|||||||
|
|
||||||
Apart from funding packages, the Foundation will sponsor projects and events related to Onyx, including teaching conferences, teaching materials, integrations etc.
|
Apart from funding packages, the Foundation will sponsor projects and events related to Onyx, including teaching conferences, teaching materials, integrations etc.
|
||||||
|
|
||||||
----
|
---
|
||||||
|
|
||||||
Onyx is the perfect balance between productivity and performance, a language understandable well both by humans and machines.
|
Onyx is the perfect balance between productivity and performance, a language understandable well both by humans and machines.
|
||||||
|
|
||||||
@@ -969,7 +989,7 @@ I heartfully believe that Onyx may become a new lingua franca for decades until
|
|||||||
|
|
||||||
Visit [nxsf.org](https://nxsf.org) to stay updated, and...
|
Visit [nxsf.org](https://nxsf.org) to stay updated, and...
|
||||||
|
|
||||||
----
|
---
|
||||||
|
|
||||||
::: hero
|
::: hero
|
||||||
|
|
||||||
@@ -977,6 +997,4 @@ Visit [nxsf.org](https://nxsf.org) to stay updated, and...
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
----
|
---
|
||||||
|
|
||||||
P.S: Until the Foundation is officially established, you may consider [sponsoring me directly](/posts/2020-08-27-sponsoring-onyx/) and joining the conversation on the [forum](https://forum.onyxlang.com).
|
|
||||||
|
|||||||
@@ -1,239 +0,0 @@
|
|||||||
---
|
|
||||||
title: Sponsoring Onyx
|
|
||||||
location: Moscow, Russia
|
|
||||||
excerpt: Standardizing and implementing a system programming language is hard, but you can help!
|
|
||||||
cover: /public/img/posts/2020-08-27-sponsoring-onyx/i-need-healing.jpg
|
|
||||||
ogType: article
|
|
||||||
---
|
|
||||||
|
|
||||||
Standardizing and implementing a system programming language is hard, but you can help!
|
|
||||||
Find out how you can sponsor the future, and how many hours does it take to create a language mascot, in this post.
|
|
||||||
|
|
||||||
<h2>TL; DR;</h2>
|
|
||||||
|
|
||||||
I wAnT yOuR mOnEy! 🤑
|
|
||||||
Pledge to my will on [Patreon](https://www.patreon.com/vladfaust) or buy me a coffee at [BMC](https://www.buymeacoffee.com/vladfaust)! 😂😂😂
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
<h2>Table of Contents</h2>
|
|
||||||
|
|
||||||
${toc}
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
I've been working on the [Onyx programming language](/posts/2020-08-20-the-onyx-programming-language) full-time for the past year.
|
|
||||||
The work includes standardization and implementation.
|
|
||||||
The process is _near to completion_, and there is a substantial chance for you to write your name in history.
|
|
||||||
|
|
||||||
In this post, I'll try to justify my eager will to grab your money with some proof of work.
|
|
||||||
|
|
||||||
By the way, I assume you've read my recent [post on System Programming](/posts/2019-08-16-system-programming-in-2k20), there is a [section](/posts/2019-08-16-system-programming-in-2k20/#on-open-source-sustainability) regarding to the open-source sustainability; as long as all my work is open, I'm also, um, an open-source engineer and thus need financial support.
|
|
||||||
|
|
||||||
## Deeds Already Done
|
|
||||||
|
|
||||||
The onyxlang.org domain name was registered on June 20^th^ 2019.
|
|
||||||
As I have a sin of registering domains as soon as I have a solid idea, the day may be treated as the Onyx birthday.
|
|
||||||
|
|
||||||
Today is August 27^th^ 2020, and I've already spent a plethora of time on Onyx.
|
|
||||||
You can see it for yourself in [NXSF](https://github.com/nxsf) and [FancySoft](https://github.com/fancysofthq) organization repositories!
|
|
||||||
|
|
||||||
### Tracked Time
|
|
||||||
|
|
||||||
From June 20^th^ 2019 until August 27^th^ 2020, this is the total time I've spent on *coding* Onyx specification, reference(s) and implementation(s):
|
|
||||||
|
|
||||||
::: hero
|
|
||||||
|
|
||||||
<big>1043 hrs 34 mins</big>
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
I've had hard _time_ on maintaining a single project across machines, so there is a lot of them (projects).
|
|
||||||
You may click on a project's name to see a detailed timing per file.
|
|
||||||
|
|
||||||
_Due to WakaTime limitations, I have to split the periods._
|
|
||||||
|
|
||||||
From June 20^th^ 2019 until June 20^th^ 2020:
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
Project name | Time spent{style="width: 10rem"} | Notes
|
|
||||||
--- | --- | ---
|
|
||||||
[`onyx`](https://wakatime.com/@vladfaust/projects/hmfpxdoxna?start=2019-06-20&end=2020-06-20) | 362 hrs 28 mins | Three generations of compilers. There even was [one written in Lua](https://github.com/fancysofthq/fnxc/tree/762e945916aa23f128f82541dd68bd8b90ff74f4)!
|
|
||||||
[`onyxlang`](https://wakatime.com/@vladfaust/projects/gbrlphmype?start=2019-06-20&end=2020-06-20) | 237 hrs 47 mins | The [Specification](https://github.com/nxsf/onyx)
|
|
||||||
[`lang`](https://wakatime.com/@vladfaust/projects/vnqouuvero?start=2019-06-20&end=2020-06-20) | 109 hrs 25 mins | A mix of specification and references
|
|
||||||
[`onyxsoftware`](https://wakatime.com/@vladfaust/projects/tjfynfxpvi?start=2019-06-20&end=2020-06-20) | 29 hrs 21 mins | Specification, again
|
|
||||||
[`kaleidoscope`](https://wakatime.com/@vladfaust/projects/amomlfdyzs?start=2019-06-20&end=2020-06-20) | 25 hrs 32 mins | Well, I've been learning [how to fight dragons](https://github.com/vladfaust/kaleidoscope)!
|
|
||||||
[`ref`](https://wakatime.com/@vladfaust/projects/vjnrvaqkxn?start=2019-06-20&end=2020-06-20) | 18 hrs 9 mins | Some reference
|
|
||||||
[`reference`](https://wakatime.com/@vladfaust/projects/bcdesjivqi?start=2019-06-20&end=2020-06-20) | 15 hrs 10 mins | Duh
|
|
||||||
[`onyxstd`](https://wakatime.com/@vladfaust/projects/swdwsydknq?start=2019-06-20&end=2020-06-20) | 14 hrs 45 mins | An attempt to implement a standard library... in Onyx
|
|
||||||
[`onyxcontrib`](https://wakatime.com/@vladfaust/projects/jrjvmhlpps?start=2019-06-20&end=2020-06-20) | 10 hrs 7 mins | Some Onyx code like HTTP server implementation
|
|
||||||
[`onyxc`](https://wakatime.com/@vladfaust/projects/qrrswxtxje?start=2019-06-20&end=2020-06-20) | 9 hrs 58 mins | Another work put in a compiler
|
|
||||||
[`code`](https://wakatime.com/@vladfaust/projects/wzdrcnwxzr?start=2019-06-20&end=2020-06-20) | 9 hrs 29 mins | [The Visual Studio Code extension](https://github.com/fancysofthq/code)
|
|
||||||
[`compiler`](https://wakatime.com/@vladfaust/projects/jvoarxevqx?start=2019-06-20&end=2020-06-20) | 7 hrs 36 mins | A compiler?
|
|
||||||
**Total** | 849 hrs 2 mins |
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
From June 20^th^ 2020 until August 27^th^ 2020:
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
Project name | Time spent{style="width: 30%"} | Notes
|
|
||||||
--- | --- | ---
|
|
||||||
[`onyxlang`](https://wakatime.com/@vladfaust/projects/gbrlphmype?start=2020-06-20&end=2020-08-27) | 106 hrs 1 min | The [Specification](https://github.com/nxsf/onyx)
|
|
||||||
[`nxc`](https://wakatime.com/@vladfaust/projects/rcdubvxegp?start=2020-06-20&end=2020-08-27) | 47 hrs 56 mins | The [C++ Compiler](https://github.com/fancysofthq/fnxc), finally
|
|
||||||
[`onyx-quickref`](https://wakatime.com/@vladfaust/projects/oygjwrhlgt?start=2020-06-20&end=2020-08-27) | 19 hrs 29 mins | The "quick" [reference](https://github.com/fancysofthq/onyx-ref)
|
|
||||||
[`onyx`](https://wakatime.com/@vladfaust/projects/hmfpxdoxna?start=2020-06-20&end=2020-08-27) | 14 hrs 31 mins | Mostly reference
|
|
||||||
[`onyxlang.com`](https://wakatime.com/@vladfaust/projects/aeahlrpcbp?start=2020-06-20&end=2020-08-27) | 2 hrs 44 mins | The website
|
|
||||||
[`quickref`](https://wakatime.com/@vladfaust/projects/oirloanfrd?start=2020-06-20&end=2020-08-27) | 2 hrs 42 mins | Also [reference](https://github.com/fancysofthq/onyx-ref)
|
|
||||||
[`fancyx`](https://wakatime.com/@vladfaust/projects/ozhupbhlcw?start=2020-06-20&end=2020-08-27) | 1 hr 9 mins | Some parts of the C++ compiler
|
|
||||||
**Total** | 194 hrs 32 mins |
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
### Untracked Time
|
|
||||||
|
|
||||||
One shall not forget that designing a language does not equal constantly slapping keyboard strokes.
|
|
||||||
In fact, implementing before giving a good thought may lead to [tragic results](https://github.com/crystal-lang/crystal/labels/kind%3Abug).
|
|
||||||
|
|
||||||
 is the general sponsor of Onyx](../../../public/img/posts/2020-08-27-sponsoring-onyx/thinking-meme.jpg "A 'programming is mostly thinking' meme" =60%x)
|
|
||||||
|
|
||||||
I've destroyed several notebooks while deciding on either using `do` / `end` or tabs.
|
|
||||||
<small>There has been a double of them throughout the year, but who's gonna believe in it?</small>
|
|
||||||
Would you dare to calculate the number of sleepless hours I've spent on _thinking_?
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
### Time Tracked in Real... Time
|
|
||||||
|
|
||||||
[WakaTime](https://wakatime.com/) is awesome, because it allows to embed recent coding statistics, so you can see how much I <s>wasted my youth</s> coded during the last 30 days!
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<embed src="https://wakatime.com/share/@vladfaust/d2418af2-a022-4f64-ada1-05fede7619fd.svg"></embed>
|
|
||||||
<figcaption>Coding activity in the last 30 days (updates daily)</figcaption>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<figure>
|
|
||||||
<embed src="https://wakatime.com/share/@vladfaust/e1ccdc24-0b8a-461e-8dd6-066a5f4220c9.svg"></embed>
|
|
||||||
<figcaption>Languages used in the last 30 days (updates daily)</figcaption>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
## Sponsoring the Development
|
|
||||||
|
|
||||||
So, the idea is simple: I want to be able to pay my bills while working on a thing both I enjoy working on and being useful for humanity.
|
|
||||||
|
|
||||||
Later on, I'm planning to make [NXSF](https://nxsf.org) an official 501 \(c\) non-profit organization, so donations made to it would be tax-exemptive, and I will have an official salary (_finally!_).
|
|
||||||
However, this would only happen when the language moves to the alpha stage (see the roadmap at [nxsf.org](https://nxsf.org/)).
|
|
||||||
|
|
||||||
Right now, Onyx is in the pre-alpha stage.
|
|
||||||
Nothing is publicly stable, work-in-progress etcetera.
|
|
||||||
But I still need to pay my bills.
|
|
||||||
And as I haven't got a real job for a long, long time, my financial cushion is relatively thin.
|
|
||||||
|
|
||||||
As a copyright holder, I'm planning on licensing the specifications I've been working on with a free, open-source license requiring attribution.
|
|
||||||
|
|
||||||
That said, I can offer you, a potential sponsor, a **perpetual**\* attribution in the Onyx programming language standard specification.
|
|
||||||
Your name or company logo with an optional link will be put into the according Early Backers section of the Standard.
|
|
||||||
|
|
||||||
\* As long as my attribution is required.
|
|
||||||
For example, if the Standard is rewritten from scratch by an NXSF committee without infringing my patent rights, it then stops being a derivation of my work.
|
|
||||||
|
|
||||||
### The Dark Scheme
|
|
||||||
|
|
||||||
According to the [roadmap](https://nxsf.org/), during the Pre-alpha stage no donations are accepted by NXSF.
|
|
||||||
Instead, you can donate directly to me, Vlad Faust, as I am effectively being the single developer thereof.
|
|
||||||
Note that these donations would not be tax-exemptive.
|
|
||||||
|
|
||||||
Also, note that the Pre-alpha stage implies no code contributions accepted officially.
|
|
||||||
Of course, you're free to pitch your ideas informally (e.g. via [Twitter](https://twitter.com/vladfaust) or the [forum](https://forum.onyxlang.com)), but you will not have any voting rights in any of standards development during this time.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
Donations made to me during this period accumulate, and the resulting sum defines the tier of your attribution.
|
|
||||||
|
|
||||||
1. From $25.
|
|
||||||
You're attributed with your name in the Early Individual Backers section.
|
|
||||||
|
|
||||||
1. From $100.
|
|
||||||
You're attributed with a custom link in the Early Individual Backers section.
|
|
||||||
|
|
||||||
1. From $500.
|
|
||||||
Your company's logo and link are attributed in the Early Business Backers section.
|
|
||||||
|
|
||||||
Individual tier backers are listed separately from Business tier backers.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
I also want to incentivize early backers, so the <s>pyramind</s> scheme is as follows.
|
|
||||||
|
|
||||||
I learned the hard way that estimating time on completing such a big project as a language specification is _quite_ hard.
|
|
||||||
Nonetheless, I'm planning to move on to the alpha stage in **3-5 months** from today (August 27^th^ 2020).
|
|
||||||
|
|
||||||
The earlier you donate, the more belief you have in me, the more you shall be rewarded.
|
|
||||||
And higher reward means **higher placement in the backers list**!
|
|
||||||
|
|
||||||
The placement of your attribution depends on your _donation score_, which is based on the amount you've donated.
|
|
||||||
Each month from today until the alpha stage, the score multiplier is reduced proportionally.
|
|
||||||
The multiplier stays the same for you throughout the months if you donate sequentially, i.e. without cancellations.
|
|
||||||
|
|
||||||
::: spoiler An example
|
|
||||||
|
|
||||||
Let's _imagine_ that alpha stage comes December 13^th^ 2020.
|
|
||||||
That means that since September 1^st^ 2020, **3 full months** passed.
|
|
||||||
The donations are made 1^st^ of each recurring month.
|
|
||||||
|
|
||||||
<div class="table-wrapper">
|
|
||||||
|
|
||||||
Month a donation was made | Donation score multiplier{style="width: 50%"}
|
|
||||||
--- | ---
|
|
||||||
September | `1`
|
|
||||||
October | `(1 - 1/4) = 3/4`
|
|
||||||
November | `(1 - 2/4) = 2/4`
|
|
||||||
December | `(1 - 3/4) = 1/4`
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
If Jake began their sponsorship in September with $100 per month without cancellations, his final score would be `100 * 1 + 100 * 1 + 100 * 1 + 100 * 1 = 400`.
|
|
||||||
|
|
||||||
If John donated $100 once in October, then skipped November and donated the same $100 in December (as the hype grows), his final score would be `100 * (3 / 4) + 100 * (1 / 4) = 100`.
|
|
||||||
|
|
||||||
As a result, John's placement would be lower than Jake's in the backers list.
|
|
||||||
|
|
||||||
In case of argument, the day a donation was made matters: making a donation on 3^rd^ gives more score than on 5^th^.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### My Soundcloud
|
|
||||||
|
|
||||||
You're welcome to become my patron on [Patreon](https://patreon.com/vladfaust) or buy me a coffee at [BuyMeACoffee](https://buymeacoffee.com/vladfaust).
|
|
||||||
|
|
||||||
Donations made on Patreon imply exclusive Forum and Discord roles, and Onyx Visioner merch.
|
|
||||||
BMC donations do not have those benefits but can be smaller and one-time.
|
|
||||||
Ideal if you want to just tip me a couple of times.
|
|
||||||
|
|
||||||
Direct Bitcoin donations are also accepted, but they are not eligible for listing.
|
|
||||||
|
|
||||||
### Everlasting Dev
|
|
||||||
|
|
||||||
I want to assure you that I have no long-term plans on living on these sponsorships.
|
|
||||||
I'm neither a [YandereDev](https://knowyourmeme.com/memes/people/yanderedev) nor some [Alex Medvednikov](https://vlang.io/).
|
|
||||||
The sponsorship opportunity is in effect exclusively during the pre-alpha stage.
|
|
||||||
|
|
||||||
Once the Foundation is established, you'll be guided to put your money there instead, in the form of donations, which implies tax exemption and proper voting rights.
|
|
||||||
|
|
||||||
[Fancy Software LLC](https://fancysoft.xyz) is a for-profit company and I as no other else want Onyx to be complete, so I can start working on my premium packages, self-hosted, gaming and AI products.
|
|
||||||
No Patreon sponsorship or non-profit salary can buy me a house.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
Until then, I want to be able to pay my bills and maybe purchase a newer graphics card.
|
|
||||||
In return, you get a chance to be immortalized as a visioner invested in a better future.
|
|
||||||
|
|
||||||
Follow me on [Twitter](https://twitter.com/vladfaust) and [GitHub](https://github.com/vladfaust), join the conversation on the [forum](https://forum.onyxlang.com) and also follow [NXSF](https://nxsf.org/) and [FancySoft](https://fancysoft.xyz/) to stay updated about the progress made.
|
|
||||||
|
|
||||||
Oh yes, there is also an official (i.e. NXSF-governed) standard planned on the language's mascot.
|
|
||||||
It will be a [panther-girl](https://en.wikipedia.org/wiki/Catgirl) named Onyx-chan. Nya! 🐾
|
|
||||||
27
posts/2022-04-12-the-game-of-life.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
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._
|
||||||
244
posts/2023-03-12-white-christmas.md
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
---
|
||||||
|
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>
|
||||||
45
posts/2023-11-07-ffmpegai.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
---
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
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!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Try it!
|
||||||
|
|
||||||
|
I challenge you to get the first frame of this GIF with ffmpeg.ai.
|
||||||
|
|
||||||
|

|
||||||
@@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
|
"tags": "post",
|
||||||
"layout": "post.pug"
|
"layout": "post.pug"
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
public/VladFaust.com.pdf
Normal file
BIN
public/img/posts/2023-03-12-white-christmas/1.png
Normal file
|
After Width: | Height: | Size: 494 KiB |
BIN
public/img/posts/2023-03-12-white-christmas/10.png
Normal file
|
After Width: | Height: | Size: 418 KiB |
BIN
public/img/posts/2023-03-12-white-christmas/2.png
Normal file
|
After Width: | Height: | Size: 412 KiB |
BIN
public/img/posts/2023-03-12-white-christmas/3.png
Normal file
|
After Width: | Height: | Size: 430 KiB |
BIN
public/img/posts/2023-03-12-white-christmas/4.png
Normal file
|
After Width: | Height: | Size: 418 KiB |
BIN
public/img/posts/2023-03-12-white-christmas/5.png
Normal file
|
After Width: | Height: | Size: 373 KiB |
BIN
public/img/posts/2023-03-12-white-christmas/6.png
Normal file
|
After Width: | Height: | Size: 453 KiB |
BIN
public/img/posts/2023-03-12-white-christmas/7.png
Normal file
|
After Width: | Height: | Size: 393 KiB |
BIN
public/img/posts/2023-03-12-white-christmas/8.png
Normal file
|
After Width: | Height: | Size: 505 KiB |
BIN
public/img/posts/2023-03-12-white-christmas/9.png
Normal file
|
After Width: | Height: | Size: 441 KiB |
BIN
public/img/posts/2023-11-07-ffmpegai/balerine.gif
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
public/img/posts/2023-11-07-ffmpegai/cover.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
public/img/posts/2023-11-07-ffmpegai/example.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
public/img/projects/jumpin_sweeties.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
@@ -9,3 +9,36 @@ body {
|
|||||||
font-family: 'Vollkorn', serif;
|
font-family: 'Vollkorn', serif;
|
||||||
width: 100%;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
15
public/styles/cv.css
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
@import './common.css';
|
||||||
|
|
||||||
|
#about {
|
||||||
|
max-width: 42rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
big {
|
||||||
|
font-size: xx-large;
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#about p {
|
||||||
|
margin: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
@@ -1,43 +1 @@
|
|||||||
@import './common.css';
|
@import './common.css';
|
||||||
|
|
||||||
main {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding: 2rem 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) {
|
|
||||||
main {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.posts {
|
|
||||||
padding-left: 2rem;
|
|
||||||
padding-right: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.posts .date {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.posts li {
|
|
||||||
display: list-item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
@import './common.css';
|
@import './common.css';
|
||||||
|
|
||||||
main {
|
main {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-items: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 2rem 0;
|
padding: 2rem 0;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main>h1 {
|
main>h1 {
|
||||||
@@ -28,7 +23,8 @@ main > .meta {
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
main > h1, main > .meta {
|
main>h1,
|
||||||
|
main>.meta {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +38,12 @@ main > hr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
article {
|
article {
|
||||||
max-width: 35rem;
|
width: 100%;
|
||||||
|
max-width: 42rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article p {
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
article .secret-link {
|
article .secret-link {
|
||||||
@@ -62,8 +63,8 @@ article > h2,
|
|||||||
article>h3,
|
article>h3,
|
||||||
article>h4,
|
article>h4,
|
||||||
article>h5,
|
article>h5,
|
||||||
article > h6
|
article>h6,
|
||||||
{
|
article.asciidoctor .paragraph {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
}
|
}
|
||||||
@@ -94,10 +95,18 @@ blockquote {
|
|||||||
background-color: rgba(0, 0, 0, 0.025);
|
background-color: rgba(0, 0, 0, 0.025);
|
||||||
}
|
}
|
||||||
|
|
||||||
pre[class*="language-"] {
|
pre[class*="language-"],
|
||||||
|
pre.highlight {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
|
font-size: 1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.highlight {
|
||||||
|
background-color: rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 1rem;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
@@ -105,6 +114,19 @@ code {
|
|||||||
/* padding: 0 0.25rem; */
|
/* 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 {
|
details {
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
@@ -125,6 +147,10 @@ figure {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
figure img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
figcaption {
|
figcaption {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -165,7 +191,8 @@ table {
|
|||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|||||||
30
public/styles/posts.css
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
77
public/styles/projects.css
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/* 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%;
|
||||||
|
}
|
||||||
|
}
|
||||||