The best Front-End frameworks 2022

React developer desk

It’s 2022, and it’s that question again which frontend framework to use? Are they maintained, production-ready, good learning curve vs benefit balance and active community? Let’s do a quick recap for the best of the best out there.

Photo by Oskar Yildiz on Unsplash


I will put React in the number 1. The best of the best, and there are many reasons for that. First, because it has a vast community, simple structure, modular, component-based, and they also care about the world. They are a big supporter of Ukraine and the free world. That’s already alone is something.

What’s also very important with React and all the JavaScript (JS) based frameworks is that the learning curve and commons are very similar between the backend and the frontend. Also, React will let you build native mobile apps using React Native. So fewer code paradigms, similar codebase and a better understanding of each other’s code for various roles. Even though most of the developers are becoming full stack over time, thanks to these frameworks listed here, they can handle both backend and frontend code.

Also important to mention that React has Next.js for the backend. Quote from their web —

Next.js gives you the best developer experience with all the features you need for production: hybrid static & server rendering, TypeScript support, smart bundling, route pre-fetching, and more. No config needed.

Honourable mention is also React alternative Preact. They still hold a strong position, but I’m taking it as an alternative and would still go with React. But they have done an outstanding job there Preact also supports Ukraine.

To read the full article, please go to my Medium post. There are more of that form the top 4.

This helpful article sums it up nicely to read more about last year’s trends.

To finish it up, I also wanted to mention some deployment and static web options that are important to be aware of on 2022.

And of course, if you need marketing automation tools for 2022, then Mockup API from Mediamodifier is the best on the market. I’m affiliated with that one.

Mockup API
Mockup API

Oh my terminal extension

Now, already a lot of time back I’m using that wonderful terminal extension on my Mac I wanted to share with others who might not have found it yet. It’s OhMyZsh –

Oh My Zsh is a delightful, open-source, community-driven framework for managing your Zsh configuration. It comes bundled with thousands of helpful functions, helpers, plugins, themes, and a few things that make you shout…

“Oh My ZSH!”

Also, be sure to check out their cheat sheet for pro usage 😉

FOMO Taastusravi podcast

That’s where it all started. One weekday evening, in the heart of Tallinn, the Bermuda Triangle, two crypto engineers met. Thanks to their life experience, of course, they had in their pockets a holistic “burnout” treatment plan, and another long evening was about to start.

