TLDR: I created a CLI and webpack plugin that converts HTML files into fully featured, dynamic Gutenberg Blocks. It allows developers to write custom blocks up to 5x faster. You can find it here: HTML To Gutenberg. I love Gutenberg. So do my clients. But like many fellow WordPress developers raised on ACF and the good old way™ of building websites, I was hesitant at first to fully embrace Guten...
Articles
Fastify is a Node.js web framework inspired by Express, offering an excellent developer experience thanks to its plugin-based architecture. Having worked extensively with Express in the past, I now use Fastify exclusively for building APIs or web applications when JavaScript is the best fit for the project. When developing a web application with server-side template rendering, I prefer Twig, my...
import path from 'path';
import FastifyPlugin from 'fastify-plugin';
import FastifyView from '@fastify/view';
import twig from 'twig';
// Adjust this to match your file structure
const v...
To simplify the daily management of an e-commerce store, it can be useful to display prices excluding VAT (net prices) directly in the administrative views, especially to ease accounting calculations on a day-to-day basis. By default, Drupal Commerce displays prices including VAT (gross prices) in its views and does not offer an option to show only the net price. This article proposes a solutio...
/**
* Plugin implementation of the 'Excluding VAT Price Formatter' formatter.
*
* @FieldFormatter(
* id = "excluding_vat_price_formatter",
* label = @Translation("Excluding VAT Price ...
As soon as a web project reaches a certain level of complexity, managing the deployment of new features becomes a crucial issue. In the past, developers sometimes worked for weeks on isolated features before merging their work for a new release. Today, deployment cycles are much more frequent; it’s not uncommon for teams working on distinct features to deploy their code several times a day with...
// Pseudo-code
$user = get_user();
$account_creation_time = $user->getCreatedTime();
$birth_country = $user->get('birth_country');
$birth_date = $user->get('birth_date');
if (
(new DateT...
Recently, I decided to delve into the "new" Gutenberg editor of WordPress to finally adopt it and offer a better editing experience to my clients. This epiphany came when I watched the case study videos by 10up about the development of the White House website. Finally, I realized that Gutenberg was not just a tedious assembly of atomic components that were laborious to evolve and maintain. Inst...
add_filter('block_type_metadata_settings', function ($settings, $metadata) {
if (! empty($metadata['render'])) {
$template_path = wp_normalize_path(
realpath(
dirn...
A few years ago, I created a small website that was picked up by a major local media outlet. The domain had since expired, but seeing that it was still available for purchase, I decided to reclaim it to set up a redirect to my current website and gain an additional high-quality backlink. "A DNS-level redirect, and that's it," I thought. Everything seemed fine until I tested the redirect and rea...
https://www.monsuperdomaine.com https://www.julienverneaut.com 301!
https://monsuperdomaine.com https://www.julienverneaut.com 301!
When I search for something on the internet, I often find that English content is much more comprehensive than French content. Although it might seem obvious given the number of English speakers in the world compared to French speakers (about 4 to 5 times more), I wanted to test this hypothesis and quantify it. TLDR: On average, an English article on Wikipedia contains 19% more information than...
def getRandomArticlesUrl(locale):
return "https://" + locale + ".wikipedia.org/w/api.php?action=query&generator=random&grnlimit=500&grnnamespace=0&prop=info&format=json"
def getRandomArticl...
When creating a listing page, it’s often necessary to offer users the ability to sort items by popularity based on the number of views of each page. This helps highlight content that is more likely to interest them. To achieve this, Drupal offers the Statistics module, which is currently included in core. This module allows you to store the number of daily views on a node, as well as views sinc...
State management is one of the most important part of a web application. From the use of global variables to React hooks to the use of third-party libraries like MobX, Redux or XState to name just these 3, it is one of the topics that fuels the most discussions as it is important to master it to design a reliable and efficient application. Today, I propose to build a mini state management libra...
const state = new State({
count: 0,
text: '',
});
state.observe(({ count }) => {
console.log('Count changed', count);
});
state.observe(({ text }) => {
console.log('Text changed...
By default, the visibility conditions of Drupal blocks on Content Types allow you to choose on which content types a block is displayed, and therefore reciprocally those on which they are not displayed. Even though this behavior seems quite logical at first glance, it only allows you to filter content types and not pages generated from programmatic routes (those from views for example). It then...
By inspecting my server metrics, I realized that my 50GB disk was almost full while this site hosts very few files and contains mostly text data. So I used the command du -h / 2>/dev/null | grep '[0-9\.]\+G'
to find the folders on my server that were taking up the most space. I then saw that my /var/lib/mysql
folder weighed nearly 30GB and was filled with binlog.xxxxxx
files. These files are bi...
[mariadb]
binlog_expire_logs_seconds=21600
WordPress being one of the most popular CMS in the world, it is a prime target for hackers as the scope of discovering a new vulnerability can be great. Automated attacks are legion, which any webmaster must have already noticed by exploring the logs of HTTP requests received by their server. Don't panic though, if you follow good practices in terms of hosting, updating the CMS and its plugins ...
/wp-json/wp/v2/users
While Git allows you to keep track of every single change to a file within a repository, it is sometimes useful to have an area in your project where you can drop unversioned files, if only to leave notes, download dumps, store curl results, etc. Rather than modifying the project's .gitignore
file or messing with Git's cache to avoid versioning these files, there is a simple trick that does exa...
Before releasing the website you are currently browsing, I maintained the subdomains lab.julienverneaut.com
and blog.julienverneaut.com
to publish front-end experiments and blog articles respectively. I wanted to unify these 2 platforms into a single site during its redesign in order to allow my visitors to discover my other content once easily. In the case of my laboratory lab.julienverneaut.c...
https://lab.julienverneaut.com https://www.julienverneaut.com/experiences 301!
While Drupal ships a default language switcher block, its options are very limited by default and are not easily customizable without using hooks or complicated template overrides. To solve this problem, the Language Switcher Extended module has been created. Thanks to this module, some new options are available through its config tab once it its installed on your site. It is a common need to w...
The Easy Breadcrumb module is one of Drupal's most popular breadcrumbs building module. When using it on a multilingual website, I stumbled upon an issue where I wasn't able to translate the home page crumb title segment (typically Home) in other languages. An issue exists that was marked as Fixed but it doesn't seem to work in my case when using Drupal 10.3.1. To solve this issue, I created a ...
diff --git a/src/EasyBreadcrumbBuilder.php b/src/EasyBreadcrumbBuilder.php
index 7790b32..15bedc7 100644
--- a/src/EasyBreadcrumbBuilder.php
+++ b/src/EasyBreadcrumbBuilder.php
@@ -339,7 +339,7...
When migrating from a WooCommerce site to Shopify, it can be useful to import the list of clients from the old site to be able to communicate with them or just for them to find their personal informations in the new site (email, address, etc.). If it's possible to use one of many WooCommerce specific plugins to export the customers list, I often find them slow and not very clear with what kind ...
const mysql = require('mysql2/promise');
const fs = require('fs');
const csv = require('fast-csv');
// TODO: Update these settings with your own config
const dbConfig = {
host: 'localhost'...
For SEO, the title of a page can be one of the elements to optimize in order to target certain requests or simply to give more information to search engines about the content present on a page. For this site, I created a Technologies taxonomy in order to communicate range of services that I offer to potential prospects. These technologies are referenced everywhere else on the site, so it made s...
<h1>{{ content.field_technology_title }}</h1>
Since the integration of pipeline building tools into major git repository hosting services (GitHub Actions for GitHub, GitLab CI/CD for GitLab), there is no longer any excuse to continue manual deployment via FTP. Personally more invested in the GitHub ecosystem than that of GitLab, I use GitHub Actions for the majority of my deployments with a pipeline that I have refined over the years. This...
name: Build and deploy
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
When deploying a Drupal project with a continuous deployment pipeline, it is often necessary to rebuild the Drupal cache so that it takes into account the latest file changes. Problem: While rebuilding the cache ensures that you have the latest server-side changes, it can cause additional slowness when loading pages for the first time while Drupal rebuilds the HTML cache of the various pages, v...
- name: Warm cache
run: ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_HOST }} "cd /var/www/html && vendor/bin/drush warmer:enqueue entity,sitemap && vendor/bin/drush queue-run warmer"