For years I have had this blog in mind, thinking, let’s see if I make an entry about this or that, time has gone by and when I review it I have realized that I have not written a single post for 8 years.
In today’s age of AI, it may not make sense to maintain a blog, but I would like to maintain my writing skills and communicate the personal projects I do.
This blog was created 19 years ago with the name “Mis Cosas Geek”, using “Geek” as a term associated with a person fascinated by technology, however in recent years the term has been increasingly associated with pop culture, video games, comics, movies and cult music, as well as science fiction and fantasy and that is not the purpose of this blog, therefore, from now on dear silicon lovers this site will be called “The Admin’s workshop” and we will continue talking about electronic botched, development and some new topics such as home automation and 3D printing.
The new Stack#
This name change could not be the only novelty and because of this it has also been migrated at a technological level going to generate static HTML, the reasons for this change are, to avoid maintaining a database and writing in Markdown, as well as SEO, performance, accessibility and security improvements (basically because it is static html :D).
- wp2hugo as a tool for performing the migration.
- Hugo as a generator of static sites.
- Blowfish Theme
- Github Actions
- Microsoft Translator with Free tier (Azure F0) for translations into other languages and 2 million characters per month included.
- Cloudflare Workers
- [Brevo](Para Newsletter)
- Buy Me a Coffee
- Pholo Site verification for RSS nostalgics like me but updated with AI
Choosing a static site generator#
The choice has been Hugo, in this new stage I want to focus on writing instead of maintaining plugins, updates, SEO etc while maintaining the best possible performance. Hugo brings the following advantages over similar technologies such as Astro, Jekyll or Next.js.
- It has no dependencies
- The learning curve is low.
- Its speed is very high.
- It is modern, compared above all to Jekyll
- Simplicity
The next thing is to choose a theme that is robust, well-designed, with built-in functionalities and that is not overloaded, after comparing multiple existing themes Blowfish was chosen.
Export#
For the migration, the first thing is to extract the contents and files from the old Wordpress using one of the libraries available on Github. After comparing multiple tools such as wordpress-export-to-markdown,markdown-exporter-for-wordpress and wp2hugo, the latter was the clear winner due to the following advantages:
- Extract comments
- It allows you to download not only the referenced images and files but also all the existing ones in Wordpress
- Transform Wordpress HTML correctly by including code blocks
- Allows you to adjust the structure of files and folders in the new blog
- Maintains wordpress and GUID slugs
The Deployment Flow#
In terms of deployment, although in my professional life I have used Jenkins, Gitlab CI/CD templates and Azure Devops, I had never used Github Actions and the experience has been wonderful.
For the “hosting” of the site, Cloudflare Workers has been used which allows free deployments even in private repositories, unlimited requests, 20,000 files, 25Mb per file, real 301 redirects (to maintain redirects of the old Wordpress RSS feeds), 404 pages per language among others.
It’s all in code: .github/workflows/publish.yml (Action “Publish”) and Cloudflare wrangler.jsonc (Worker).
Each push a main launches the Action, which does two jobs in a row:
1. Translation#
I would like the blog to reach more people, for this I have chosen the most spoken languages in the world and the posts will be automatically translated into them:
- Spanish
- English
- Mandarin Chinese
- Hindi
- Spanish
- French
- Arabic
- Bengali
- Portuguese
- Russian
To do this, I use translate.py that translates new or modified posts using Microsoft Translator free of charge and uploads the translations to the repository. If there is nothing, the script finishes in seconds without spending any fee. - If the translation fails or the quota runs out: it is displayed anyway, so the post in Spanish is published anyway. - You can resume pending translations or redeploy by hand: Actions → Publish → Run workflow. - GitHub secrets: AZURE_TRANSLATOR_KEY, AZURE_TRANSLATOR_REGION, CLOUDFLARE_API_TOKEN (“Edit Cloudflare Workers” template, zone talleradmin.com) and CLOUDFLARE_ACCOUNT_ID.
2. The deployment#
Build with Hugo (the latest version available with Blowfish support) and deploy with wrangler.jsonc in Cloudflare’s Worker.
The Newsletter#
I’m not sure if newsletters are still alive or dying, so I’ve created one with [Brevo](Para Newsletter) to test it. I’ve been surprised that a feature that 20 years ago offered hundreds of websites for free to webmasters is now ultra-limited paid services. Still, according to what I’ve been able to research, Claude and I Brevo seems to offer the best free plan with RSS automation.
Other topics reviewed and migrated#
Accessibility
Adsense
Google Search console: migrate the blog since the domain has also changed rubeninfante.com to talleradmin.com
Aliexpress and Amazon Affiliate Links
Optimize images
sudo apt install optipng jpegoptim find static/wp-content -iname '_.png' -print0 | xargs -0 -P"$(nproc)" -n4 optipng -o2 -strip all -quiet find static/wp-content -iname '_.jp\*g' -print0 | xargs -0 jpegoptim --strip-all --all-progressive -qReview robots.txt
Review of accents in categories and tags
In my case I have cleaned up tags and categories using the
static/_redirectsfileClean up unused files
I’ve added images to each page and a generic one for when there is no
static/img/social-default.jpgandassets/img/background.jpgReview Wordpress plugins before migration and disable all but the essential ones.
Modify and create redirects from rubeninfante.com to talleradmin.com
In daily work#
Commands#
Create a new item
hugo new posts/mi-nuevo-articulo/index.md- If an image in the
mi-nuevo-articulofolder is calledfeature.[jpg,png,webp]it will be used as the main image, header and social media
- If an image in the
Check for broken links
Create the
lychee.tomlfile at the root of the site with content# lychee.toml — enlaces que no se comprueban (expresiones regulares) exclude = [ "#nolychee$", # la marca de evitar enlaces "https://web.archive.org/web/*", "reddit.com/submit", "facebook.com/sharer", "linkedin.com/shareArticle" ] exclude_path = ["^public/(en|zh-cn|hi|fr|ar|bn|pt-br|ru)/"]Run the command:
hugo --gc --cleanDestinationDir lychee --root-dir "$PWD/public" 'public/**/*.html' --format markdown --output informe.mdReview
informe.md- Add
https://web.archive.org/web/to the beginning of the url if the link no longer exists - Add
#nolycheeto the end of a link or to thelychee.tomlfile if the detection is incorrect due to anti-bots or another reason
- Add
To update the theme#
Update the theme
cd themes/blowfish OLD=$(git rev-parse HEAD) # para comparar después git fetch --depth 1 origin main && git checkout -B main origin/mainReview the files that you have overwritten on the subject
cd ../.. for f in $(cd layouts && find . -type f); do git -C themes/blowfish diff --quiet $OLD HEAD -- "layouts/${f#./}" 2>/dev/null || echo "Revisar: layouts/${f#./}"; done
Images#
It is important to know the routes in which to store the images of the Blog:
assetsfor images that the theme uses and can optimize: the background (defaultBackgroundImage), the default featured image (defaultFeaturedImage), and your author photo. That’s why background.jpg is fine there: the theme shrinks it and the 3.4 MB isn’t served.staticfor which you need a fixed and unchanged URL: favicons, ads.txt, PDFs, files to download or images to which you link from outside. As an example Isocial-default.jpgput it there because Whatsapp and X ask for a stable URL.Imágenes de un post concreto: In the folder of the post itself (page bundle).NOTE In hugo.toml I set up
staticalso as assets. That’s why static/ images are also optimized when the theme uses them as a cover. It’s a fix for the WordPress migration.[[module.mounts]] source = "static" target = "assets"
Add a language#
Files to be modified/added
config/_default/languages.xx.toml config/_default/menus.xx.toml i18n/xx.toml (Sólo en el caso del que el tema no incluya el idioma)Modify
/config/_default/params.tomlnewsletter.formAction] es = "https://..." xx = "https://..."