That evening in 2021, summer showed itself for the first time and there was light electricity in the air. Time was late at the cosy office — microphones and other devices, not yet known, to them were found (
A little later, after researching these devices and realizing again that the price of Bitcoin had fallen again, many of them needed to be “comforted” with a good word, and it was decided to create a podcast FOMO Taastusravi. This will reach many and quickly.

Read more from Medium article

TypeScript 4.0 is here!

TypeScript 4 features

Microsoft continues to make developers feel great using new technologies. Now they announced the availability of TypeScript 4.0! It’s better in all areas – productivity, stability, and scalability.

Developers love to work with clean, well structured, readable, and functional code. This is exactly what TypeScript is for. Together with their IDE Visual Code it’s a strong and convenient combination for almost any web developer.

No more ‘undefined’ errors, better structure, and easier refactoring, mixed types of black magic. If needed create your own composite types for complex situations.

There’s a great article on TypeScript blog on what’s added and how to get started right away.

Start hacking and learn something new!

npm install -D typescript

TypeScript 4 features

Running Obyte wallet on headless RaspberryPi 3+

RaspberryPi 3+

Let’s build and run headless Obyte wallet on RaspberryPi 3+. We’re going to run Obyte light node. Running full node is too slow to sync and the first database buildup can take weeks-months to complete Raspberry Pi 3+.

I also tried to do the full node syncing on another computer and then copied that DB into the Raspberry. Still, keeping it in sync was too much for Raspberry so it didn’t work out even then.

Prepare image on to the SD card

Go with the Raspbian Stretch Lite image from here Raspian is based on Debian Linux.

Raspbian Stretch Lite

Next, download balenaEtcher ( for burning that image onto the SD card. If you haven’t used it yet then the balenaEtcher is a very easy, convenient way to burn OS images into the SD & USB drives.

Note that I have 16GB SD card in my example, 8GB is more than enough.


Configure SSH & Wifi (if needed)

Now, enable SSH so you could connect into your Raspberry Pi without a need for a screen and keyboard. I’m going to use cable LAN and therefore don’t need to setup Wifi connection at the beginning.

To setup SSH you need to create the file ssh into the boot folder. Basically, there are two volumes – boot and rootfs. Create empty file names ssh and validate that it’s there.

For Wifi setup create a file named wpa_supplicant.conf again into the boot folder with the following content:


This file will be copied on the first boot into the /etc/wpa_supplicant/wpa_supplicant.conf folder.

Find your Pi and log in

Now it’s time to put SD card into the Raspberry, connect LAN and power up.

You need to find your device IP address. One option is to assume that it has default hostname. In that case, you could ping raspberrypi.local to get it. The easiest way!

Other ways are to use arp -a, nmap (more info here or get IP addresses list from your router and find it from there.

Log in using SSH using IP or ssh raspberrypi.local. The default username is “pi” and password “raspberry”. Change your password after login.

Update and configure

When logged in, first update its system.

sudo apt update
sudo apt upgrade

Then check Raspberry configuration tool to setup Wifi (if needed and you didn’t do this before) and extend file system. Run raspi-config.

For the menu “Advanced Options” choose “Expand Filesystem”. This will make Raspberry use the whole SD card.

To be sure that system is updated you could also run “Update” from there.


Install NodeJS, Git, Tor and Screen

curl -sL | sudo -E bash -
sudo apt install nodejs git screen tor

I also like to use vim and sysv-rc-conf, but there’s no need to install these for this setup.

“Screen” will be used to run wallet on the background while remaining overview of the situation. This is totally optional.

Clone and configure wallet

Now clone “headless-obyte” from Github.

git clone obyte
cd obyte
npm install

Create the user configuration file into ~/.config/headless-obyte/conf.jsonand enter the following.

"socksHost": "",
"socksPort": 9050,
"socksLocalDNS": true, "control_addresses": [""], "bLight": true,
"bFaster": true

Don’t set socksHostsocksPort, and socksLocalDNS if you don’t wish to use TOR.

Also, you can also define control_addresses (array) with your Obyte wallet device address, so you can control your wallet remotely or payout_address, to restrict, which addresses the wallet can withdraw funds.

Run & enjoy

node start.js --max-old-space-size=2048

It will ask to set the passphrase. Later on every run it also asks that. This is used to protect your wallet private keys.

When you run the node, “my pairing code” is the code that you can use to connect headless wallet with your Obyte wallet.

====== my pairing code: *****************

When everything work you can “Ctrl + a + d” to detach that screen. And with command screen -r go back into it. “Ctrl + d” or `exit` to terminate.

An issue to be dealt with will be handling growing log file size. One option is to disable the log, but it won’t suggest doing that.

For now, if everything runs without errors turn logs off by adding the following line into the conf.json file.

“LOG_FILENAME”: “/dev/null”


WooCommerce Multilingual translated variations’ quantity out of sync fix

This PHP script may help if WooCommerce Multilingual product variation quantities are getting out of sync. Basically what it does is it deletes old “post_product_variation” relations from icl_translations table and creates new ones (and the ones which were already missing – that’s where the problem is) using pure PHP mysqli connection rather than any WordPress/WooCommerce functionalities so it doesn’t depend on those if they had any bugs causing the out of sync situation in first place.

  1. Try WooCommerce Multilingual built-in troubleshooting feature at WooCommerce > WooCommerce Multilingual > Status > Troubleshooting > check all the boxes except duplicate term (or check it if you need) and Start. Might happen it already solves the chaos or for some but not all products.
  2. Download the script to your WordPress site root directory where there is also wp-config.php (required). You’ll find the .zip at the end of this post. Make backups and read the script code first, use at your own risk! Yes, it deletes old relations from the DB, so have a backup. Run the script directly (it is not a plugin).
  3. Go back to point 1 and Sync variables products again. This step is necessary!
  4. (Bonus) Now the variation quantities should be already synced. However if the quantities are now same in different languages but you edit (or order) a variation quantity and it doesn’t update the other translations:
    1. WPML > Translation Management > Multilingual Content Setup. Custom Field Translation > Show system fields, _stock has to be listed and set to “copy”.
    2. If _stock is not listed nor set to “copy” examine WooCommerce > WooCommerce Multilingual > Status for _stock. And plugins/woocommerce-multilingual/wpml-config.xml file and optionally same file in your theme folder. Edit XML to “copy” and Restore default at WPML > Languages > Reset settings.
    3. Everything ok but still not synchronizing automatically? Add the following code to your themes functions.php, requires points 4.1 and 4.2 to be resolved (_stock listed and set to “copy”):

// WooCommerce Sync variation quantity in translations
add_action('updated_post_meta', 'wc_sync_variation_quantity_in_translations', 10, 4);
function wc_sync_variation_quantity_in_translations($meta_id, $post_id, $meta_key, $meta_value)
    if ('_stock' == $meta_key) {
		do_action('wpml_sync_custom_field', $post_id, $meta_key);
// /

Tested/solution for:
* WooCommerce 2.6.14, the latest WooCommerce2 version.
* WooCommerce Mutlilingual 4.2.0
* WPML Translation Management 2.2.6

Even if the script was written for WooCommerce2 this kind of trouble exists on newer 3+ versions also. Still give it a try.

MediaWiki, Parsoid and Heroku configuration hints

(MediaWiki 1.31.0)

Login “Remember password” checked by default

Add to LocalSettings.php:

$wgHooks['AuthChangeFormFields'][] = function ($requests, $fieldInfo, &$formDescriptor, $action) {
    $formDescriptor['rememberMe']['default'] = true;
    return true;

See Hooks/AuthChangeFormFields and HTMLForm.

However, if you need it because of random session drops then see the next chapter:

Session handling / PHP’s default session handler / Session problems

$wgSessionsInObjectCache vs $wgPHPSessionHandling

The first one (and setting it to false) is deprecated (= no longer has effect).

In case you’re getting randomly logged out or “a loss of session data” errors appear then try to disable mixing session handling of MW and PHP. Add to LocalSettings.php:

$wgPHPSessionHandling = 'disable';

Wake Parsoid on user login if running on Heroku free dynos

Parsoid is a node.js-based service used by MediaWiki’s awesome VisualEditor. Parsoid can be set up on a free Heroku account.

Add to LocalSettings.php:

$wgHooks['UserLoggedIn'][] = function($user) {
    if ($user->isAllowed('edit')) {

        $parsoid_host = '';

        $fp = fsockopen('ssl://' . $parsoid_host, 443, $errno, $errstr, 30);
        $out = "GET / HTTP/1.1\r\n";
        $out .= "Host: " . $parsoid_host . "\r\n";
        $out .= "Content-Length: 0"."\r\n";
        $out .= "Connection: Close\r\n\r\n";
        fwrite($fp, $out);

After a user with edit permission logs into MediaWiki, sends a GET request to Parsoid Heroku-URL but doesn’t wait for an answer. Shouldn’t affect login time but decreases VisualEditor’s first-load time (otherwise could be ~20+ seconds). Free dynos go to sleep after 30min of inactivity. Currently maximum allowed awake time per 24h is 18h.

Enable local Parsoid to have edit access without hardcoding IP or cookie forwarding

Might be useful, depends on your server config. Add to LocalSettings.php:

if ($_SERVER['REMOTE_ADDR'] == gethostbyname(trim(`hostname`))) {
    $wgGroupPermissions['*']['read'] = true;
    $wgGroupPermissions['*']['edit'] = true;
    $wgGroupPermissions['*']['upload'] = true;
    $wgGroupPermissions['*']['reupload'] = true;
    $wgGroupPermissions['*']['reupload-shared'] = true;

Fix Jasny File Input in Avant theme and IE / MS Edge

Applies to “Avant – Clean and Responsive Bootstrap 3.3.2 Admin” or Avant 1.4 (c) 2015 as written in readme.txt.

Open /HTML/assets/css/styles.css, find the following block:

.btn-file > input {
  position: absolute;
  top: 0;
  right: 0;
  margin: 0;
  opacity: 0;
  filter: alpha(opacity=0);
  transform: translate(-300px, 0) scale(4);
  -webkit-transform: translate(-300px, 0) scale(4);
  font-size: 23px;
  height: 100%;
  width: 100%;
  direction: ltr;
  cursor: pointer;

Comment out the following lines:

/*  transform: translate(-300px, 0) scale(4);
  -webkit-transform: translate(-300px, 0) scale(4); */

Now Select file/image etc buttons should work in Internet Explorer 11 (as tested on 11.306.10586.0) and Microsoft Edge.

To make the examples in File Inputs section of the Form Components page work, open /HTML/form-components.htm and change:

<script type='text/javascript' src='assets/plugins/form-jasnyupload/fileinput.min.js'></script>


<script type='text/javascript' src='assets/plugins/form-jasnyupload/fileinput.js'></script>

Now the controls and image preview are functioning.

Additionally the plugin could be upgraded to a more recent version, select “Download source code” and replace /HTML/assets/plugins/form-jasnyupload/fileinput.js and fileinput.less files with the ones from the downloaded archive. Upgrading to 3.1.3 makes “too much recursion”-errors disappear from the JS-console.

Android apk keystore signing for store


First think you need to do is to generate keystore file for project. Store apps needs to be signed with that and its always good to have separated keystore for each app. Keep that securely cause you need this everytime youre updating your app on store.

You can generate also using various IDEs like NetBeans, Eclipse, Android Studio and so on, but in this time we’re using command line.

user@host:~/home $ keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000


After you have built your apk (unsigned) you need to use following command to sign this with previously generated keystore.

user@host:~/home $ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application.apk alias_name

Validate signed apk:

user@host:~/home $ jarsigner -verify -verbose -certs my_application.apk


Finally align you apk to optimize it and after that it’s ready to be submitted into store.

user@host:~/home $ zipalign -v 4 my_application.apk my_application_aligned.apk


Using IF condition in SELECT in Active Record SQL scope (for Yii)

Instead of a string value use an array to specify different ‘select’ expressions (just a string will get exploded using comma as delimter and there’ll be an error). NB! New variables defined only in SQL query code (with AS) should be defined also in the Model:

// AR variables defined in SQL query code
public $begins_same_day;
public $is_long;

public function scopes()
	return array(
		'more' => array(
			'select' => array(
				'FALSE AS begins_same_day',
				'IF (DATE(date_to) > DATE(date_from + INTERVAL 1 DAY), TRUE, FALSE) AS is_long'
			'condition' => 'TO_DAYS(date(date_from)) > (TO_DAYS(date(NOW())) + 2)',
			'order' => 'date_from ASC, date_to ASC',
			'limit' => 20