# Full Content Archive for Dariusz Więckiewicz 🇬🇧 [EN]

This document contains the complete text content of the website for comprehensive AI context and analysis.


---
## Hugo, Netlify, and the llms.txt Dilemma
- **URL:** https://dariusz.wieckiewicz.org/en/hugo-netlify-llms-txt/
- **Date:** 2026-06-21
- **Tags:** Hugo, Netlify, LLMs, Agentic Browsing, SEO, Page Speed Insights

### Content

The `llms.txt` and discussion around it recently is quite controversial.

On one hand, Google’s Search Relations team (led by John Mueller and Gary Illyes) has explicitly stated that `llms.txt` files will not help your SEO or search rankings. On the other hand, Google's developer tools team recently introduced an experimental **"Agentic Browsing"** category into Lighthouse and PageSpeed Insights that actively audits for an `llms.txt` file.

This seems contradictory, but it makes perfect sense once you separate **Search Discovery** from **On-Page Navigation**.

<!--more-->

## The Search Team's View - John Mueller

John Mueller’s critique focuses strictly on **SEO, discovery, and trust**.

Google Search ignores `llms.txt` because it is a self-reported file. If a brand writes _"We are the absolute best law firm in London"_ in their `llms.txt`, an AI cannot use that to rank them above a competitor. Mueller compared it to the old `meta keywords` tag from the 2000s — it is too easy for webmasters to game or fill with spam, so Google Search and AI Overviews rely on standard HTML and external authority signals instead.

## The PageSpeed - Agentic Browsing

The new **Agentic Browsing** audits in PageSpeed Insights are not looking at your site from an SEO perspective. They are testing how easy it is for an AI agent to **interact with and use** your site _after_ it has already arrived.

If an AI agent lands on your site to complete a task, it needs clear directions.

**`llms.txt`** acts like a map or store directory at the entrance. It tells the agent what key pages exist so the bot doesn't waste time and context window tokens blindly crawling your entire HTML structure.

---

Whereas the `llms.txt` is one story is one thing, the thing that I found interesting was the analysis in regards to **accessibility**.

The PageSpeed Insights are a great place to assess your website. If you find some issues, you can work on them to make your website better. The problem is, especially when your stats are poor and you fail the **Core Web Vitals assessment**, that it does not refresh overnight. You may fix all the things today, but to see how changes done today will reflect on the score, you will need to wait 28 days or more.

**Accessibility Tree & CLS:** Ensure the page layout is stable and correctly labelled so an AI agent reading the code (or taking screenshots) doesn't miss buttons or click empty space if the page shifts.

---

The `llms.txt` is nothing new right now, and many people who are building their site with SSG like Hugo already figured out how to implement this automatically in their site.

I have decided to do this as well, but want to make it across my website more universal. Some of "my" websites are in English only, others in Polish only, but I got, however, some that have two or three languages, and the template that I want to use needs to work on them.

For AI, the language does not matter as much as for us, humans. Whereas Polish was named one of the best languages for AI, due to its directiveness and descriptiveness (this is why it is so hard for foreigners to learn, compared to English, that they lose a lot in translation), I opted to keep my `llms.txt` in English for all sites.

The **agentic browsing** checks mainly if its `llms.txt` **follows recommendations** from [llmstxt.org](https://llmstxt.org/).

> According to the official spec, the file needs a specific layout split into sections: a primary title (`#`), a brief description, an optional list of key details, and then sections for main sections (`##`) and external resources.

Before I start with the template, I need to make Hugo generate it automatically, as I do not have time to maintain it all the time.

{{% ads-in-article %}}

## Hugo - Configuration

In my Hugo configuration file `hugo.toml`, I need to find my `[outputs]` section and add an option to generate relevant files.

The `llms.txt` layout shall be lean and not bloat the AI with information. You shall not generate all that is on your website into a single file. 

Following [Getting our Hugo+Netlify site agent compatible](https://www.linkedin.com/pulse/getting-our-hugonetlify-site-agent-compatible-steph-locke-bnjoe/) by [Steph Locke](https://www.linkedin.com/in/stephanielocke/), I opted into the approach of having two files:

* `llms.txt` — structured index
* `llms-full.txt` — full content version for deeper indexing

My element in config will look as follows:
```toml
[outputs]
  page = [ "html"]
  home = [ "html", "rss", "llms", "llmsfull"]
```

This needs to follow us with a definition, and what these two options do.
```toml
[outputFormats.llms]
  baseName = "llms"
  isPlainText = true
  mediaType = "text/plain"

[outputFormats.llmsfull]
  baseName = "llms-full"
  isPlainText = true
  mediaType = "text/plain"
```

## Hugo - The Netlify Header Fix

If you just output `llms.txt` via Hugo, Netlify will serve it with a standard `text/plain` content type (as instructed). However, because it contains Markdown syntax, browsers and advanced AI agents can get confused about how to parse it.

To fix this, you want Netlify to explicitly serve it as Markdown even when serving it  as a `.txt` file. You can enforce this directly in your `netlify.toml` file so Netlify appends the correct header when the file is requested:

```
[[headers]]
  for = "/llms.txt"
  [headers.values]
    Content-Type = "text/markdown; charset=utf-8"

[[headers]]
  for = "/llms-full.txt"
  [headers.values]
    Content-Type = "text/markdown; charset=utf-8"
```

Or, through my preferred method in the `_headers` file located in my `static` folder.

```
/llms.txt
  Content-Type: text/markdown; charset=utf-8

/llms-full.txt
  Content-Type: text/markdown; charset=utf-8
```

## Hugo - Template

Having all the above, I am ready for my layout.

> When assessing a website for presence `llms.txt`, the agentic browsing does not *currently* care for it in subfolders and will look for the file in the domain root directory. However, if my site is in the root `/` and other languages in a subfolder `/en/`, I want to follow this pattern, like it is with sitemaps, and, especially on multilingual sites, to inform about other versions available along with `llms-full.txt`.

Starting with `layout/home.llms.txt`, that will generate `llms.txt`

```markdown
# {{ .Site.Title }} [Language: {{ .Language.Name | upper }}]

> {{ .Site.Params.description | default "Website content index for AI agents." }}

{{ if .IsTranslated -}}
## Alternative Languages
{{ range .AllTranslations -}}
- [{{ .Language.Label }}]({{ .Permalink }}llms.txt)
{{ end }}
{{- end }}

## Key Information
- Current Language: {{ .Language.Lang }}
- Full Content Archive: {{ with .OutputFormats.Get "llmsfull" }}{{ .Permalink }}{{ else }}{{ "llms-full.txt" | absURL }}{{ end }}

## Main Sections
{{ range .Site.Sections -}}
- [{{ .Title }}]({{ .Permalink }}): {{ .Description | default (printf "Browse the %s section." .Title) }}
{{ end }}

## Recent Content
{{ range first 15 .Site.RegularPages -}}
- [{{ .Title }}]({{ .Permalink }}): {{ .Summary | plainify | htmlUnescape | chomp }}
{{ end }}
```

And following up with `home.llmsfull.txt`, that will generate `llms-full.txt`

```markdown
# Full Content Archive for {{ .Site.Title }} [{{ .Language.Name | upper }}]

This document contains the complete text content of the website for comprehensive AI context and analysis.

{{ range .Site.RegularPages }}
---
## {{ .Title }}
- **URL:** {{ .Permalink }}
- **Date:** {{ .Date.Format "2006-01-02" }}
{{ with .Params.tags -}}- **Tags:** {{ delimit . ", " }}{{ end }}

### Content
{{ .RawContent }}

{{ end }}
```

This approach creates **universal and context-aware** output. It dynamically detects the current language, changes its labels automatically, and lists _only_ the pages belonging to that specific language.

For my (this) site, when Hugo builds `/llms.txt`, `.Language.Lang` is `"pl"`. The headers switch to Polish, and `.Site.RegularPages` loops through _only_ your Polish articles.

When Hugo switches to build `/en/llms.txt`, `.Language.Lang` becomes `"en"`. The headings instantly flip to English, and it loops through _only_ your English articles.

If you have a third or fourth language table in your `hugo.toml` in your design, this layout template requires zero code adjustments and works flawlessly!

{{% ads-in-article %}}

---

It is in such a way, with simple implementation, that if you want this or not, all is done in "set and forget" mode, and PageSpeed Insights under Agentic browsing will report your `llms.txt` without any issues.

Here are my files, generated after deployment, if you want to analyse how they look and what they contain:

* [https://dariusz.wieckiewicz.org/llms.txt](https://dariusz.wieckiewicz.org/llms.txt)
* [https://dariusz.wieckiewicz.org/en/llms.txt](https://dariusz.wieckiewicz.org/en/llms.txt)

* [https://dariusz.wieckiewicz.org/llms-full.txt](https://dariusz.wieckiewicz.org/llms-full.txt)
* [https://dariusz.wieckiewicz.org/en/llms-full.txt](https://dariusz.wieckiewicz.org/en/llms-full.txt)


---
## Switching Away from Apple Watch: A Downgrade and an Upgrade at the Same Time
- **URL:** https://dariusz.wieckiewicz.org/en/switching-away-from-apple-watch/
- **Date:** 2026-05-20
- **Tags:** Apple Watch, Smartwatch, Huawei Watch GT 5 Pro, Hybrid Smartwatch, Fitness Tracker, Battery Life, Digital Detox, Withings ScanWatch 2, Garmin Venu 4, Xiaomi Smart Band

### Content

As an iPhone user, it is quite natural to choose Apple-branded devices to fulfil everyday needs. My first Apple Watch was a Series 4, followed by a Series 6. After a few years, I finally moved to the Series 10. This time, for myself at least, I am not looking for any further upgrade come September 2026, to whichever series arrives next.

*Twenty years ago, I remember buying ringtones for my mobile phone; whereas now, my current phone is silent most of the time, with certain exceptions for important calls.*

I have been a happy user of the Apple Watch for years. I do not have anything against it, apart from one thing. The device itself has become superior due to its medically graded sensors. We always hear stories of how the Apple Watch saved someone's life by early detection of conditions that could lead to life-threatening situations.

Now that I am in my mid-forties, I look at that aspect much closer. For me, health features have become a major selling point. However, other aspects have slowly started to become annoying.

All measurements are done in the background and nicely synchronised with my device. The communication features, however, have become more of a nuisance, especially during stressful days at work. The constant buzzing has become a distraction rather than a useful feature.

Over recent months, I tried to break ties with my watch-screen addiction. It came to the point where I really wanted something that felt less like a phone on my wrist and more like an ordinary watch—but without losing those vital measuring capabilities.

**So, I looked for an alternative.**

<!--more-->

Before I moved to the Apple Watch, I had been using Xiaomi Mi Bands (currently branded as Xiaomi Smart Bands).

Starting with the first generation, which did not even have a screen but just three LED dots, I went through various models. I still have the Generations 6, 7, and 8 at home, and my daughter will shortly be using the latest 10th Generation.

I used the Mi Band when I was still a heavy Android user. Even when I moved into the Apple ecosystem, I still managed to sync my data from the bands wherever I needed using dedicated apps.

My first Apple Watch was a gift and a significant upgrade from the Mi Band at the time, so I stuck with the ecosystem right up until the Series 10.

I skipped the Series 11, and this year I started rethinking an alternative. Fortunately, there is a huge number of choices on the market.

I want a watch that looks good and measures what is needed accurately, but lasts a reasonable length of time before I "need" to replace it.

With the Apple Watch Series 6, I held onto it until the Series 10 arrived—not because everything was perfect, but rather the opposite.

My Series 6 eventually failed, but [Apple didn't fail me](/en/apple-service-experience-to-infinity-and-beyond/). When my battery degraded, I received a replacement, even though I no longer had a warranty or AppleCare. Here, the consumer rights ["SAD FART" rule](https://www.moneysavingexpert.com/reclaim/consumer-rights-refunds-exchange/) probably helped, even though I didn't know as much about it then as I do now.

The main issue with the Apple Watch was the need to develop the habit of charging it every single day.

I have a nightstand where I place it before I go to bed. This allows me to maintain a full day of usage.

Here, however, I lost the ability to track my sleep. Despite the watch having that option, I would need to remember to charge it early in the morning and not forget to take it off the charger before leaving the house.

This became more of an annoyance than a useful feature, so I simply gave up on sleep tracking altogether.

The Xiaomi Mi (Smart) Bands had coddled me with their long-lasting battery life, which was counted in days rather than hours.

This is why I stopped looking into getting the next Apple Watch—at least until Apple fixes the battery in a meaningful way, extending its life to at least a few days.

I do not believe that this will happen anytime soon. This is why I decided to look elsewhere, especially since the competition on the market has managed to get this sorted!

## Withings ScanWatch 2

A hybrid smartwatch like the Withings ScanWatch 2 caught my attention (or perhaps a social media ad did).

It features physical, mechanical hands and a real watch face. Tucked inside is a tiny, greyscale OLED circle for notifications and health data. It looks like a premium traditional watch and is much more discreet.

Additionally, it boasts a staggering 30-day battery life. You could go on a month-long holiday without ever packing a charger.

Both Withings and Apple offer very accurate, medically graded sensors. The main pain point of the Apple Watch—battery life—is well rectified here.

My primary goal was to reduce my screen interaction with the watch and concentrate on long-term health monitoring.

Additionally, I want this device to last for years without becoming outdated and unreliable.

The Apple Watch is simply a tiny computer on your wrist that requires a lot of power to work. Because of that, and the pattern of daily charging, the battery degrades within two to three years. In contrast, the Withings will likely remain in use for four to seven years, if not longer.

Battery life and longevity are huge factors for me, whereas the price tag is less of an issue.

Devices like the Apple Watch lose value over time like everything else, though you can still recoup approximately 40–50% of the cost after a year.

If I were to change devices, I would like to at least sell one to buy the other without adding any extra cash, or just a bare minimum.

The problem with smartwatches, like phones, is the software. New software becomes increasingly demanding on old hardware, which naturally drives people to look for an upgrade.

Apart from the physical battery longevity, I looked at how long a device would be supported. I wanted to know if it would receive updates not just to its mobile app, but to the firmware itself. Maintaining longevity by having the firmware updated for as long as possible has become a must-have requirement for me, right behind battery life.

Because of the premium pricing on some models, I kept looking further for alternative devices that **look good**, work for a long time, and will be supported for years. I know this can be difficult to find, as that exact business model doesn't always benefit companies that rely on profit from selling new hardware every year.

## Garmin Instinct Crossover

Garmin was another hybrid watch that I analysed as a potential contender. Its price range was acceptable. Selling my Apple Watch would mean I wouldn't have to spend much out of pocket to put this device on my wrist. However, because I couldn't see the device in person, I worried from the pictures that it would look too bulky.

There was also one health feature missing from this device that I really wanted: an ECG. While perhaps not a total dealbreaker for everyone, it is a feature I prefer not to compromise on. Furthermore, some of its measuring features are not backed up by true, clinically verifiable data. This pushes it out of the medically oriented health category and places it firmly into the fitness tracker category, much like a Xiaomi Smart Band.

Analysing further features—or rather, the lack of them—I quickly decided to move on and look for something else.

Still, its promised 28-day battery life was a massive win against the Apple Watch.

As the Garmin felt more like a downgrade from a medical device to a fitness tracker, I considered going extremely cheap instead. Selling my Apple Watch 10 would give me back around £180. For that amount of money, I could go back to the Xiaomi Smart Band 10 (£40 at the time) and keep a significant amount of cash in my pocket!

I even dusted off my old Xiaomi Smart Band 7 and wore it for a few days to remind myself of the experience before spending any money.

## Xiaomi Smart Band 10

The Xiaomi Smart Band offers up to 21 days of battery life. The device is small and can be worn comfortably overnight, meaning tracking sleep patterns is an easy win.

However, this was still a massive downgrade to a simple fitness tracker rather than something that can proactively detect if something is wrong with your cardiovascular health.

I needed to re-evaluate my priorities and clarify what I genuinely need and want.

If I just want to count steps, track my activity through the week, and see basic sleep scores without spending a fortune, the Smart Band 10 is an incredibly strong contender.

Because I use an iPhone, there is always a downside due to limited, locked-down synchronisation with the built-in Apple Health and Fitness apps.

Relying on a third-party app causes minor friction and requires adjustments to daily routines to ensure the data stays in sync.

My goal was to find something that offers excellent value for money today, ticks all my boxes, and lasts a significant amount of time.

Overall, I want to feel like I *want* to upgrade, not that I *must* upgrade simply because an otherwise pristine device is failing due to a degraded internal battery.

## The Apple Pay Dilemma

While paying with a watch using Apple Pay was originally a phenomenal novelty, I quickly discovered that I actually pay with my iPhone 99% of the time.

Moving away from the Apple Watch would mean losing that wrist-based alternative form of payment. In the rare event that my phone dies (which hasn't actually happened to me yet), I would no longer be able to make a payment without carrying my physical wallet.

I was willing to lose this feature, but if it could be offered by an alternative device, it would be a huge win.

Here, the Xiaomi Smart Band 10 loses immediately. The UK version does not support contactless payments, and even the imported Chinese NFC model will not fulfil these duties due to a lack of regional bank support.

The Withings ScanWatch 2 also does not support contact-free payments. You can purchase third-party NFC-enabled watch straps, but they are not particularly secure.

## Breaking the "Check-In" Habit

My main goal, amidst a busy and stressful daily life, was to break the constant "check-in" habit.

The Apple Watch is explicitly designed to be looked at. Its vibrant, always-on screen invites you to check your rings, your heart rate, and your notifications dozens of times a day.

Because the Withings features a physical analogue face, it looks like a piece of jewellery or a classic watch. The tiny OLED sub-dial remains completely dark most of the time. You don't just "glance" at data; you have to intentionally press the crown to see anything. This small bit of physical friction is often enough to break the habit of constant, unnecessary checking.

This is where the "silent guardian" philosophy wins when switching away from Apple.

If a watch is designed primarily to be a timekeeper, running its medical algorithms quietly in the background, you quickly adopt the mindset that no news is good news. Having no distractions when you need to focus is a great way to break your psychological reliance on yet another screen.

Instead of managing and looking at your wrist constantly, you check the data once or twice a day in the designated smartphone app, and that is it.

Achieving peace of mind over data fatigue was always at the back of my mind when deciding where to go next.

## Battery Longevity

The Apple Watch battery degrades quickly because it is pushed to its absolute limits every single day and then recharged. That is 365 days a year, 365 charge cycles. It is no surprise that after two years, you are forced to look for an upgrade—not because the software or hardware has slowed down, but simply because the watch can no longer make it through a full day.

Charging a device every two weeks or once a month extends the battery's overall lifespan so drastically that the hardware can easily survive for five years or more.

If I were to buy another Apple Watch in September, the battery would inevitably dictate another replacement in two or three years. If I buy a ScanWatch 2 or a similar long-battery device, the cell should easily match the physical lifespan of the watch itself.

## Find My...

One of the features I rely on the most is the ability to find my misplaced phone by pinging it from my watch. Sometimes it is hidden under a blanket or left in another room, and that audible ping is incredibly handy.

Also, because the Apple Watch is quite expensive, I appreciate having the option to locate it on a live map if I happen to misplace it outside the house.

This is where the Find My network shines. Apple designed it so elegantly that even devices without an active internet connection (as I use the non-cellular Apple Watch) can securely ping off passing Apple devices to report their location on a map.

If I am going to buy an expensive device, I want that peace of mind. If my new device is much cheaper, losing it won't cause a massive financial strain. While missing out on a global tracking network isn't a total dealbreaker, losing the basic ability to ping my phone from my wrist feels less like a luxury and more like a necessity.

When I tested the Xiaomi Smart Band, this ping function did not work reliably with my iPhone.

The Withings is designed to be a standalone health instrument. It intentionally lacks many "smart" utility features to maintain its 30-day battery and distraction-free design.

While analysing my options, I came across another hybrid watch very similar to the Withings: the **Pininfarina Senso Hybrid**. However, this contender didn't bring quite enough to the table to justify a purchase—until I stumbled upon something else entirely.

## Huawei Watch GT 5 Pro (GT5 Pro)

In my search for an Apple Watch alternative, I discovered the Huawei Watch GT 5 Pro (GT5 Pro), which has been widely described as a "smartwatch disguised as a traditional luxury watch".

It looks fantastic, and as I researched further, it quickly became my strongest contender to replace my Apple Watch.

The version I analysed was the 46mm model, which is crafted from aerospace-grade titanium.

On the health front, it features a fully UK-approved, medical-grade ECG alongside continuous heart rate tracking, SpO2 monitoring, and highly accurate sleep analysis. It also includes stress and emotional mood detection which reviews show is incredibly accurate. This is something the Apple Watch requires a third-party app to achieve, sacrificing even more of its precious battery life.

The Huawei watch allows me to ping my phone when needed and offers a massive library of customisable watch faces. Most importantly, it offers up to 14 days of battery life.

Because the GT5 Pro looks like another fully-fledged "mini-computer" on your wrist, I was intrigued by how Huawei managed to achieve a two-week battery life where Apple completely fails.

It ultimately comes down to their HarmonyOS operating system, which is perfectly optimised alongside the internal hardware. Processes do not run constantly in the background; they are fired up strictly when needed. It is highly impressive.

As a counter-suggestion to this watch, some recommended the **Garmin Venu 3S**. However, that device feels much more like a sporty fitness tracker rather than a medical device disguised as a classic timepiece.

Going back to the Huawei option, the most interesting discovery (made just before I realised the newer GT6 Pro was hitting the market) was that I could purchase a pre-owned **GT5 Pro** in perfect condition for just **£99.99**. Compared to the trade-in value of my Apple Watch (£180), this switch would actually put cash back into my pocket.

**But would this be an upgrade or a downgrade?** I kept researching and asking questions.

The strongest elements of its physical design are the **titanium case and sapphire glass**. When buying a pre-owned device, the durability of these materials virtually guarantees that the watch remains in excellent, practically as-new condition.

Even though the software features and the battery itself will slowly age, the physical chassis is built to survive five years without major scratching or scuffing—unlike the softer aluminium of my standard Apple Watch Series 10.

There are, naturally, some **downsides** due to iOS limitations placed on third-party smartwatches. For example, I will not be able to reply to text messages directly from my wrist. You can do this if the watch is paired to an Android phone, but not with an iPhone.

While many would view that as a major downgrade, for me, it sounds exactly like what I am looking for. Reducing my wrist interactions pushes me toward a **forced digital detox**. I can read notifications on the watch to filter what is urgent, but if I really need to respond, I will physically take my phone out of my pocket.

If the goal is to stop obsessively checking my wrist, this limitation naturally breaks the habit. It is a downgrade and an "upgrade" at the same time.

Another commonly highlighted downside was the NFC chip, which apparently does not work with standard UK banks. While I can use Apple Pay seamlessly on my watch right now (even if rarely), I initially thought I would lose this feature entirely on the Huawei. **But that wasn't entirely true.** I will expand on this shortly.

The main disadvantage of the GT5 Pro is that **it is still a screen**.

Unlike the Withings, which features physical, mechanical hands, the Huawei still relies on an OLED digital display. Even if I configure it to use an "Always-On" classic analogue style watch face, it remains a glowing screen, which might not cure the checking habit quite as effectively as a genuine mechanical face.

---

An Apple Watch typically forces its user to upgrade every two to three years due to a degrading battery. Before deciding which direction to take, I want to map out how long this new device will last me.

My goal this time is to hit the five-year mark. Achieving that would be a massive benefit to my personal budget, allowing me to focus those funds elsewhere. This is exactly why I looked at Withings in the first place.

If, however, I can find a device that comfortably beats the three-year mark, offers two weeks of battery life, and still runs smoothly, that represents money well spent.

Given my desire to step off the continuous Apple upgrade cycle, stop constantly fiddling with my wrist, and secure a device that quietly monitors my health for the next five years, the pre-owned GT5 Pro deal for £100 sounded exceptional.

---

The GT5 Pro originally launched in September 2024. Huawei will likely provide software upgrades for two to three years from that date.

The **Apple Watch** is an incredible device with brilliant software. Apple will actively support a model with new watchOS updates for up to five years. **The catch** is that the physical lithium-ion battery is worn down by daily charging long before that software support window closes. You might have the newest watchOS version in year three, but if the watch dies by 2:00 pm, it becomes useless. Effectively, **the hardware fails before the software does.**

With watches like the GT5 Pro or the Withings ScanWatch 2, the dynamic shifts.

Sometime around 2027, Huawei will likely stop pushing new features, fresh UI animations, or major HarmonyOS updates to the GT5 Pro. The software will effectively be "frozen" in time.

However, because I will only be charging the GT5 Pro twice a month, the titanium hardware and the physical battery cell will easily survive well past 2029. **The hardware outlives the software support.**

If I am wearing the GT5 Pro in 2028 and it is no longer receiving major operating system updates, **it does not become a brick**. It will still track my ECG and heart rate flawlessly. It will still ping my phone to help me find it. It will still display the weather and the date. It will still hold a charge for over a week.

Furthermore, the companion Huawei Health app on the iPhone will continue to receive updates via the Apple App Store, meaning the watch will retain its ability to sync seamlessly with Apple Health.

**My Five-Year Plan**

If my goal is to have a device that keeps adding shiny new apps and gimmicky features every single September, the GT5 Pro will disappoint me by year three.

But if my goal is to buy a premium titanium watch today, step off the expensive annual upgrade cycle, and own a reliable tool that quietly monitors my health and finds my phone **until 2031**, the Huawei will comfortably go the distance precisely because the battery isn't being hammered on a charger every single night.

At the time of my analysis, in April 2026, the GT5 Pro is already roughly 18 months old, which makes it the perfect time to find a great pre-owned deal. Buying it for £99.99 represents excellent value for money.

## Garmin Venu 4

I spent a long time juggling different watches from various manufacturers in the hope of finding a device that ticks every single box as an Apple Watch replacement.

Then I came across the Garmin Venu 4, which hit the market in September 2025. Garmin specifically designed this model to bridge the gap between a rugged sports tracker and a sleek, lifestyle smartwatch.

Upgraded materials and health features, including a UK-cleared ECG, make it a strong competitor to the Apple Watch. However, its premium price tag would require me to invest a bit of cash upfront, without necessarily gaining a massive advantage over what I already have.

The Garmin Venu 4 ticks all my boxes, solves the battery life issue, and is nowhere near as bulky as standard Garmin sports watches. It can even accept phone calls directly on the wrist, something the Withings cannot do.

However, it is still a screen. It will still feel like wearing a glowing piece of technology, which might not break the instinctive "checking" habit as effectively as the Huawei's analogue styling or the Withings' mechanical hands.

Because this route would require me to invest over £200 out of pocket after selling my current watch, the Huawei Watch GT5 Pro remains the superior strategic play. It allows me to secure a premium titanium build for £100 while completely escaping the daily charging chore.

Looking for other models similar to the GT5 Pro, I also looked into the **Amazfit Cheetah 2 Pro**. Yet again, after analysing the features, it felt much more like a dedicated fitness tracker than a disguised health device imitating an ordinary watch.

The Amazfit Cheetah 2 Pro is a brilliant watch if you are actively training for a half-marathon—which I am not—but it is the wrong tool for my specific long-term goals.

The ultimate long-term health guardian that provides a titanium build, UK-cleared ECG, a 14-day battery, and phone-pinging capabilities still points me firmly toward the **Huawei Watch GT 5 Pro**.

---

When you start doing deep research online, **cookies** track your interests across the web, and suddenly your social media feeds are flooded with targeted advertisements. This is how I stumbled across an ad for the **Norm Two** watch, which I decided to investigate.

The **Norm Two** is arguably the most beautiful watch I have analysed. It brilliantly hides its digital screen to prevent you from obsessively checking notifications. However, beneath that stunning Danish minimalist design, it completely lacks the one feature I rely on most for long-term health monitoring: the medical security of an ECG.

**So, I decided to keep looking.**

As I currently own an Apple Watch Series 10, the tech world is anticipating the launch of the Series 12 this September. Hopes are always high, but I strongly doubt it will solve the most annoying struggle of the device: battery life. Recent leaks are already confirming this disappointing reality.

Ruling out the Apple Watch Ultra for being far too bulky and expensive, and the entry-level SE lineup for lacking an ECG altogether, the upcoming Series 12 will still chain me to a magnetic puck every single night. 

The £100 Huawei Watch GT5 Pro remains the most logical escape route.

It ultimately comes down to accepting a harsh, unavoidable compromise. No single manufacturer has managed to build a watch that combines 100% of the Apple Watch's deeply integrated software features with a genuine two-week battery life.

Right now, I have an opportunity to secure a premium titanium watch that completely frees me from the daily charging cycle for just £100.

This trade-off means compromising on things I vaguely mentioned earlier, such as the global Find My network. If I lose my Apple Watch somewhere, even when it is offline, it can securely use nearby Apple devices to broadcast its location back to my phone.

If I accept that losing the GT5 Pro means it cannot be tracked on a map, losing a £100 device hurts significantly less than losing a device worth over £400.

---

While I was contemplating which route to take, I explored going back to the basics with the Xiaomi Smart Band 10.

I ordered the latest version of the band, but before it arrived, I wore my old Band 7 for a few days just to adjust myself to the habit of syncing health data through a third-party app.

While wearing it, I realised that going with a budget tracker meant sacrificing too much. While I wouldn't want to buy the GT5 Pro at its full retail price (£189.99 at Argos at the time), and the newest flagship version would drain my budget further (£299.99 at Argos at the time), the £100 pre-owned offer I found was a compelling choice. I just needed a bit of encouragement to make the jump.

---

**The Upgrade:** Choosing the GT5 Pro gives me a two-week battery life housed in aerospace-grade titanium and sapphire crystal.

**The Medical Guardian:** Unlike the basic Xiaomi tracker, the GT5 Pro includes the UK-cleared ECG and arterial stiffness detection I require if I want a direct replacement for my Apple Watch's health suite.

**The Financial Win:** By selling my Series 10 for £180 and buying the Huawei for £100, I walk away with an £80 profit while still wearing a premium piece of hardware.

---

Stepping away from the Apple Watch is ultimately about breaking a psychological habit. Apple intentionally designs its watches to be highly interactive, demanding our attention and a nightly spot on the charger.

Both the Xiaomi band and the Huawei watch are designed to sit quietly in the background, doing their jobs without constant management.

If I make the jump, I am choosing battery freedom and mental focus in my busy daily life.

---

While I was finalizing my decision, another targeted advertisement popped up for the newly released **OnePlus Watch 4**.

However, as an iPhone user, I was quickly disappointed.

Unless I was planning to sell my iPhone as well (which I am absolutely not), the OnePlus Watch 4 would be completely useless to me.

Due to its underlying software design, it will not pair with iOS. You cannot get past the initial setup screen without an Android phone. If I bought it today, it would be nothing more than a £300+ titanium paperweight on my desk.

---

Downgrading from a medically graded device like the Apple Watch to a basic fitness tracker like the Xiaomi Smart Band 10 would likely result in quick disappointment.

While the Xiaomi is a phenomenal fitness tracker for the price (and if you are looking for a basic budget option, I highly recommend it), stepping up to the GT5 Pro restores clinical-grade health monitoring. When navigating your mid-forties, having a UK-cleared ECG built directly into the crown and continuous arterial stiffness detection offers a profound level of preventative reassurance that a £40 plastic band simply cannot provide.

## The Perfect Compromise?

After a long chat with a friend who used previous generations of the Huawei GT-series watches, I was finally convinced to give it a try.

Ultimately, if I change my mind, I can easily sell it without losing any money, or simply return it within 14 days to the shop I bought it from, risking only the cost of return postage.

So, while the Xiaomi Smart Band 10 still sits in its unopened box on my desk, **I ordered the Huawei GT5 Pro.**

As with all new technology I buy, I love to spend ime searching for more information to justify my choice.

I quickly put together a final comparison: **Apple Watch 10 vs. Huawei Watch GT 5 Pro**

* **UPGRADE – Battery Longevity**: I am moving from an 18-hour cycle to a 14-day cycle. Charging becomes a twice-a-month task rather than a daily requirement.
* **DOWNGRADE – Physical Security (Find My)**: The Apple Watch can be tracked on a live map anywhere in the country via the global Find My network. The Huawei lacks this capability; it uses a standard local Bluetooth ping to locate a handset nearby but cannot be tracked globally if the watch itself is lost.
* **UPGRADE – Build Quality**: The Pro model is crafted from aerospace-grade titanium with a sapphire crystal face as standard. It is significantly more durable than the aluminium Apple Watch and looks like a traditional mechanical timepiece.
* **SO-SO – Communication**: On the Huawei, I will receive notifications for texts, WhatsApp messages, and emails, but I cannot type replies or dictate messages like I can on the Apple Watch. Crucially, **these are features I wasn't actively using anyway.** It provides a "read-only" experience that naturally reduces screen time.
* **TIE – Health & Medical**: Both devices offer UK-cleared ECG and SpO2 monitoring. However, the Huawei provides more continuous 24/7 skin temperature tracking and arterial stiffness detection, whereas the Apple Watch focuses heavily on overnight baselines.

The final piece of the puzzle was another **TIE – Contactless Payments**.

If you read general information online about NFC support on Huawei watches in the United Kingdom, you will be quickly disappointed. Despite official statements noting that Huawei’s payment system isn't directly supported by major high street banks, there is an official, elegant workaround: **Curve**.

**Curve** acts as a financial intermediary, offering you a single physical or digital debit card behind which you can link multiple standard bank cards. It allows you to switch payment methods seamlessly or even "go back in time" to move a transaction from one card to another after the purchase is made.

This post isn't a review of Curve, but since I already use Curve as my daily financial tool, I was thrilled to discover that Curve officially supports Huawei hardware in the UK.

Thanks to this, you can use the NFC chip on the GT5 Pro seamlessly by installing the official Curve app via the Huawei ecosystem and syncing your card.

This bridges the gap left by Apple Pay on the Apple Watch beautifully!

## HarmonyOS

When I received my GT5 Pro, the very first thing I did—apart from charging it to 100%—was update its built-in firmware. After a series of consecutive updates, the watch successfully landed on HarmonyOS 6.

HarmonyOS is Huawei’s completely bespoke operating system.

A few years ago, when the US government restricted Huawei from utilising Google’s software ecosystem, the company was forced to build its own software platform from scratch.

For their smartwatches, they designed an incredibly efficient, lightweight system. HarmonyOS is the true "secret sauce" that allows the GT5 Pro to achieve its remarkable 14-day battery life.

Unlike Apple’s watchOS or Google’s Wear OS (which are heavy, resource-intensive systems running processes constantly in the background), HarmonyOS is highly optimised to draw power strictly when called upon.

The HarmonyOS 6 update on the GT5 Pro is a massive software drop. It brings a completely redesigned Emotional Wellbeing app, smoother UI animations, better system notification icons, and a fresh batch of customisable watch faces to my device.

With the officially available Curve app running on HarmonyOS, I found the ultimate UK smartwatch loophole and successfully enabled seamless contactless payments.

Because Curve is already my default payment method, I have completely neutralised the Apple Pay disadvantage. I can simply double-click the bottom hardware button and tap my wrist at any payment terminal exactly as I used to do (albeit rarely) with my Apple Watch. It is a massive win for daily convenience whenever I need it.

## Buyer's Remorse

To be perfectly honest, when I was doing my initial research and discovered the GT5 Pro, I didn't perform a thorough check to realise that the newer GT6 Pro had already been released. While finding out after the fact gave me a brief moment of hesitation...

**I started wondering if I had made the right choice.**

However, with HarmonyOS 6 fully deployed on the GT5 Pro (bringing it to parity with the software running on the GT6 Pro), I realized I had effectively bought 95% of the flagship GT6 Pro experience for a fraction of the cost.

I know that I have traded away the deeply integrated, highly connected "smart" features of the Apple Watch. In return, I have gained structural durability, battery freedom, and the traditional aesthetics of a luxury timepiece.

Switching to the GT5 Pro also brought the hidden benefit of financial peace of mind.

Wearing a fragile, £429 aluminium device on your wrist brings a subtle, subconscious daily anxiety. I used to invest heavily in plastic screen protectors just to maintain its resale value for the future.

I would find myself constantly protecting my arm against door frames to avoid hurting my pocket.

By switching to a £100 device built out of rugged aerospace titanium and sapphire crystal, I have regained the freedom to actually wear my watch as a rugged tool. Even in the absolute worst-case scenario where it is lost or physically destroyed in a few years, it owes me nothing. Securing £180 from selling my Apple Watch Series 10 makes this a total financial victory.

I have fully embraced the read-only notifications and modified my daily mindset accordingly.

Apple intentionally designs its watch to be a highly interactive wrist computer that constantly demands our attention, which inevitably drains both the tiny 18-hour battery and our personal focus.

Even though I generally do not answer calls on my wrist, I did wonder if it would at least be technically possible with the GT5 Pro.

Apple locks down its proprietary messaging protocols so tightly that only an Apple Watch can directly interact with incoming texts. That is why text notifications are strictly read-only on the Huawei watch when paired with iOS.

However, phone calls operate on standard, universal Bluetooth hands-free protocols. When a call comes in, my iPhone simply looks at the Huawei GT5 Pro and treats it exactly like a pair of wireless earbuds or a car's hands-free kit. Because the watch features a built-in microphone and speaker, the iPhone happily routes the audio straight to your wrist.

Some options, even when you don't use them daily, are simply worth having for emergencies.

I have been using the Huawei watch for three weeks now. The first week was quite intensive as I spent a lot of time playing with settings and exploring the UI. As with any technology honeymoon period, I drained the battery much quicker than normal, and it landed back on the charger after seven days. The second week looked significantly better; after a full seven days of standard use, the cell was still sitting at 51%. 

Currently, we are at the time of year where we are starting to hear the usual rumours regarding the Apple Watch Series 12, which will be presented in September 2026. Most of the leaks are bringing a bit of disappointment. If you are holding out for a massive breakthrough in battery life, it is unlikely to happen.

It would be amazing if Apple decided to implement the microkernel efficiency of HarmonyOS alongside the hardware optimization present in Huawei's wearables. However, doing so would require a significant, fundamental change in their architectural design. As we have seen over the years, that formula rarely changes much.

My switch has been entirely successful, and I look forward to seeing just how many years of enjoyment I get out of this watch.


---
## Do not let AI (Gemini) forget your thoughts when you need them.
- **URL:** https://dariusz.wieckiewicz.org/en/do-not-let-gemini-forget-your-thoughts/
- **Date:** 2026-05-09
- **Tags:** Gemini, Google Gemini, Gemini Apps, Google Activity, Privacy Checkup, auto-delete, auto-delete activity, activity

### Content

The AI interaction is becoming more and more common. We are getting a lot of useful information (a lot of crap as well) very quickly through it, saving us time and making us more productive.

> I will not be discussing here aspect we all fear now, that AI will be replacing us at work. Thats a total different subject. I will be thinking here from perspective of using the AI, Gemini in this case, to make myself more productive - **by embracing it**.

<!--more-->

At my current age, the **time** is the only thing that I am missing. This recalls this that summarises it perfectly.

[![The Life Cycle Balance - Time Money Energy](the_life_cycle_balance.png)](the_life_cycle_balance.png)

This is where the AI comes from.

Do not stick to the above. You will not be able to suddenly give yourself more time in a busy lifestyle; that's impossible.

Embrace AI, learn it, use it, let it save your time.

**Don't be a generation who will do everything they can to oppose the change, so it comes to the point that they will, eventually, be replaced by it.**

As we're getting older, our memory is getting worse over time. This is a natural part of ageing.

When we use AI, in my instance Gemini, we collect our "chats" in it with some valuable information; some of them we will recall and interact over time, **like a memory.**

The problem is that if we, humans, lose memory (thoughts), so does AI. I am not talking here about "context window size" of an AI chat; I am talking about whole chats going **puff!**

Over the last years, we all have become more **privacy-concerned**.

Using Google services, it is normal that we do not want Google to gather too much information about us. This is why from time to time we go through **[Privacy Checkup](https://myaccount.google.com/privacycheckup)** and clean some old stuff or set automatic deletion after some period of time.

**The problem is that this setting will also affect our chats with Gemini!**

I found out about this **the hard way**, where I lost one of my chats that I wanted to recall after 4 months, but they were gone.

**This was all my fault.** Not because I deleted it (as I even pinned this chat, but still got missing), but because I instructed when my old data is removed by Google itself.

Google respected it to the latter.

The settings that I used, before I embraced Gemini, were set in [My Activity](https://myactivity.google.com/myactivity). 

My Web & App Activity, I changed from default 18 Months to 3 months. Same with Timeline. The YouTube history I turned off.

It was after investigation, where my missing chats go, that I found out some of these settings, to be removed after 3 months, have been inherited by Gemini activity as well.

**On the above page there is no direct link to that, and this is where the confusion comes from.**

You need to go to the buried page of the [Gemini Apps activity page](https://myactivity.google.com/product/gemini) to see what is set that affects retention of your chats (or click on the **Activity** button under your chats).

[![Gemini Apps activity](Gemini_Apps_Activity.png)](Gemini_Apps_Activity.png)

There, in the **Choose an auto-delete option**,  I found out about the inheritance of my other preferences. 

[![Choose an auto-delete option for your Gemini Apps activity](Gemini_Apps_Activity_auto-delete.png)](Gemini_Apps_Activity_auto-delete.png)

**Three months.**

After that period, the chats that I haven't interacted with will be automatically deleted, **even** if they are pinned in your Gemini app.

I changed it personally to **Don't auto-delete activity**.

I learned this hard way by losing some valuable information that I gather in some chats. Nothing that I cannot recreate, but this, again, is all about the **time** that I need to waste to do so. **Time** is what I get less and less each day in this world.

If you are using Gemini, head to [Gemini Apps activity page](https://myactivity.google.com/product/gemini) today and check your settings to avoid any losses.

---

The **Don't auto-delete activity** may be a bit extreme. Maybe the **18 months** will be sufficient, but you don't know how important the information you gather over years will be valuable for you.

Where I keep other activities restricted more, this one I want to be there when I need it.


---
## Building your own Attended Sysupgrade server for an OpenWrt router
- **URL:** https://dariusz.wieckiewicz.org/en/building-your-own-asu-openwrt/
- **Date:** 2026-03-29
- **Tags:** OpenWrt, Networking, Sysupgrade, Attended Sysupgrade, Router Update, Firmware Update, Ubuntu Server, ImageBuilder

### Content

As it happened, Attended Sysupgrade with the latest version of OpenWrt 25.12, since it became the default approach to update OpenWrt devices, started seeing a spike in popularity.

When I first tried this, I was either 1st in the queue or just a few users behind. Days later, when the next version (25.12.1) was released, this jumped to around 200-300. Now, with another release (25.12.2), [the servers](https://sysupgrade.openwrt.org) cannot handle it anymore.

> Server response: server overload, queue contains too many build requests: 1001

Following a discussion with one of my visitors, it was suggested that I use someone else's server for Attended Sysupgrade, but there is always a catch to that. The recommended server uses SNAPSHOT builds as default, which I do not recommend for a production or business environment. While you can play with it on a home router, in business, you need to rely on stability.

I have been thinking that maybe I will create my own server for that purpose. I already have a small mini-PC at home (and at work) — a Chromebox repurposed as an Ubuntu Server running Docker. My usage is not massive, and there is plenty of computing power available.

<!--more-->

> At the time of writing, I am using an Asus Chromebox 3 with ChromeOS removed and full UEFI installed using the [MrChromebox.tech](https://docs.mrchromebox.tech) solution.

Because of that, I have been thinking: **why not build my own solution for Attended Sysupgrade when I need it, to avoid waiting?**

As Attended Sysupgrade is gaining popularity, I do not see the situation improving anytime soon. For some companies that need to keep their devices updated to comply with legal requirements, waiting is not an option.

> Building an Attended Sysupgrade server is another learning curve to add to my wide range of skills.

Digging into that, I found a confirming answer: **Yes**, I can **build** my own solution, and my devices are more than capable of that.

Before I go any further, I need to understand how this all works.

## How a local Attended Sysupgrade (ASU) actually works

When you request a sysupgrade, the server doesn't compile the firmware from scratch (which takes hours). Instead, it uses the **OpenWrt ImageBuilder**. The ImageBuilder simply takes pre-compiled packages (`.ipk` files) and combines them into a final firmware image for your specific router.

> Having analysed the performance of my devices, the process will likely take just few minutes to complete locally, compared to waiting hours in the public queue.

{{% ads-in-article %}}

## Installing the official Attended Sysupgrade (ASU) Docker image

The good news is that **[OpenWrt maintains an official Dockerised version of the Attended Sysupgrade server](https://hub.docker.com/r/openwrt/asu).** That's a big win!

> You need to have Docker installed on your designated device before moving forward. I will not be covering that here and will assume you have this sorted already.

### Attended Sysupgrade (ASU) requirements

The ASU architecture requires:

1. **A Redis database:** To queue the build jobs and cache previously built images.
2. **The ASU server:** The web/API interface that your router talks to.
3. **The ASU worker:** The "muscle" that actually spins up temporary ImageBuilder containers to compile the firmware.

### Create a Docker Network

Because we will be dealing with three separate containers, they need a shared network to communicate with one another.

```bash
sudo docker network create asu-network
```

### Start the Redis Cache

This spins up a lightweight Redis instance and attaches it to our new network.

```bash
sudo docker run -d \
  --name asu-redis \
  --network asu-network \
  --restart unless-stopped \
  redis:alpine
```

### Start the ASU server (API)

This is the container our router will interact with. I map the internal port `8000` to my preferred port for this purpose, `8123`.

```bash
sudo docker run -d \
  --name asu-server \
  --network asu-network \
  -p 8123:8000 \
  -e REDIS_URL="redis://asu-redis:6379/0" \
  -e PUBLIC_PATH="/app/public" \
  -v asu-data:/app/public \
  --restart unless-stopped \
  openwrt/asu:latest \
  uv run uvicorn --host 0.0.0.0 asu.main:app
```

### Start the ASU worker

This container waits for jobs in the Redis queue and executes them.

> The command below must map the `/var/run/docker.sock` file. This allows the worker container to talk to the host machine's Docker daemon so it can spin up the isolated OpenWrt ImageBuilder containers required to pack your firmware safely.

```bash
sudo docker run -d \
  --name asu-worker \
  --network asu-network \
  -e REDIS_URL="redis://asu-redis:6379/0" \
  -e PUBLIC_PATH="/app/public" \
  -e CONTAINER_SOCKET_PATH="/var/run/docker.sock" \
  -v asu-data:/app/public \
  -v /var/run/docker.sock:/var/run/docker.sock \
  --restart unless-stopped \
  openwrt/asu:latest \
  uv run rqworker --logging_level INFO
```

### Verifying the setup

Once all three commands have been run, you can check that everything is working by opening a browser and navigating to your device's IP address, for example:

```
http://192.168.1.12:8123/api/distros
```

If it returns a bit of JSON text showing the supported OpenWrt distributions, your server is alive and kicking!

Mine returned:

```
{"detail":"Not Found"}
```

If you see that, or something similar, your Docker container is up, running, and successfully answering web requests on port `8123`.

If you head directly to the address below (without `/api/distros`), you will land on a similar interface to the [official sysupgrade.openwrt.org](https://sysupgrade.openwrt.org).

[![The homepage of the OpenWrt Sysupgrade Server](OpenWrt_Sysupgrade_Server_homepage.png)](OpenWrt_Sysupgrade_Server_homepage.png)

{{% ads-in-article %}}

## Connecting our router to our local ASU server

Now that we know our local server is alive and working well, we can point your OpenWrt router to it.

1. Log into your router's OpenWrt LuCI web interface.
2. Navigate to **System** -> **Attended Sysupgrade**.
3. Click on the **Configuration** tab.

[![LuCI - Attended Sysupgrade - Configuration Tab](Attended_Sysupgrade_LuCI_Configuration_Tab.png)](Attended_Sysupgrade_LuCI_Configuration_Tab.png)

4. Change the Server Address from `https://sysupgrade.openwrt.org` to your server's IP and port.

> Make sure you use just the base URL without any API paths at the end. For example: `http://192.168.1.12:8123` (replace this with your actual server IP).

5. Click **Save & Apply**.

Once that is saved, switch back to the **Overview** tab in Attended Sysupgrade and click the **Search for firmware upgrade** button.

[![LuCI - Attended Sysupgrade - Overview - Search for firmware upgrade](Attended_Sysupgrade_LuCI_Overview_Search.png)](Attended_Sysupgrade_LuCI_Overview_Search.png)

### When your router fails to communicate with your local ASU

When I set my own server address in my OpenWrt and clicked the **Search for firmware upgrade** button, I got stuck with:

```
Searching...

Searching for an available sysupgrade of 25.12.1 - r32768-b21cfa8f8c
```

My Docker logs showed my previous test attempts when I loaded `http://192.168.1.12:8123/api/distros` in my browser, but there are no signs of my router communicating with it.

For some reason, it may be that the router is blocking itself from accessing the LAN IP. This is a bit strange, but I will need to check.

I logged in via SSH to my router and executed:

```bash
curl -I http://192.168.1.12:8123/api/v1/overview
```

OR if curl isn't installed:

```bash
wget -qO- http://192.168.1.12:8123/api/v1/overview
```

and got

```
HTTP/1.1 405 Method Not Allowed
date: Sun, 29 Mar 2026 07:56:52 GMT
server: uvicorn
allow: GET
content-length: 31
content-type: application/json
```

Meaning, despite `HTTP/1.1 405 Method Not Allowed`, my router and my Ubuntu server are talking to each other perfectly. There are no firewalls blocking the connection, and the network routing is spot on. The logs on the Docker container (`asu-server`) are also showing communication from my router.

Time to run another command.

```bash
owut check --verbose
```

This will confirm if the router can talk to our own ASU server and display more information as to why it may be failing.

---

If you do not have the `owut` package installed on your system, add it using the command below:

```bash
apk update
apk add owut
```

---

All looks good, so I investigated my LuCI connection in Chrome with DevTools open and found some errors when I pressed the button to search for new firmware, relating to **CORS (Cross-Origin Resource Sharing)** and **301 Redirects**.

**I could theoretically stick with SSH and do `owut upgrade` to proceed, but I want to fix the UI.**

The issue is that my browser demands the server sends an `Access-Control-Allow-Origin` header to prove it is allowed to share data. The official `openwrt/asu` Docker container currently does not send this header by default, so we need to fix that.

Let's start by going backwards a bit and removing `asu-server` for now.

```bash
sudo docker stop asu-server
sudo docker rm asu-server
```

On the server, I will create a file that will grab the existing app and inject the headers into the browser.

```bash
nano cors_wrapper.py
```

Paste the following code into the file.

```bash
from asu.main import app
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
```

**Now let's run the container with the wrapper**.

```bash
sudo docker run -d \
  --name asu-server \
  --network asu-network \
  -p 8123:8000 \
  -e REDIS_URL="redis://asu-redis:6379/0" \
  -e PUBLIC_PATH="/app/public" \
  -v asu-data:/app/public \
  -v $(pwd)/cors_wrapper.py:/app/cors_wrapper.py:ro \
  --restart unless-stopped \
  openwrt/asu:latest \
  uv run uvicorn --host 0.0.0.0 cors_wrapper:app
```

Now, when the browser asks for the `/api/v1/overview` endpoint without a trailing slash, the Python server issues a `301 Redirect` to add the slash. Previously, the browser blocked that redirect because it lacked CORS headers. Now, the `CORSMiddleware` guarantees that every single response—even redirects—contains the `Access-Control-Allow-Origin` header, allowing your browser to follow the path perfectly.

Now, when I press the **Search for firmware upgrade** button, I get an instant response:

[![New firmware upgrade available - Request firmware image](New_firmware_upgrade_available.png)](New_firmware_upgrade_available.png)

And so I pressed **Request firmware image**, only to get **Error building the firmware image**.

{{% ads-in-article %}}

### Error building the firmware image - Podman not found

```
podman.errors.exceptions.NotFound: 404 Client Error: Not Found
```

Recently, the OpenWrt developers completely rewrote the ASU backend. For security reasons (to prevent builds from having too many permissions), they hardcoded the worker to strictly use **Podman** instead of Docker to spin up the ImageBuilder containers.

Even though we are successfully running the worker inside a Docker container, the Python script inside that container is using a Podman-specific library (`podman.version()`). It reaches out to the `/var/run/docker.sock` we gave it and expects Podman to answer, but Docker answers instead. The script asks for a Podman-specific API path, Docker replies with a "404 Page Not Found", and the whole build crashes.

The good news is that we do not need to tear down our Docker setup. We just need to install Podman alongside Docker on your Ubuntu Server and hand the Podman socket to the worker container instead.

```bash
sudo apt update
sudo apt install podman
```

By default, Podman doesn't keep a background service running like Docker does. We need to turn on its listening socket so the ASU worker can talk to it.

```bash
sudo systemctl enable --now podman.socket
```

**Now we need to recreate the ASU Worker.**

```bash
sudo docker stop asu-worker
sudo docker rm asu-worker
```

Then, run the corrected worker command. Notice that the two paths at the bottom have changed to `/run/podman/podman.sock`.

```bash
sudo docker run -d \
  --name asu-worker \
  --network asu-network \
  -e REDIS_URL="redis://asu-redis:6379/0" \
  -e PUBLIC_PATH="/app/public" \
  -e CONTAINER_SOCKET_PATH="/run/podman/podman.sock" \
  -v asu-data:/app/public \
  -v /run/podman/podman.sock:/run/podman/podman.sock \
  --restart unless-stopped \
  openwrt/asu:latest \
  uv run rqworker --logging_level INFO
```

Because LuCI tends to keep the last error message in its cache, clicking **Request firmware image** will return the previous message. To bypass this, we need to either `reboot` the router or clear some temporary files created by ASU (which are typically flushed upon a router reboot).

Run the following command on your OpenWrt router:

```bash
rm -rf /tmp/owut* /tmp/attended*
```

Let's head back to our OpenWrt web interface and click that **Request firmware image** button one more time. The worker will now successfully talk to Podman, download the ImageBuilder, and compile our custom firmware.

**That is the theory!**

[![Queued - Request in build queue position 0](Queued_position_0.png)](Queued_position_0.png)

[![Building firmware - Progress - 10% Setting up ImageBuilder](Building_firmware_10_ImageBuilder.png)](Building_firmware_10_ImageBuilder.png)

As in my instance, it failed again.

```
invalid config provided: pasta networking is only supported for rootless mode
```

> Anybody fancy some pasta? 🍝

**Pasta** is the rather oddly named network driver that Podman uses to connect containers to the internet securely.

This is because in our previous step, we started Podman using `sudo systemctl`. This turned on the **Administrator** Podman socket. The worker script checked the socket, saw it was running as `root`, panicked because it expected a **rootless user**, and threw a "500 Internal Server Error".

**Let's take a step back again.**

Run this to shut down the `root` level Podman socket we created earlier.

```bash
sudo systemctl disable --now podman.socket
```

Now, we turn on the socket for your standard, non-administrative Ubuntu user.

> **Do not** use `sudo` for this command! It must be run as your normal user.

```bash
systemctl --user enable --now podman.socket
```

However, because we are likely logged in via SSH to our Ubuntu Server, Ubuntu tries to save resources by not spinning up a dedicated background `systemd` manager for your specific user account. When you ask it to start a user-level service like Podman, it fails because the user systemd instance isn't running.

We need to tell Ubuntu to let your user account (my user: `darek`, replace this with yours accordingly) run background services permanently, even when you log out. This is called "lingering".

Before that, let's remove any locks that may be in place in the system.

```bash
sudo rm -rf /run/user/1000/podman
```

**Let's enable "Linger" for our User.**

```bash
sudo loginctl enable-linger darek
```

Sometimes SSH sessions drop a crucial environment variable that systemd needs to find your user folder. Let's force it, just to be safe:

```bash
export XDG_RUNTIME_DIR=/run/user/$(id -u)
```

Now that your user is authorised and the path is set, lets start the Socket Again.

```bash
systemctl --user enable --now podman.socket
```

---

Finally, we need to swap the socket path in our Docker command for the worker container.

Let's start by removing `asu-worker`.

```bash
sudo docker stop asu-worker
sudo docker rm asu-worker
```

And spin it back up with the correct rootless socket path.

> If, for some reason, your user ID is not `1000`, you will need to change the `1000` in the second `-v` line; however, 99% of the time on Ubuntu, it is exactly `1000`.

```bash
sudo docker run -d \
  --name asu-worker \
  --network asu-network \
  -e REDIS_URL="redis://asu-redis:6379/0" \
  -e PUBLIC_PATH="/app/public" \
  -e CONTAINER_SOCKET_PATH="/run/podman/podman.sock" \
  -v asu-data:/app/public \
  -v /run/user/1000/podman/podman.sock:/run/podman/podman.sock \
  --restart unless-stopped \
  openwrt/asu:latest \
  uv run rqworker --logging_level INFO
```

Let's run our quick cache-clearing routine on our OpenWrt router.

```bash
rm -rf /tmp/owut* /tmp/attended*
```

Head back to LuCI and hit that green button again.

[![Building firmware - Progress - 10% Setting up ImageBuilder](Building_firmware_10_ImageBuilder.png)](Building_firmware_10_ImageBuilder.png)

This time, I passed the 10% point.

[![Building firmware - Progress - 30% Validating package selection](Building_firmware_30_Validating.png)](Building_firmware_30_Validating.png)

[![Building firmware - Progress - 50% Generating firmware image](Building_firmware_50_Generating.png)](Building_firmware_50_Generating.png)

[![Successfully created firmware image](Successfully_created_firmware_image.png)](Successfully_created_firmware_image.png)

```
11:16:35 Successfully completed asu.build.build(BuildRequest(distro='openwrt', version='25.12.2', version_code='', target='...) job in 0:05:43.333466s on worker 172b8078680c4f64989ef57693b834a2
11:16:35 default: Job OK (f7b1b5f55f2de817f4d9ed18026a1ac8c31d664ef30a612d5430f14d899cb409)
11:16:35 Result is kept for 10800 seconds
```

It took slightly under 6 minutes (on my ASUS Chromebox 3), and my locally generated image was ready. I kept the box ticked to keep the configuration, and after the reboot, everything has been working great!

This way, I created my own independent ASU server, which will remove pressure from the OpenWrt servers and let me have better control over the overall process!


---
## Attended Sysupgrade – The right way of updating OpenWrt Firmware
- **URL:** https://dariusz.wieckiewicz.org/en/attended-sysupgrade-openwrt/
- **Date:** 2026-03-07
- **Tags:** OpenWrt, Networking, Sysupgrade, Attended Sysupgrade, Router Update, Firmware Update

### Content

**I should have discovered this years ago!**

I never came across this feature, and it was apparently available a few versions ago. Just now, when version 25.12.0 was officially released, I learned how to simplify upgrading from one version to another (I did this from 24.10.2 to 25.12.0).

I have developed [my own routine for backing up packages and configuration files, installing a new image, and restoring everything](/en/firmware-update-openwrt/). To be honest, **I always hate doing that**, especially in a business environment, as it always requires some downtime. This is why I sometimes fall behind on some sub-versions of OpenWrt firmware (I was still on 24.10.2 instead of 24.10.5).

When you cannot afford extended downtime, you can minimise it with this approach: [**Attended Sysupgrade (ASU)**](https://openwrt.org/docs/guide-user/installation/attended.sysupgrade).

<!--more-->

On its official page, you can read:

> A couple of clicks and a short wait let you download and install a new image with your previous packages and configuration. This eliminates the need to make a list of packages you installed manually or re-enter the configuration just to upgrade your firmware. 

**This sounds like a dream**, as this was the only feature that all OpenWrt users were missing – upgrading the firmware while everything stays the same.

> This package comes preinstalled by default in the OpenWrt 25.12 series, along with the new package manager **apk** instead of **opkg**.

It's like on routers with stock firmware: when you upgrade the firmware, your config stays there. Let's see if that magic is indeed there. **Spoiler alert: it is!**

I was interested to see if I could simply update my router from OpenWrt 24.10.2 to 25.12.0 without losing **time** on backing up and restoring, as I have tended to do in the past.

> Of course, I did my own backup the way I always do, just in case, but I was full of hope at this stage that all would go as planned.


On my current router, running **24.10.2**, I installed **Attended Sysupgrade (ASU)**:

```bash
opkg update
opkg install luci-app-attendedsysupgrade
```

When you request firmware with ASU, if any of the packages on your system do not exist in the latest version, it will fail, warn you about what is missing, and prevent you from moving forward — **and that's a good thing!** I will explain further.

There is, however, one caveat that you need to remember. 

**ASU** will not back up the `/root` folder by default, or any custom configuration in the `/etc/` folder, if you do not tell them to do so in advance.

You can, of course, change that. If you follow my other OpenWrt posts, you know you can add files and folders to be kept by editing `/etc/sysupgrade.conf` or, from **LuCI** > **System** > **Backup / Flash Firmware**, adding them in the **Configuration** tab. **Simple!**

**Important note!**

When jumping between major releases (such as from 24.x to a future 25.x release), be aware that underlying software structures occasionally change. Whilst your configuration files will be preserved by the backup mechanism, it is always good practice to download a manual backup archive (.tar.gz) to your computer before initiating the upgrade, just in case a major syntax change requires you to reset and manually reconfigure certain services.

> There was a very significant jump from version 23.x to 24.x in the past; due to many underlying changes with Firewall4 and interface names, I often needed to start from scratch. With 24.10 to 25.12.x, you don't need to worry as much.

**Let's see how ASU works in practice!**

---

{{% ads-in-article %}}

## Attended Sysupgrade (ASU) in practice

Once you have installed ASU and logged into the LuCI web panel, you will see a new option under **System** called **Attended Sysupgrade**, where you will be greeted with the following:

[![Attended Sysupgrade](01_Attended_Sysupgrade.png)](01_Attended_Sysupgrade.png)

After clicking the green **Search for firmware upgrade** button, you will then be presented with the options available for your device.

[![New firmware upgrade available 24.10.5](02_New_firmware_upgrade_available_24_10_5.png)](02_New_firmware_upgrade_available_24_10_5.png)

Because my device was on 24.10.2, the next version presented to me was 24.10.5. From the dropdown menu, I could then choose version 25.12.0.

[![New firmware upgrade available 25.12.0](03_New_firmware_upgrade_available_25_12_0.png)](03_New_firmware_upgrade_available_25_12_0.png)

When you are ready to do so, click (**NOT YET!**) the green **Request firmware image** button.

**But, before you do that...**

---

Make sure to go to **System > Backup / Flash Firmware** and then to the **Configuration** tab.

There, you must add all the custom configuration files and folders you have on your router that must be maintained, backed up, and restored upon upgrade.

For example, mine looks like this:

```
# /etc/example.conf
# /etc/openvpn/
/etc/ssl/
/etc/cloudflared/
/root/
```

I want to keep the **ssl** folder and its contents, as well as **cloudflared** and my **/root** folder.

I also highly recommend that you **Generate archive** from the **Actions** tab and check that the archive is extractable (not corrupted). If, for some reason, it is corrupted, refer to my post: [How to Backup Your OpenWrt Router When Built-in Tools Fail](en/how-to-backup-your-openwrt-router/).

> If your firmware should, for some reason, update with the new packages but lose its configurations, you can easily upload your backup via **System** > **Backup / Flash Firmware** > **Restore backup**, and have everything back as it was in no time.

**Moving on...**

---

Your router will communicate with the official OpenWrt servers and check what is available. At this time, it will check which packages are currently on your router and what is available in the repository.

If the server detects that any of your packages have not yet been moved to the new version, it will throw an **error**.

[![Error building the firmware image](04_Error_building_the_firmware_image.png)](04_Error_building_the_firmware_image.png)

From this error screen, you will see that the package (`luci-app-nft-qos`), which is available in the 24.10.x repository, is not yet available in 25.12.x.

Because of that, you cannot move forward and you need to resolve this issue first.

**You have two options:**

1. Hold off on the update until the package upon which you rely on your current device becomes available, or
2. Remove the package that is causing the conflict, **reboot** your device, and try again.

Once the conflict is resolved, we can move on.

---

{{% ads-in-article %}}

Now click **Request firmware image** and wait.

[![Building firmware - Received build request](05_Building_firmware_Received_build_request.png)](05_Building_firmware_Received_build_request.png)

Firstly, the server will validate the packages that need to be included in your firmware.

[![Building firmware - Validating package selection](06_Building_firmware_Validating_package_selection.png)](06_Building_firmware_Validating_package_selection.png)

Then it will build the firmware for you.

[![Building firmware - Generating firmware image](07_Building_firmware_Generating_firmware_image.png)](07_Building_firmware_Generating_firmware_image.png)

Once the firmware is successfully created, you will be presented with the following information.

[![Succesfully created firmware image](08_Succesfully_created_firmware_image.png)](08_Succesfully_created_firmware_image.png)

Before you click the green **Install firmware image** button, make sure that the option **Keep settings and retain the current configuration** is ticked as well.

[![Installing sysupgrade image](09_Installing_sysupgrade_image.png)](09_Installing_sysupgrade_image.png)

The installation will then commence.

Wait patiently until your router applies everything and reboots into the new version.

If all goes well, your router should restart with the new firmware, with all the packages that you previously installed (using the official installation method) and all configurations applied.

---

If you have upgraded to version 25.12.0 for the first time and you log back into LuCI, you will be greeted with a question asking if you want to automatically check for new firmware versions.

[![Check online for firmware upgrades](10_Check_online_for_firmware_upgrades.png)](10_Check_online_for_firmware_upgrades.png)

If you decide to **enable checking**, you will be asked, in the next step, to add one line to the router configuration.

[![Check online for firmware upgrades - Configuration changes](11_Check_online_for_firmware_upgrades_Conf_changes.png)](11_Check_online_for_firmware_upgrades_Conf_changes.png)

You just need to click **Save & Apply** and you are ready.

---

This method of upgrading OpenWrt will definitely help more users to supercharge their compatible routers, not only extending their lifespan but also increasing their privacy.

👏 🙌

---

**PS.** If you installed [Cloudflare Tunnel on your OpenWrt Router](/en/adding-cloudflare-tunnel-to-openwrt-router/), this package was installed manually. Despite the fact that it updates itself regularly, you will need to re-install it (re-download) after the first reboot with the new firmware. For that, refer to the [Install the official cloudflared package](/en/adding-cloudflare-tunnel-to-openwrt-router/#install-the-official-cloudflared-package) step. Remember that in the 25.12 series, **opkg** has changed to **apk**.


---
## Proving What You Wrote Is Yours in the Age of AI
- **URL:** https://dariusz.wieckiewicz.org/en/proving-what-you-wrote-is-yours-in-the-age-of-ai/
- **Date:** 2026-02-14
- **Tags:** AI Detectors, Academic Integrity, Ethics, Genuine Work, Stop False Accusations, Human Generated, Fair Grading, AI Challenge, Writing

### Content

We are living in times when AI is becoming a daily tool we use at work and at school.

A lot of students support themselves by using AI to learn new things, quickly find information, and extend their knowledge.

I am from a generation who finish schools and University before AI existed. During my Uni times, it was the Internet boom, and access to information started pushing out the need to visit a library to gain knowledge. Yet, despite all of that, I am proud that all my hard work put towards my education was my own.

In current times, a lot of students want to go the easy route. Same as with the workplace, where it’s hard to find a hard-working employee on very demanding job role for an average salary.

People no longer want to work hard to earn money. Everybody is looking into the easiest route earing tones of money by doing the minimum. It’s not working like that, at least not for the majority of us. If you are the person who thinks that's how it's working, if you are not a millionaire right now, then you are delusional.

Same with education. Knowledge that you gain is for you to be a better person in future. You're learning stuff to use in your future life. If you decide to go the easy route and ask AI to write you a work that you will just copy and paste, then submit to a tutor, there is something significantly wrong here.

You can do this; nobody is stopping you (almost) from doing that, but how much are you learning from that?

<!--more-->

Teachers know that, and in current AI times, they need to bring their own tools to fight it. The problem is that the tools, that they are using are mostly useless.

The tools that teachers are using are, in many cases, unsanctioned, unverified and most of the time are highlighting text, that is 100% your own work, as a 90% written by AI!

This is a total joke of what is happening right now, and that must change.

The issue is so significant that it is discouraging the genuine students, putting a lot of effort into searching for information and writing their own work, where the feedback received from the tutor is that 70% of their work is AI and they need to re-write it!

**Be resilient and confident.**

{{% ads-in-article %}}

Do not let teachers tell you something that is not true, especially when you are 100% sure that your work is your own!

If you are a foreigner whose English language wasn't the first language you learned, the way and how you write and how you compose sentences is way different from native English speakers.

As a foreigner, your work is more likely to trigger a warning by AI detectors than the native English speaker who wrote their own work with their own words.

Same as me, we are slightly different. We formulate sentences and use words differently. Sometimes we are using very refined words, triggering a warning that this work is way above our age. This is crazy!

**As always, there are two sides to the same coin.**

Teachers need to fight with "cheaters" who think that they do not need to work hard. The problem is that they are punishing the genuine students along the way.

Let's take, for example an unauthorised AI checker tool from [justdone.com/ai-detector](https://justdone.com/ai-detector) that I know that some teachers are using to check if the work is genuine.

This is a commercial tool, offering an AI checker for free, and on purpose (in their interest) they bump AI warning to offer their paid services to Humanise your own work – the work that you, a human, wrote in the first place!

I took multiple texts that I wrote down, my email that I sent, which I know that I wrote in 100% from my head, and put them through this checker. The results frighten me and really make me angry. I see daily people doing educational work, only to be discouraged from writing from their head, as what they wrote is marked as AI generated!

All my work, texts (and I put multiple of them to check), was highlighted between 70 and 100% as AI-generated.

**That's totally absurd!**

If I were a student now, wrote a few pages of my work and got feedback from my tutor that I used AI to do this and my work is rejected, I would be furious!

It’s not only annoying, but also totally discouraging people from doing genuine work by themselves, as others, who use AI tools and Humaniser tools, by doing the bare minimum, are accepted and moving forward.

**Come on, teachers, you need to do better!**

{{% ads-in-article %}}

As educators, you are shaping the future of this country. Though your poor work in fighting AI-generated content, by using inaccurate tools, you are promoting students who are doing the bare minimum to pass, that’s something wrong!

If somebody is writing a document about some laws and regulations, as an example, it’s obvious that their work will trigger an AI-generated content warning. They will likely be quoting parts of the law or using similar wording as they learned. Sometimes it is not possible to clearly rewrite something without losing content, and because of that, the student will be punished.

I understand the problem. I put a lot of hard work into my day-to-day work. I support myself currently with AI, like everybody else. In a way, I am using it; I am still proud of the work that I am presenting at the end. I know, where it's required, my work is my own and despite your AI checkers saying differently, I know what the truth is.

If, indeed, you need to use AI checkers tools, make sure you use the ones that are approved and accurate in the first place. Take into consideration the student background, and if you still have a doubt, check it in other means and not just simply ask them, for a 3rd time, to dilute their own work just to meet the "pass" point of an inaccurate AI checker!

**Come on, we need to do better.**

I been an academic teacher for a very short period, and I been a student as well. My work daily is based on creating things with my head and with materials that are available. I know when you can go easy route and when you need to put hard work into it. But if hard work is not respected, the society that we are building now will end up in a land of "con men". These con men will later govern this country. Do we really want this to happen? It's already happening in other countries, but do not need to happen here. We are better at that!

We are the people who shape the future generation, so we need to shape it correctly, even in the challenging AI times we are living in now.

Using a tool like AI in a smart way will become a skill, in the same way that using Google was when I first started interacting with it during my studies.

Not all written things are AI-generated. If you need to use tools to check that, make sure your tools are doing their job correctly on first place.

Students, if you are 100% sure that your work is your own, develop courage and resilience to stand your ground, defend yourself, as this is the most important skill that you will need in your life.

---

According to the inaccurate JustDone AI Detector, the text above—despite being written by a human (me) — is flagged as 91% AI-generated. **What a total joke!**


---
## Policy-Based Routing on an OpenWrt Router
- **URL:** https://dariusz.wieckiewicz.org/en/policy-based-routing-openwrt/
- **Date:** 2026-01-24
- **Tags:** Routing, Policy-Based, Cloudflare, IPv6, OpenWrt, VPN, WARP, WireGuard

### Content

For some time, I have been covering topics concerning OpenWrt on my website. One of the primary interests among my users has been the implementation of WireGuard and adding a Cloudflare WARP tunnel, as well as managing multiple internet connections on a single router.

What I have not yet covered is how to conditionally route traffic once we have established two internet connections, or when we have added a virtual connection (such as a VPN) to the router on a single physical connection.

While firewall rules can be used to route traffic, they are not always straightforward to implement; consequently, I looked for an alternative solution.

I was particularly interested in being able to quickly configure a router to direct traffic from a specific device over a VPN tunnel whenever necessary. To assist with this, I looked into the **PBR** (Policy-Based Routing) package.

<!--more-->

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

## Installation

The objective is to manage everything swiftly through the web interface. For this reason, I will not be installing the `pbr` package in isolation; instead, I will install the LuCI package directly, which will automatically pull in `pbr` as a dependency.

```bash
apk update
apk add luci-app-pbr
service rpcd restart
```

> This procedure requires the installation of `luci-app-pbr` and a restart of the `rpcd` package before we proceed with any further configuration.

By default, during the initial installation, you will be presented with an error message. **This is normal.** The `pbr` service is disabled by default to ensure nothing breaks at this stage. **You can ignore it for now.**

```
ERROR: The pbr service is currently disabled!
Run the following commands before starting the service again:
uci set pbr.config.enabled='1'; uci commit pbr;
pbr 1.2.0-r6 FAILED TO START in fw4 nft file mode!!! Check the output of nft -c -f /var/run/pbr.nftERROR: The pbr service is currently disabled!
ERROR: Errors encountered, please check https://docs.openwrt.melmac.ca/pbr/1.2.0/#ErrorMessagesDetails!
```

[![OpenWrt Services menu with new option Policy Routing](01_openwrt_services_policy_routing.png)](01_openwrt_services_policy_routing.png)

Before moving any further, we can log in to our router via a web browser. In the **Services** section, a new option called **Policy Routing** will now be visible.

Let's review the default options and adjust them to our environment before enabling the service.

{{% ads-in-article %}}

## Configuration

### Basic Configuration

[![Basic configuration default options in Policy Based Routing](02_basic_configuration.png)](02_basic_configuration.png)

1. **Output verbosity**

> This determines the level of detail the `pbr` service writes to your system log (`logread`) and console during startup and rule changes.

* **Recommendation:** Keep this set to **Verbose output** (the default). Once everything is functioning correctly, you can switch to **Condensed output**.

2. **Strict Enforcement**

> This controls what happens to traffic if the specific gateway assigned to a policy (such as a VPN tunnel) goes down. This feature is also commonly known as a **Kill switch**.

* **Recommendation:** If you wish to prevent your real IP address from leaking when a destination connection (VPN) fails, select **Strictly enforce policies** (the default). If you prefer your internet connection to remain active via your ISP even if the "protected" route is broken, choose **Do not enforce**.

3. **Use resolver set support for domains**

> This allows `pbr` to use `ipset` or `nftset` to route entire domains (e.g. netflix.com) by intercepting DNS queries, **where supported**.

* **Recommendation:** Set this to **Enabled** (specifically look for an `nftset` option if available, such as `Dnsmasq nft set`). As current versions of OpenWrt utilise `fw4`, using sets is the most efficient way to handle domain-based routing without manually searching for IP ranges.

---

On my router, the **GL-MT6000 (Flint 2)**, only the **Disabled** option was available, accompanied by the message: `The dnsmasq.nftset is not supported on this system.`.

I would definitely want this feature enabled if I plan on routing specific websites (such as BBC iPlayer) through specific interfaces.

**OpenWrt 24.10** utilises a modern `nftables` environment. The warning regarding `dnsmasq.nftset` usually indicates that the specific older integration script for `dnsmasq` cannot be found, but do not let this discourage you.

**Why is it "Disabled"?**
For `pbr` to use domain sets, it requires `dnsmasq` (which is present on my system) to be compiled with `nftset` support. In newer OpenWrt releases, the standard `dnsmasq` package often needs to be replaced by `dnsmasq-full`.

**How to fix it**
To unlock this option, we usually need to swap the DNS components. We can do this by running the following commands:

```bash
apk update
apk del dnsmasq
apk add dnsmasq-full
```

Before moving forward, let's also run these commands:
```bash
rm /tmp/luci-indexcache*
service rpcd restart
```

When we head back to our web interface and refresh the page, the **Dnsmasq nft set** option will be available in the dropdown list.

---

4. **IPv6 Support**

> This toggles whether the policy engine creates routing tables and firewall rules for IPv6 traffic.

* **Recommendation:** Set this to **Enabled** if you have IPv6 provided by your ISP. Leaving this disabled will result in "leaks"—while your IPv4 traffic might follow your policies, IPv6 traffic will bypass them and exit via your default ISP gateway.

{{% ads-in-article %}}

### Advanced Configuration

[![Advances configuration default options in Policy Based Routing](03_advanced_configuration.png)](03_advanced_configuration.png)

1. **Supported Interfaces**

> This tells `pbr` exactly which network interfaces it is permitted to route traffic through. If left blank, it usually attempts to auto-detect tunnels (such as `tun*` or `wg*`).

* **Recommendation:** Leave this blank for now. If you eventually find that a specific WireGuard or OpenVPN tunnel is not appearing in the "Interface" dropdown menu when creating policies, you can manually add its name here.

2. **Ignored Interfaces**

> This prevents `pbr` from attempting to manage traffic for specific interfaces, such as a VPN server you might be hosting for remote access.

* **Recommendation:** Retain the default (`vpnserver`). You do not want `pbr` attempting to route traffic that is entering your router from an external source.

3. **Rule Create option**

> This determines whether `pbr` rules are appended to the bottom of the firewall list (**Add**) or placed at the very top (**Insert**).

* **Recommendation:** **Add** (the default). Inserting rules at the top can sometimes interfere with core system firewall bypasses (such as traffic intended for the router itself). "Add" is safer and usually sufficient for most setups.

4. **Default ICMP Interface**

> This forces "pings" and "traceroutes" to go through a specific interface, regardless of other existing rules.

* **Recommendation:** **No Change** (the default). If you force this to "wan", you will not be able to "ping" through your VPN to verify its connectivity. It is better to allow ICMP to follow the same policies as your data.

**Uplink Interface Table FW Mark** & **Service FW Mask** are technical "tags" (hexadecimal values) used to track packets in the system memory so the router knows which route they belong to. **Do not change these.** These high values (starting with `010000`) are specifically set to avoid clashing with other services such as SQM (Smart Queue Management) or QoS. Unless you have a very specific manual firewall configuration, the defaults are perfect.

### Web UI Configuration

[![Web UI Configuration default options in Policy Based Routing](04_web_ui_configuration.png)](04_web_ui_configuration.png)

These final two options purely affect how you interact with the `luci-app-pbr` interface when you begin creating rules.

1. **Add Ignore Target**

> This adds an 'Ignore' option to the list of interfaces for policies. If you set this to **Enabled**, any traffic assigned the 'Ignore' flag will bypass `pbr` entirely and follow the router's default routing table.

* **Recommendation:** **Enabled**. This is incredibly useful for troubleshooting. If a specific device or website is malfunctioning, you can quickly set its policy to "Ignore" to determine if `pbr` is the cause without having to delete the entire rule.

2. **Supported Protocols**

> This defines which protocol options appear in the dropdown menu when creating a new policy.

* **Recommendation:** **Leave as default**. Generally, you will primarily use "tcp udp" for standard browsing or "all". Whilst having "icmp" visible is helpful if you wish to route pings differently from data, "all" or "tcp udp" covers 99% of use cases for most users.

Now we can press the **Save & Apply** button.

{{% ads-in-article %}}

## Policies

[![Default Policies in Policy Based Routing](05_policies.png)](05_policies.png)

Now we will discuss the policies section which, by default, contains the rules shown above. These default rules are "boilerplate" templates included by the developer to prevent common headaches.

**Ignore Local Requests**
This is a safety net to ensure that traffic between your own devices (such as your phone communicating with your printer) does not get redirected into a VPN tunnel and dropped. You may need to adjust this slightly, especially if you change the default IP mask used by OpenWrt from the standard `192.168.1.x` range.

**Plex/Emby Rules**
These ensure that media server traffic remains on your primary ISP line (WAN) so that remote streaming functions correctly and is not throttled by a VPN.

All of these policies are initially set to **Disabled** (the 'Enabled' tick box is not selected). My recommendation is to tick **Enabled** for **Ignore Local Requests** after making any necessary adjustments to the IP range.

## DNS Policies

[![Default DNS Policies in Policy Based Routing](06_dns_policies.png)](06_dns_policies.png)

> This section is used to force specific devices to use a designated DNS server, bypassing your router’s global DNS settings.

* **Recommendation:** Keep this **Disabled**. As I have a global Cloudflare DoH (DNS over HTTPS) gateway running on port 5053, I want all my devices to benefit from that privacy. The default example (redirecting `192.168.1.5` to Cloudflare's `1.1.1.1`) is only useful if you have a "rebel" device—such as a Google Home or a Smart TV—that attempts to use hardcoded DNS settings, and you wish to intercept them. Unless you have a specific reason to override your DoH proxy for a particular device, leave this section empty.

## DSCP Tagging

[![Default DCSK Taggin values in Policy Based Routing](07_dscp.png)](07_dscp.png)

> DSCP (Differentiated Services Code Point) is used for Quality of Service (QoS). It "marks" packets so that your ISP or another router knows which traffic is high priority (such as VoIP) and which is low priority (such as a background download).

* **Recommendation:** **Leave blank**. Most residential ISPs ignore DSCP tags entirely. Unless you have a highly complex multi-router setup where you have configured specific hardware to prioritise certain "marked" packets, completing this section will not provide any noticeable benefit and might even cause issues with some external networks.

## Custom User File Includes

[![Default Custom User File Includes in Policy Based Routing](08_custom.png)](08_custom.png)

> These are pre-made scripts that assist `pbr` in managing services that utilise thousands of frequently changing IP addresses.

* **pbr.user.dnsprefetch:** Highly recommended to **Enable**. This helps resolve domains in your policy list before you even visit them, ensuring the "initial load" of a routed website feels significantly faster.
* **pbr.user.aws:** Keep **Disabled** unless you specifically wish to route all Amazon Web Services traffic through a particular interface (which is generally inadvisable as it encompasses a vast portion of the internet).
* **pbr.user.netflix:** **Enable if you plan on routing Netflix.** Netflix is notoriously difficult to route because they utilise hundreds of different IP ranges; this script handles the complex management for you.

{{% ads-in-article %}}

## Status

[![Control buttons to Enable and Start the service of Policy Based Routing](09_status.png)](09_status.png)

Now we are ready to **Enable** our service under **Service Control**. Follow this by pressing the **Start** button.

## Use Case

My objective is to use `pbr` to direct the entirety of the traffic from one of the devices on my network through a Cloudflare WARP tunnel.

Referencing my previous post, [Cloudflare WARP and a router with OpenWrt](/en/turbocharge-your-internet-connection/#cloudflare-warp-and-a-router-with-openwrt), I utilised [**wgcf**](https://github.com/ViRb3/wgcf/) to set up a virtual interface for Cloudflare WARP routing.

**Important**
Because traffic will be routed via `pbr`, when setting up the WireGuard interface for the Cloudflare WARP tunnel, you must remember **NOT** to tick **Route Allowed IPs**. Otherwise, all of your traffic will be routed through this new interface by default.

For the Cloudflare WARP interface in the aforementioned article, I recommended attaching it to the **wan** zone within the **Firewall Settings**. However, if your provider supplies native IPv6 support, you should not enable IPv6 **Masquerading**, as your devices will lose their individual IPv6 addresses and all traffic will be routed through the router's single IPv6 address.

In that instance, I recommend creating an additional Firewall zone where you can set **Masquerading** for IPv4 and (in Advanced Settings) IPv6. This zone will be used explicitly for the Cloudflare WARP interface. All other options should remain exactly like the default **wan** zone.

---

Once our additional interface is up and running, let’s perform a quick check to ensure everything is functioning correctly.

Navigate to **Services** > **Policy Routing** and, by clicking the **Add** button in the policy section, create a rule to route the traffic of your computer through the new interface.

In **Local addresses/devices**, you need to target your device on the local network using both IPv4 and IPv6. This may prove problematic if these addresses change; therefore, **the simplest method** is to target the device by its name. You can find this name on the main status page when you log into your router, under **Active DHCP Leases**.

> Remember, if your device name appears as "iPhone-Darek (iPhone-Darek.lan)", you should only type "iPhone-Darek".

PBR will automatically resolve the name to both its current IPv4 and IPv6 addresses. If the addresses change, the rule remains valid.

Type your device name, select the interface through which it should be routed, and add the rule by pressing **Save**, followed by the **Save & Apply** button.

To verify quickly if **all** traffic is passing through the new interface, simply head to [speedtest.net](https://www.speedtest.net) and check the connection source on the left. If you are using Cloudflare WARP, it will state **Cloudflare Warp** (instead of **toob**, which is my current ISP).

[![SpeedTest website showing source of traffic through the tunnel](10_speedtest_check.png)](10_speedtest_check.png)

The decision regarding what you wish to route, and how, now rests entirely with you.

Enjoy!


---
## My (23) Stars of GitHub at the End of 2025
- **URL:** https://dariusz.wieckiewicz.org/en/my-stars-of-github-at-the-end-of-2025/
- **Date:** 2025-12-28
- **Tags:** github, github stars, emoji-cheat-sheet, google-photos-album-image-url-fetch, ImageOptim, web-performance-research, fuse-t, comic-mono-font, woff2, open-source-mac-os-apps, SQL-tips-and-tricks, AssetCatalogTinkerer, rufus, rustdesk, Latest, awesome-selfhosted, public-iperf3-servers, sveltia-cms, wg-easy, embed-pdf-viewer, Handy, netdata, open-webui, watchtower, Win11Debloat

### Content

Following [my post from last year](/en/my-stars-of-github-at-the-end-of-2024/), in which I shared my GitHub stars for 2024, I have now reviewed what I discovered throughout 2025.

I review my stars periodically, and the 31st of December 2025 was no exception.

By the end of 2025, I had accumulated (or rediscovered) the following repositories, all of which are well worth a look.

> This is a curated list, and I have selected those most worth knowing for the coming year, 2026. I have avoided repeating anything covered previously. To see my earlier recommendations, you can read [my 2024 Stars of GitHub](/en/my-stars-of-github-at-the-end-of-2024/).

<!--more-->

## [ikatyang / emoji-cheat-sheet](https://github.com/ikatyang/emoji-cheat-sheet)

> A markdown version emoji cheat sheet

Comprehensive markdown-based reference guide designed for users who want to incorporate emojis into GitHub, Slack, and other platforms that support emoji shortcodes. It provides an extensive, categorised list of emojis alongside their respective shortcodes (such as :smile:) and Unicode representations.

The repository is notable for being automatically updated, pulling data directly from the GitHub Emoji API and the Unicode Full Emoji List to ensure the content remains current with the latest additions. It serves as a highly popular and lightweight tool for developers and writers to quickly find and copy the exact syntax needed to render icons within markdown files, commit messages, and documentation.

## [yumetodo / google-photos-album-image-url-fetch](https://github.com/yumetodo/google-photos-album-image-url-fetch)

> Extract public image URL from shared album URL on Google Photos

TypeScript-based library designed to programmatically extract direct image URLs from public Google Photos shared albums. Unlike standard API-based approaches that often provide temporary links, this tool focuses on retrieving more persistent URLs by scraping and parsing the album's metadata directly from the shared page's HTML structure.

The tool is particularly useful for developers who want to use Google Photos as a lightweight content delivery system or host for website images. It includes features to fetch image dimensions and update dates, and it even provides a mechanism to track new additions to an album over time. Leveraging the specific data callbacks embedded in Google Photos web pages, it allows for automated integration of photo galleries into third-party applications without requiring a complex OAuth setup for public content.

{{% ads-in-article %}}

## [ImageOptim / ImageOptim](https://github.com/ImageOptim/ImageOptim)

> GUI image optimiser for Mac

The source code for the popular open-source macOS application designed to reduce image file sizes without sacrificing quality. It functions as a graphical front-end that seamlessly integrates several powerful command-line optimisation tools, such as Zopfli, MozJPEG, and PNGOUT. By automating these tools, it finds the best compression parameters to strip away bloated metadata, invisible junk, and unnecessary colour profiles from JPEG, PNG, and GIF files.

The project is highly regarded for its "brain-dead simple" user interface, which allows users to simply drag and drop images or entire folders to initiate batch processing. Beyond the desktop app, the repository serves as the foundation for a broader ecosystem, including an API and CLI tools, making it a staple for web developers and designers looking to improve page load times and app performance. Because it runs locally on your Mac, it ensures privacy by processing images without ever uploading them to an external server.

## [imteekay / web-performance-research](https://github.com/imteekay/web-performance-research)

> ⚡️ Web Performance Research

Comprehensive, curated collection of resources dedicated to the deep study and application of web performance. It serves as a personal research log and knowledge base that covers a vast array of topics, from Core Web Vitals like LCP and CLS to advanced browser internals, rendering engines, and memory management.

The repository is organised into thematic sections, including architecture, backend, networking (HTTP/2, caching), and frontend frameworks like React. It aggregates high-quality articles, videos, podcasts, and case studies, providing developers with a structured path to move from basic optimisation techniques to a fundamental understanding of how browsers execute code and render pixels. By documenting real-world experiments and industry best practices, it functions as a go-to reference for building faster, more resilient web applications.

## [macos-fuse-t / fuse-t](https://github.com/macos-fuse-t/fuse-t)

A modern, "kext-less" implementation of FUSE (Filesystem in Userspace) for macOS. Its primary purpose is to serve as a successor to older projects like macFUSE that rely on kernel extensions. Because Apple has increasingly restricted the use of third-party kernel extensions for security and stability reasons, this project offers a more sustainable path for developers to create custom filesystems on the Mac.

Technically, the tool functions by implementing a userspace server that translates FUSE protocol calls into NFS v4 (Network File System) calls. This allows macOS to mount volumes using its built-in, native NFS client rather than requiring deep, low-level system modifications. This approach avoids the need to lower system security settings (such as disabling System Integrity Protection) or reboot into recovery mode, which is often necessary for traditional FUSE implementations.

The project is designed as a drop-in replacement, maintaining compatibility with existing libfuse API headers so that many existing filesystems can be ported with minimal changes. It is particularly popular within the privacy and backup communities, being used by tools like Cryptomator and rclone to provide a seamless way to mount encrypted or cloud-based storage as if it were a local drive.

{{% ads-in-article %}}

## [dtinth / comic-mono-font](https://github.com/dtinth/comic-mono-font)

> A legible monospace font... the very typeface you’ve been trained to recognise since childhood

A unique, monospaced font designed specifically for coding, inspired by the aesthetic of the infamous Comic Sans typeface. It is a derivative of Shannon Miwa’s "Comic Shanns," modified to be a perfect monospaced font where every character has the exact same width. This makes it suitable for use in code editors and terminal emulators, offering a legible and casual alternative to more traditional, rigid programming fonts.

The project addresses common alignment issues found in the original inspiration by ensuring that glyphs are properly centred and scaled to work within a grid. It includes features such as bold and italic variants, and the repository provides simple installation scripts for various operating systems. For developers who find standard fonts too clinical, Comic Mono offers a readable, "hand-drawn" feel that maintains the technical requirements of a development environment without sacrificing the whimsical character of the source design.

## [google / woff2](https://github.com/google/woff2)

The repository provides the reference implementation for the Web Open Font Format 2.0 (WOFF2), a font packaging format that provides significantly better compression than its predecessor. The project includes C++ libraries and command-line utilities—specifically `woff2_compress` and `woff2_decompress` — built on the Brotli compression algorithm to help developers prepare fonts for efficient web delivery.

This tool is particularly useful when working with repositories like [dtinth / comic-mono-font](https://github.com/dtinth/comic-mono-font), which only provides the font in TrueType (.ttf) format. While TTF files work well for local desktop use, they are often too large for optimal web performance. By using this utility, you can convert those TTF files into WOFF2 format, making them lightweight and ready for use in web applications and websites to ensure faster loading times and reduced bandwidth consumption.

## [serhii-londar / open-source-mac-os-apps](https://github.com/serhii-londar/open-source-mac-os-apps)

> 🚀 Awesome list of open source applications for macOS.

A massive, community-driven "Awesome List" that serves as a definitive directory for open-source software on macOS. It categorises hundreds of applications across dozens of fields, including development tools, productivity, audio-visual editing, security, and system utilities. The project is designed to help users find high-quality, free alternatives to proprietary software while encouraging developers to discover new projects they can contribute to.

Unlike smaller, highly curated lists, this repository is exhaustive and includes both native Swift/Objective-C apps and cross-platform tools. Each entry typically features a brief description, links to the official website, and the primary programming languages used in the project. Because it is powered by a large community of contributors, the list is frequently updated with the latest open-source releases, making it an essential resource for Mac users who prioritise transparency and community-driven software.

{{% ads-in-article %}}

## [ben-nour / SQL-tips-and-tricks](https://github.com/ben-nour/SQL-tips-and-tricks)

> SQL tips and tricks

A practical, curated guide designed to help developers and data analysts write cleaner, faster, and more maintainable SQL queries. It moves beyond basic syntax to cover professional best practices, such as using leading commas for better readability, leveraging Common Table Expressions (CTEs) to simplify complex logic, and understanding the specific performance implications of different filtering methods.

The collection is particularly valuable for its focus on common pitfalls and "pro-tips" that are often missed in standard tutorials. It includes advice on avoiding ambiguity in calculated fields, mastering the order of execution, and using advanced functions like QUALIFY or ROLLUP for sophisticated data aggregation. Whether you are working on ad-hoc analysis or production-level database code, this repository serves as a concise cheat sheet for refining your SQL craftsmanship.

## [insidegui / AssetCatalogTinkerer](https://github.com/insidegui/AssetCatalogTinkerer)

> An app that lets you open .car files and browse/extract their images.

A native macOS utility designed to open, browse, and extract the contents of `.car` files, which are the compiled asset catalogues used by Apple in iOS, macOS, watchOS, and tvOS applications. It allows developers and designers to peer into the internal resources of an app to view images and icons that are otherwise packaged in a proprietary binary format.

The application is particularly useful for reverse engineering or design research, as it can export individual assets or entire catalogues into standard formats. Beyond simple image viewing, the project includes a QuickLook plugin for macOS, enabling users to preview the contents of an asset catalogue directly from the Finder. While it was originally built with images in mind, recent updates have expanded its capabilities to include a command-line tool named `act` and support for modern asset types like SVGs and SF Symbols.

## [pbatard / rufus](https://github.com/pbatard/rufus)

> The Reliable USB Formatting Utility

A home of the "Reliable USB Formatting Utility," a widely used open-source Windows application for creating bootable USB flash drives. It is particularly renowned for its speed and reliability when preparing installation media from ISO images for Windows, Linux, and UEFI-based systems. The tool is frequently used for low-level tasks, such as flashing BIOS or firmware from DOS or running system utilities on computers without a pre-installed operating system.

Beyond simple formatting, Rufus includes advanced features such as the ability to create "Windows To Go" drives and bypass specific Windows 11 hardware requirements, like TPM 2.0 or Secure Boot, during the media creation process. The repository contains the highly optimised C-based source code, which allows the application to remain small, portable, and remarkably fast compared to many official alternatives. It supports a vast array of file systems and is available in dozens of languages, making it a staple utility for IT professionals and home users alike.

## [rustdesk / rustdesk](https://github.com/rustdesk/rustdesk)

> An open-source remote desktop application designed for self-hosting, as an alternative to TeamViewer.

The source code for a full-featured, open-source remote desktop infrastructure. Designed as a self-hosted alternative to proprietary solutions, it provides users with total control over their data security by allowing them to host their own relay and ID servers. The application is built using Rust, ensuring high performance and low memory usage across multiple platforms, including Windows, macOS, Linux, iOS, and Android.

It has gained significant popularity as a powerful replacement for enterprise tools like TeamViewer, particularly for those looking to migrate their user base to a more transparent and cost-effective platform. As your personal favourite app for offering remote support, it provides a seamless transition for managing multiple users without the licensing restrictions or privacy concerns often associated with commercial competitors. Its ability to work out-of-the-box with a public rendezvous server, while still offering the flexibility of private deployment, makes it a versatile choice for both casual support and professional IT administration.

{{% ads-in-article %}}

## [mangerlahn / Latest](https://github.com/mangerlahn/Latest)

> A small utility app for macOS that makes sure you know about all the latest updates to the apps you use.

A home of a highly useful open-source utility for macOS that simplifies the often tedious task of keeping non-App Store applications up to date. While the official Mac App Store handles updates for its own software, many third-party apps downloaded from websites require manual checks; this tool bridges that gap by scanning your /Applications folder and identifying which apps have newer versions available.

The application primarily supports apps that use the popular Sparkle framework or those hosted on GitHub, presenting them in a clean, native interface that feels like a natural part of the macOS ecosystem. It allows you to view release notes for each update and perform the entire installation process with a single click. For users who prefer a centralised dashboard for software maintenance without relying on command-line tools, it offers a fast and elegant way to ensure their entire toolkit remains current and secure.

## [awesome-selfhosted / awesome-selfhosted](https://github.com/awesome-selfhosted/awesome-selfhosted)

> A list of Free Software network services and web applications which can be hosted on your own servers

One of the most significant collections of open-source software on GitHub, acting as a definitive directory for applications that can be hosted on one's own infrastructure. It provides an exhaustive list of self-hosted alternatives to popular software-as-a-service (SaaS) platforms, covering everything from cloud storage and communication tools to media streaming and home automation.

The project is meticulously organised into dozens of categories, ensuring that users can easily find reliable tools for specific needs, such as password management, analytics, or document editing. Because the repository is community-driven and adheres to strict quality guidelines, it serves as a trusted roadmap for enthusiasts and sysadmins looking to reclaim their digital privacy and data sovereignty. It is often considered the "gold standard" resource for anyone building a home lab or managing their own private server.

## [R0GGER / public-iperf3-servers](https://github.com/R0GGER/public-iperf3-servers)

> A list of public iPerf3 servers...

A curated and actively monitored directory of public iPerf3 servers located across the globe. It addresses the common challenge of finding reliable endpoints for network performance testing, providing a verified list of servers hosted by data centres, ISPs, and educational institutions rather than unreliable residential connections.

The list is organised by continent and includes essential connection details such as hostnames, available ports, and support for specific protocols like IPv6 or UDP. By maintaining strict uptime requirements for inclusion, the repository ensures that network administrators and enthusiasts have a dependable resource for measuring bandwidth, latency, and jitter between their local environment and various geographic regions.

{{% ads-in-article %}}

## [sveltia / sveltia-cms](https://github.com/sveltia/sveltia-cms)

> Netlify/Decap CMS successor. Fast, lightweight, Git-based headless CMS. Modern UX, first-class i18n support, mobile support + 100s of improvements. Framework-agnostic, open source & free.

A lightweight, open-source, and Git-based Content Management System (CMS) designed as a modern successor to Decap CMS (formerly Netlify CMS). It acts as a static site generator’s administrative interface, allowing users to manage content via a user-friendly GUI that automatically commits changes directly to a Git repository. Because it is built as a single-page application that runs entirely in the browser, it requires no backend server, making it an incredibly efficient way to add "WordPress-like" management to static sites.

It has become a standout choice for those looking to bring high-level content editing to static frameworks, such as the widely used [Hugo](https://github.com/gohugoio/hugo). By integrating Sveltia CMS with a Hugo-built site, you can provide an intuitive dashboard for non-technical users to edit posts and upload media, while still benefiting from the speed, security, and simplicity of a static architecture. Its ability to work seamlessly with various Git providers and its focus on performance make it a powerful tool for bridging the gap between professional development and easy content administration.

## [wg-easy / wg-easy](https://github.com/wg-easy/wg-easy)

> The easiest way to run WireGuard VPN + Web-based Admin UI.

One of the most user-friendly ways to deploy and manage a WireGuard VPN server. It bundles the WireGuard VPN and a sleek, web-based management dashboard into a single Docker container, removing the complexity of manual configuration files and command-line peer management.

The tool is highly regarded for its simplicity, allowing users to create, delete, and manage clients through a responsive interface that even generates QR codes for instant mobile setup. It handles essential networking tasks automatically, such as internal NAT and firewall rules, making it an ideal choice for home lab enthusiasts or small teams who want a secure, high-performance VPN without the steep learning curve typically associated with network administration.

## [embedpdf / embed-pdf-viewer](https://github.com/embedpdf/embed-pdf-viewer)

> A PDF viewer that seamlessly integrates with any JavaScript project

A lightweight, customisable solution for embedding a professional PDF viewing experience directly into web applications. It is built as a wrapper around the powerful `PDF.js` library, offering a clean and modern user interface that remains responsive across different screen sizes. By using this tool, developers can bypass the inconsistent behaviour of native browser PDF plugins and provide a uniform experience for their users.

The project is designed for easy integration, allowing for the rendering of PDF documents with features like zooming, page navigation, and text selection without requiring complex backend processing. It is particularly useful for documentation sites or content-heavy web apps where displaying portable documents inline—rather than forcing a download—is essential for a seamless user journey. The repository includes clear instructions for deployment, making it a straightforward addition to any modern web project.

{{% ads-in-article %}}

## [cjpais / Handy](https://github.com/cjpais/Handy)

> A free, open source, and extensible speech-to-text application that works completely offline.

A free, open-source speech-to-text application for macOS that prioritises privacy by working completely offline. It leverages OpenAI’s Whisper model locally on your machine to provide highly accurate transcriptions without ever sending your audio data to the cloud.

The application is designed to be extensible and unobtrusive, allowing users to quickly transcribe audio from their microphone or system output directly into text. Because it processes everything on-device, it is an excellent tool for users who need reliable transcription services while maintaining strict data sovereignty and avoiding recurring subscription fees.

## [netdata / netdata](https://github.com/netdata/netdata)

> The fastest path to AI-powered full-stack observability, even for lean teams.

A home of a highly advanced, open-source monitoring agent designed to provide real-time, per-second observability for entire IT infrastructures. Unlike traditional monitoring tools that often rely on historical data or slow polling intervals, Netdata captures thousands of metrics every second—covering everything from CPU and memory usage to application-specific performance and hardware sensors—and visualises them in an interactive, web-based dashboard that requires zero initial configuration.

What sets the project apart is its "distributed" architecture and extreme efficiency; the agent is written primarily in C to maintain a tiny resource footprint (often using less than 1% CPU) while performing complex tasks like unsupervised machine learning for anomaly detection directly at the edge. By keeping the data local to the source and only streaming views when needed, it offers a secure and high-fidelity alternative to centralised, expensive SaaS platforms. Whether you are troubleshooting a single server or managing a massive cluster of containers and IoT devices, Netdata provides the instant insights necessary to identify root causes and resolve incidents before they impact users.

## [open-webui / open-webui](https://github.com/open-webui/open-webui)

> User-friendly AI Interface (Supports Ollama, OpenAI API, ...)

A feature-rich, self-hosted interface designed to be the ultimate front-end for interacting with large language models. Originally developed as Ollama WebUI, it has evolved into a universal gateway that supports various backends, including Ollama and OpenAI-compatible APIs. It brings a polished, ChatGPT-like experience to local AI setups, allowing users to manage conversations, documents, and models through a sleek and responsive web interface.

What makes this project stand out is its extensive suite of advanced features, such as Retrieval-Augmented Generation (RAG) support, which allows the AI to "chat" with your local files and websites. It also includes comprehensive multi-user management, fine-grained access controls, and a "Functions" system for extending the model's capabilities with custom scripts. For privacy-conscious users and developers, it serves as an essential tool for creating a powerful, private AI workstation that remains entirely under their own control.

{{% ads-in-article %}}

## [nicholas-fedor / watchtower](https://github.com/nicholas-fedor/watchtower)

> Automate Docker container image updates

A prominent and actively maintained fork of the original `containrrr/watchtower` project. As the original upstream repository has become largely unmaintained, this fork has emerged as the community-recommended version for users who want to keep their Docker infrastructure secure and up-to-date. It functions as a process for automating Docker container base image updates, periodically checking for newer versions of your running images and gracefully restarting containers to apply those updates.

What distinguishes this specific fork is its commitment to modern Docker features and frequent bug fixes that have stalled elsewhere. Notably, it introduces robust support for depends_on logic within Docker Compose, ensuring that dependent containers are restarted in the correct order to prevent service failures. It also includes refined self-update behaviour, improved notification propagation through Shoutrrr, and fixes for the Docker API to ensure compatibility with the latest system environments.

For home lab enthusiasts and sysadmins, this version of Watchtower provides a "set-and-forget" solution for maintaining a fresh software stack without manual intervention. By mounting the Docker socket, it can monitor all running containers (or a specific subset) and send detailed reports via various notification services if an update occurs. It remains a critical utility for anyone looking to automate their DevOps workflow while ensuring their containers benefit from the latest security patches and performance improvements.

{{% ads-in-article %}}

## [Raphire / Win11Debloat](https://github.com/Raphire/Win11Debloat)

> A simple, lightweight PowerShell script to remove pre-installed apps, disable telemetry, as well as perform various other changes to customise, declutter and improve your Windows experience. Win11Debloat works for both Windows 10 and Windows 11.

A comprehensive PowerShell-based utility designed to transform a standard Windows 11 installation into a cleaner, faster, and more private environment. It is widely considered an essential first step for any freshly purchased computer or a clean Windows installation, as it systematically removes the "bloatware" and intrusive features that often clutter the default operating system experience.

The tool offers an extensive range of optimisations, from uninstalling pre-installed third-party apps and disabling telemetry to stripping away sponsored content from the Start menu and Taskbar. Beyond mere cleanup, it provides deeper system tweaks such as restoring the classic context menu, disabling Bing search within the OS, and removing non-essential system components like OneDrive or Cortana. Its modular approach allows users to run it via an interactive graphical interface or through automated scripts, making it a powerful ally for anyone looking to reclaim their system resources and ensure their hardware isn't bogged down by unnecessary background processes from day one.

One of the most reassuring aspects of Win11Debloat is its "safety-first" design; when running with the default settings, the tool is remarkably non-destructive. If you find that you miss a specific feature or accidentally removed an app you actually needed, any changes applied can be easily reverted.

Because the script focuses on disabling services and hiding components rather than permanently deleting critical system files, you can restore functionality without a full OS reinstall. Furthermore, any stock applications that were uninstalled can be reinstalled through the Microsoft Store with ease, ensuring that you have complete control over your system's configuration without the fear of breaking Windows permanently.

---

And that is all.

I hope you find something useful here too. If you do, please leave a star on the relevant repository to let the creators know that their hard work is highly appreciated.


---
## How to Add Your Website as a Preferred Source on Google: A Hugo Guide
- **URL:** https://dariusz.wieckiewicz.org/en/how-to-add-your-website-as-a-preferred-source-on-google-hugo-guide/
- **Date:** 2025-12-27
- **Tags:** Preferred Source, Google, Google Search, Hugo, WebDev, WebP, HTML, CSS, Button

### Content

In the past, I have been exploring various ways to increase the reach of my website and other websites that I am working with, which are publishing content regularly.

I have explored [a way of publishing my content in Bing News](/en/publish-your-content-in-bing-news-windows-feed/), which was typically faced with **rejection** without any explanation. My last attempt on this matter was in July 2024, after which I decided not to bother anymore. Overall, this option was deprecated shortly after.

From time to time, my site is landing in [Bing Jail](/en/bing-jail/) for no reason. With my involvement in the past, I [escaped from Bing Jail](/en/escape-from-bing-jail/), but from time to time, I am serving a sentence again and again.

The most recent Bing Jail for my site happened shortly after 2nd October 2025 and lasted until 17th December 2025, when I started seeing a slow recovery without me doing anything in that matter. This nonsense that is going on with Bing prevents me from recommending search engines other than Google, such as DuckDuckGo, which relies heavily on Bing. Microsoft needs to sort out its nonsense if it ever wants to come closer to Google. In the current age of AI, I don't think that will ever happen.

At some point, I explored [publishing my content in Google News](/en/publish-your-content-in-google-news/) until Google decided to kill it as well.

Right now, popularity is gaining for another Google solution: **adding websites as preferred sources of information in Search**.

<!--more-->

**Google Preferred Sources** is a feature that lets you "pick your favourites" (favourite websites) when it comes to news (though not news in its broadest sense).

Instead of letting Google’s algorithms decide which news websites you should see, you can tell Google which publishers you trust or enjoy reading most. When those sites write about a topic you’re searching for, Google will move them to the top of your results.

The new approach—a button that can be added to a website—is a way to encourage people to subscribe to your website.

Primarily, it is designed for "news" websites; however, a lot of technical blogs and websites are also trying to explore this new way of gaining visitors. Overall, people searching the web are not only doing so to read about recent news. If you're looking for a [recipe](https://yummyrecipes.uk) using Google, and you're doing this quite often, it is worth picking your [favourite sites](https://google.com/preferences/source?q=https://yummyrecipes.uk), so you will be pointed to websites you trust for the same search query, rather than an unknown one that may not always serve you what you expect.

The idea of **preferred sources** is to have your favourite sites appear more prominently for you in Google Search (while you are logged in to your Google Account).

This time, Google made sure that the implementation is as easy as possible. They started with a simple article ([How to select your preferred sources in Top Stories in Search](https://blog.google/products/search/preferred-sources/)) where they walked through the process of adding sources.

To allow website owners to implement this swiftly, they created a [dedicated help centre](https://support.google.com/news/publisher-center/answer/10598160?hl=en&ref_topic=10630761&sjid=15947966067918083781-NA) page, where you can understand how to build a link (called a **deeplink**) with your website address in it, as well as where you can [download dedicated buttons](https://services.google.com/fh/files/helpcenter/google_preferred_source_badge.zip).

I decided to try this approach for [my friend's website](https://yummyrecipes.uk), built on [Hugo](https://gohugo.io).

## Building a link

Google explains simply how to build your link:

```html
https://google.com/preferences/source?q=<your website URL>
```

You just need to replace `<your website URL>` with your site address. 

This will look as follows:

```html
<div class="google-preferred-source-badge">
	<a target="_blank" rel="noopener" rel="nofollow" href="https://google.com/preferences/source?q=https://yummyrecipes.uk" aria-label="Add Yummy Recipes UK as a preferred source on Google">

	<!-- image will go here -->

	</a>
</div>
```

In **Hugo**, my code will look as follows:

```html
<div class="google-preferred-source-badge">
    {{- $baseUrl := "/" | absURL -}}
    <a href="https://google.com/preferences/source?q={{ $baseUrl }}"
       target="_blank"
       rel="noopener nofollow"
       aria-label="Add {{ .Site.Title }} as a preferred source on Google">

    <!-- image will go here -->

    </a>
</div>
```

It's time to add the images.

## Add official images + WebP

On the [dedicated help centre](https://support.google.com/news/publisher-center/answer/10598160?hl=en&ref_topic=10630761&sjid=15947966067918083781-NA) page, find the [Download the button](https://services.google.com/fh/files/helpcenter/google_preferred_source_badge.zip) link. This will download a ZIP file that you need to extract and place in a dedicated folder.

In my Hugo instance, I will put this into the `/static` folder, within a subfolder named `google_preferred_source_badge`.

The folder will contain the following files:

```
google_preferred_source_badge_dark.png
google_preferred_source_badge_dark@2x.png
google_preferred_source_badge_light.png
google_preferred_source_badge_light@2x.png
```

I have also converted them into WebP images. I used the macOS terminal with WebP installed via Homebrew (`brew install webp`). I used the command `cwebp -q 75 image.png -o image.webp` to get the relevant output, but you can simply go to [**Squoosh.app**](https://squoosh.app).

> In the **Squoosh.app** app: Drag and drop your image. In the **Compress** section on the right, select **WebP** from the dropdown. Adjust the **Quality** slider to **75**.

My folder structure will be:

```
google_preferred_source_badge_dark.png
google_preferred_source_badge_dark.webp
google_preferred_source_badge_dark@2x.png
google_preferred_source_badge_dark@2x.webp
google_preferred_source_badge_light.png
google_preferred_source_badge_light.webp
google_preferred_source_badge_light@2x.png
google_preferred_source_badge_light@2x.webp
```

The image part of the code (that will go into `<!-- image will go here -->`) will look as follows:

> This takes into account the use of `colour-scheme: light dark` that I have implemented on my website, as well as `prefers-colour-scheme`.

```html
<picture>
    <source
        srcset="/google_preferred_source_badge/google_preferred_source_badge_dark@2x.webp 2x,
                /google_preferred_source_badge/google_preferred_source_badge_dark.webp 1x" 
        type="image/webp" 
        media="(prefers-color-scheme: dark)">
    <source 
        srcset="/google_preferred_source_badge/google_preferred_source_badge_dark@2x.png 2x,
                /google_preferred_source_badge/google_preferred_source_badge_dark.png 1x" 
        type="image/png" 
        media="(prefers-color-scheme: dark)">

    <source 
        srcset="/google_preferred_source_badge/google_preferred_source_badge_light@2x.webp 2x,
                /google_preferred_source_badge/google_preferred_source_badge_light.webp 1x" 
        type="image/webp">
    <source 
        srcset="/google_preferred_source_badge/google_preferred_source_badge_light@2x.png 2x,
                /google_preferred_source_badge/google_preferred_source_badge_light.png 1x" 
        type="image/png">

    <img 
        src="/google_preferred_source_badge/google_preferred_source_badge_light.png" 
        alt="Add {{ .Site.Title }} as a preferred source on Google" 
        width="338" 
        height="107" 
        loading="lazy"
        style="color-scheme: light dark; font-style: italic; vertical-align: middle;">
</picture>
```

When implementing this in **Hugo**, I will use this approach:

```html
<picture>
    {{- $path := "/google_preferred_source_badge/google_preferred_source_badge" -}}
    
    <source 
        srcset="{{ printf "%s_dark@2x.webp" $path }} 2x, {{ printf "%s_dark.webp" $path }} 1x" 
        type="image/webp" 
        media="(prefers-color-scheme: dark)">
    <source 
        srcset="{{ printf "%s_dark@2x.png" $path }} 2x, {{ printf "%s_dark.png" $path }} 1x" 
        type="image/png" 
        media="(prefers-color-scheme: dark)">

    <source 
        srcset="{{ printf "%s_light@2x.webp" $path }} 2x, {{ printf "%s_light.webp" $path }} 1x" 
        type="image/webp">
    <source 
        srcset="{{ printf "%s_light@2x.png" $path }} 2x, {{ printf "%s_light.png" $path }} 1x" 
        type="image/png">

    <img 
        src="{{ printf "%s_light.png" $path }}" 
        alt="Add {{ .Site.Title }} as a preferred source on Google" 
        width="338" 
        height="107" 
        loading="lazy"
        class="google-badge-img">
</picture>
```

## i18n

With my Hugo website, I am using an **i18n** approach to serve content in the right language.

In the above code, we have two elements that will require translation: `aria-label` and `alt`.

We will change this part:

```
Add {{ .Site.Title }} as a preferred source on Google
```

to this:

```
{{ T "GooglePreferredBadge" (dict "Title" .Site.Title) }}
```

and in the relevant file (`i18n/en.toml`), I will add:

```toml
[GooglePreferredBadge]
other = "Add {{ .Title }} as a preferred source on Google"
```

## Final Code for the Hugo website

```html
<div class="google-preferred-source-badge">
    {{- $baseUrl := "/" | absURL -}}
    <a href="https://google.com/preferences/source?q={{ $baseUrl }}"
       target="_blank"
       rel="noopener nofollow"
       aria-label="{{ T "GooglePreferredBadge" (dict "Title" .Site.Title) }}">

        <picture>
            {{- $path := "/google_preferred_source_badge/google_preferred_source_badge" -}}
            
            <source 
                srcset="{{ printf "%s_dark@2x.webp" $path }} 2x, {{ printf "%s_dark.webp" $path }} 1x" 
                type="image/webp" 
                media="(prefers-color-scheme: dark)">
            <source 
                srcset="{{ printf "%s_dark@2x.png" $path }} 2x, {{ printf "%s_dark.png" $path }} 1x" 
                type="image/png" 
                media="(prefers-color-scheme: dark)">

            <source 
                srcset="{{ printf "%s_light@2x.webp" $path }} 2x, {{ printf "%s_light.webp" $path }} 1x" 
                type="image/webp">
            <source 
                srcset="{{ printf "%s_light@2x.png" $path }} 2x, {{ printf "%s_light.png" $path }} 1x" 
                type="image/png">

            <img 
                src="{{ printf "%s_light.png" $path }}" 
                alt="{{ T "GooglePreferredBadge" (dict "Title" .Site.Title) }}" 
                width="338" 
                height="107" 
                loading="lazy"
                class="google-badge-img">
        </picture>

    </a>
</div>
```

```css
.google-badge-img {
    color-scheme: light dark;
    font-style: italic;
    vertical-align: middle;
    height: auto;
    max-width: 100%;
}
```

And that's it.

You will find a live example of this button on my friend's website, [yummyrecipes.uk](https://yummyrecipes.uk), at the end of each individual recipe.


---
## Winget in Windows 11: Say Goodbye to Outdated Software
- **URL:** https://dariusz.wieckiewicz.org/en/winget-say-goodbye-to-outdated-software-in-windows/
- **Date:** 2025-12-19
- **Tags:** Windows 11, Winget, Microsoft, Software Updates, PowerShell, Automation, Intune, Microsoft365, Package Manager

### Content

I have been a fan of Linux since I was young. My favourite branches are these Debian-based. Even though I never officially go full on it, Linux is a part of my daily life, and yours as well.

In daily life, I am using Windows 11, and my main driver is macOS, who derived from Unix. The macOS shares a lot of similarities with Linux, and thanks to the power of the terminal, I can do more than just rely on apps with a GUI (Graphical User Interface).

On the other hand, my other devices all rely on Linux. My router is Linux-based (OpenWrt), I got small Ubuntu server helping me explore stuff and a few Raspberry Pis here and there.

The best feature that I admire in Linux based operating system is the option of managing packages (software) installed in the system. With a few commands using `apt` (Debian) or `opkg` (currently in OpenWrt), I can quickly update all that I am currently using in the system.

This is a feature that I miss the most on Windows. To support myself in having always up-to-date apps installed, I used various software. Some are crap, some are doing their job, like [UCheck](https://www.adlice.com/ucheck/), but none of them are doing everything.

Since Microsoft started to take its Microsoft Store on Windows to their advantage, more and more apps appear there. Most of the apps that are installed directly from their developer website appear there as well, even as a direct link to the installers.

> In opposition to what I said, from a Mac user perspective, I am disappointed by how Apple is utilising its AppStore on macOS. Where iPhones rely on AppStore in 99% of the time, with macOS, there is plenty of staff missing, and that's disappointing.

Thanks to the existence of more and more apps through the Microsoft Store, they can be quickly updated through it without any hustles and that great. However, this does not sort out all the problems.

<!--more-->

We still have some other software installed in our system that would need updating, and here the package [**winget**](https://learn.microsoft.com/en-us/windows/package-manager/winget/) (Windows Package Manager) comes to the rescue.

Forget about expensive software to keep your apps up-to-date and try this solution first.

> Spoiler alert. Some packages provided through Winget may be a version or two behind the current latest, but sometimes that's fine, as it relies more on stability rather than on always the latest, but not always the most edgy version.

**WinGet** is a command-line tool enabling users to discover, install, upgrade, remove and configure applications on Windows.

It's so useful, and reminds me use of `sudo apt update && sudo apt upgrade` in Linux, that I even decided to implement this as an automation on all computers in my workplace.

In a business environment, keeping the operating system up-to-date is not a problem, but keeping apps in the latest version is a different story. As a global administrator in Microsoft 365 infrastructure, help from `winget` will be a game-changer to keep users updated.

## Get WinGet

In the latest version of Windows 11, `winget` can already be available by default, but it's worth running Microsoft Store and, by heading to Downloads, checking for any updates and installing them. This may pull and update to an **App Installer**, which is part of **winget** that we will be using.

If, for some reason command `winget` does not exist (in older Windows 11 versions), you need install it. Just head to [official Winget CLI GitHub Repository](https://github.com/microsoft/winget-cli/releases/latest/) and from **Assets** section download one with **.msixbundle** extension (_ [Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle](https://github.com/microsoft/winget-cli/releases/latest/download/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle)_).

## Winget in Terminal (Admin)

Let's right-click on our Start menu and run **Terminal (Admin)** to try **winget** and see how powerful it is.

> When running WinGet without administrator privileges, in the user **Terminal**, some applications may require elevation to install. You will be prompted to do so wherever required.

To see what software is installed on our computer, you just need to run the following command:

```bash
winget list
```

Notice that the list may be long, and not all the apps can be upgraded through Winget; most of the software can, and we will concentrate on that.

To quickly see outdated apps that can be updated, just run:

```bash
winget upgrade
```

If you want to update a specific app from the list you generated, just add the app name to the above command, but if you want to run an upgrade on all apps, just use the following:

```bash
winget upgrade --all
```

This is the quickest method to get all upgraded.

If, after running `--all`, you still have some apps not updated, this may be due to the way you install the app, but even for that, there is a solution.

In that case, uninstalling it (`winget uninstall`) and installing it back (`winget install`) will solve the issue for the future, so it can be updated through it.

Winget got multiple commands available, but I will not concentrate on this here. [You can explore all Winget commands by learning them from the official Microsoft source](https://learn.microsoft.com/en-us/windows/package-manager/winget/).

What I want to concentrate on is to keep apps updated through an automated task (in Task Scheduler), so we can set it and forget about it.

This is very useful, as it can be deployed through the Intune portal in the Microsoft 365 business environment, to all computers running Windows 11. This is something that I will concentrate on below.

For some of you, running manually `winget upgrade --all` will be something that you may prefer, but for most ordinary users, set and forget approach may be better.

If you are running `winget upgrade` for the first time, you may be asked to accept source agreements. When you want to run it automatically through the task scheduler, you will also need to amend your system to allow running scripts. We will cover all of this in one command.

## Deploy Winget Update Script and Schedule Task

I've been working on some sort of script that will deploy on a user's computer, set everything what needed, schedule a task and execute it on specified time.

I needed to consider a few things before it starts working as intended, but let's analyse what the script includes step by step.

> If you just want the final PowerShell script, head to the [Final Script](#final-script)

### Step 1. Ensure Execution Policy allows script execution

The script, deployed through Intune in a business environment, or run manually, will require enabling the ability for users to execute scripts. This is not enabled by default and needs to be done by executing the following lines in the PowerShell terminal.

```powershell
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope LocalMachine -Force
```

### Step 2: Check if Winget is installed

If your environment does not have **winget** and you didn't manage to install it earlier, as described, the script will check that and, when required, will [download the latest version](https://github.com/microsoft/winget-cli/releases/latest/download/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle) and install it.

### Step 3: Write the full update script content

In the user profile folder (`%userprofile%`), the script will write a file that will be later used by Task Scheduler to run and update apps. The file will be named `winget_upgrade_all.ps1` and will run in silent mode by default.

When working on this file, I stumbled upon some issues with some apps that do not allow running in silence (in the background). In that case, after they are detected as failed, the task will re-run, and the user will be prompted to follow on-screen instructions.

If all goes well and no further failed app updated been found, the script will terminate, and the task will re-run next time when needed.

Inside that script, I considered accepting any source agreements and package agreements that appear for the first time when the user is running the **winget** command, as in other cases, it will fail to do anything, especially when running in silence.

### Step 4: Create or update scheduled task (Weekly trigger for Mon–Fri)

The final step was to create a task in Task Scheduler to do automatic checks at 13:00 every day from Monday to Friday.

Here I stumbled upon some issues again that I need to consider. If the task was already there, I want to make sure that it will be updated. Even then, I faced some issues, so I need to think that if the update of the task fails, to remove it and re-add it.

### Final Script

Finally, I got a script that can either be run manually through the terminal to create required update file and task in Task Scheduler, or deployed through the Intune portal.

In Intune portal, I put this into **Devices** > **Scripts and remediations** under **Platform Scripts** with following options selected:

* Run this script using the logged-on credentials: **Yes**
* Enforce script signature check: **No**
* Run script in 64-bit PowerShell Host: **Yes**

> I haven't used the **Remediations** option, as not all licences, for all my users, allow that.

```powershell
# ============================================
# Deploy Winget Update Script and Schedule Task
# ============================================

# Step 1: Ensure Execution Policy allows script execution
Write-Host "Setting Execution Policy to Bypass..."
powershell.exe Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force
powershell.exe Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope LocalMachine -Force
powershell.exe Get-ExecutionPolicy -List

# Define paths
$UserFolder = $env:USERPROFILE
$ScriptPath = Join-Path $UserFolder "winget_upgrade_all.ps1"
$TaskName = "WingetAutoUpgrade"

# Step 2: Check if Winget is installed
if (-not (Get-Command winget.exe -ErrorAction SilentlyContinue)) {
    Write-Host "Winget not found. Downloading App Installer from GitHub..."
    $WingetUrl = "https://github.com/microsoft/winget-cli/releases/latest/download/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
    $WingetPath = "$env:TEMP\AppInstaller.msixbundle"

    try {
        Invoke-WebRequest -Uri $WingetUrl -OutFile $WingetPath -UseBasicParsing
        if (Test-Path $WingetPath) {
            Write-Host "Installing App Installer..."
            Add-AppxPackage -Path $WingetPath
            Write-Host "App Installer installed successfully."
        } else {
            Write-Host "Failed to download App Installer package."
        }
    } catch {
        Write-Host "Error installing App Installer: $($_.Exception.Message)"
    }
} else {
    Write-Host "Winget is already installed."
}

# Step 3: Write the full update script content
$ScriptContent = @'
# ============================================
# Winget Advanced Upgrade Script
# ============================================

$LogPath = "$env:TEMP\WingetAdvancedUpgradeLog.txt"
Write-Host "Starting Winget upgrade process..." -ForegroundColor Cyan
Write-Host "Logging to $LogPath" -ForegroundColor Cyan
Add-Content -Path $LogPath -Value "`n===== Upgrade Run: $(Get-Date) =====`n"

if (-not (Get-Command winget -ErrorAction SilentlyContinue)) {
    Write-Host "Winget is not installed or not in PATH." -ForegroundColor Red
    Add-Content -Path $LogPath -Value "Winget not found."
    exit 1
}

Write-Host "Running silent upgrade for all apps..." -ForegroundColor Yellow
$SilentResult = winget upgrade --all --silent --accept-source-agreements --accept-package-agreements
Add-Content -Path $LogPath -Value "`nSilent Upgrade Output:`n$SilentResult"

Write-Host "Checking for failed apps..." -ForegroundColor Yellow
$FailedApps = ($SilentResult | Select-String "Installer failed" | ForEach-Object {
    if ($_ -match '\[(.*?)\]') { $Matches[1] }
}) | Where-Object { $_ -ne "" }

if ($FailedApps.Count -gt 0) {
    Write-Host "Retrying failed apps interactively (no --silent)..." -ForegroundColor Yellow
    foreach ($App in $FailedApps) {
        Write-Host "Retrying $App..." -ForegroundColor Cyan
        Add-Content -Path $LogPath -Value "`nRetrying ${App}:`n"
        winget upgrade $App --accept-source-agreements --accept-package-agreements | Out-File -Append $LogPath
    }
} else {
    Write-Host "No failed apps detected." -ForegroundColor Green
    Add-Content -Path $LogPath -Value "`nNo failed apps detected.`n"
}
'@

# Save the script to user folder
Set-Content -Path $ScriptPath -Value $ScriptContent -Force

# Step 4: Create or update scheduled task (Weekly trigger for Mon–Fri)
$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$ScriptPath`""
$Trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday,Tuesday,Wednesday,Thursday,Friday -At 13:00
$Principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive -RunLevel Highest

if (Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue) {
    try {
        Write-Host "Scheduled task '$TaskName' already exists. Attempting update..."
        Set-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger
    } catch {
        Write-Host "Update failed. Removing and recreating task..."
        Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false
        Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger -Principal $Principal
    }
} else {
    Write-Host "Creating new scheduled task '$TaskName'..."
    Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger -Principal $Principal
}

Write-Host "Deployment complete: Script saved to $ScriptPath and scheduled task '$TaskName' created or updated."
```

And in such a way, I have implemented a better way to keep my and my users' devices software updated, thanks to **winget**.


---
## Modern Website Colour Theme Switcher with only HTML and CSS
- **URL:** https://dariusz.wieckiewicz.org/en/modern-website-colour-theme-switcher-with-only-html-css/
- **Date:** 2025-11-09
- **Tags:** dark mode, light mode, HTML, CSS, prefers color scheme, color scheme, light dark, backwards compatibility, switcher

### Content

I recently found time to watch a very insightful, fast-paced presentation by [Adam Argyle](https://nerdy.dev) titled "**25 New & Rad Features of CSS**".

{{% details-summary "Watch here: 25 new & rad features of CSS by Adam Argyle" %}}
{{< youtube QW6GECIzvsw >}}
{{% /details-summary %}}

After just five minutes, when he demonstrated the use case of `@view-transition { navigation: auto; }` and the whole crowd reacted positively, I was hooked and watched until the end.

I learned a great deal and implemented many of the features mentioned in my websites. Some of them I had heard of before, but I am not keen to implement everything straight away. When technologies are still at the early stage of adoption in web browsers, I tend to wait. The problem is that later I often forget about them, which is why Adam’s presentation reminded me of some of the concepts I had already come across.

One of these was the use of `color-scheme: light dark;` and the `light-dark()` syntax approach for light and dark colours.

<!--more-->

On my website, I implemented a three-way colour switcher some time ago. However, this relied heavily on JavaScript and CSS rules that needed to be **duplicated** to achieve the intended output.

With the adoption of `light-dark`, it was time for me to move away from that approach and convert my three-way colour theme switcher into **HTML and CSS only**.

> I added minimal JavaScript — **optional**, yet useful from the user’s perspective.

I was amazed by how easy the conversion was, and that the functionality for users remained unchanged. To be honest, I doubt anybody noticed any differences. The improvement is most evident in the simplicity of my CSS on my end, but for an ordinary visitor, it is business as usual.

Let’s take a look at my implementation.

Feel free to use it on your own website :)

---

## CSS – prefers-color-scheme (backwards compatibility)

Before I implemented the new `light-dark()` approach for light and dark mode on my website, I asked myself two questions:
- Will this work for users who are not on the latest browser?
- Will the colours still display as intended?

The answer was **no**.

Because of that, I needed to ensure backwards compatibility for as long as necessary.

I placed my colours within the `:root {}` element in my CSS. By default, everything in that element refers to light colours. I then specified the option for the dark theme using a `@media` query, as I have been doing for some time.

In standard form, it looks like this:

```css
/* Light theme (default) - Fallbacks for browsers that don't support anything */
:root {
  --main: #137faa;
}

/* Dark theme - Fallback for browsers that support media queries but not light-dark() */
@media (prefers-color-scheme: dark) {
    :root {
      --main: #2EBAE0;
    }
}
```

The `--main` variable is a defined parameter for my primary colour, which I later use in my CSS as follows:

```css
.article-entry p > a {
  color: var(--main);
}
```

That works just as it did before. When a user sets their device to light mode, they are served the primary colour `#137faa`. When they switch to dark mode, they are served the dark version of the primary colour `#2EBAE0`.

## CSS – color-scheme (future compatibility)

Once the backwards compatibility fallback is in place, it is time to incorporate the new syntax. I am doing this in such a way that it will only be applied when the user’s browser supports `color-scheme: light dark`; hence the use of the `@supports` clause and embedding `:root {}` inside it.

Starting with `color-scheme: light dark;`, we then focus on predefining parameters used throughout the styles.

```css
/* New syntax for modern browsers */
/* This block will be read by modern browsers and override the fallbacks */
@supports (color-scheme: light dark) {
  :root {
    color-scheme: light dark;

    --main: light-dark(#137faa, #2EBAE0);
  }
}
```

As you can see, the syntax `light-dark(#137faa, #2EBAE0);` is much simpler. When applied to a light theme, it uses `#137faa` for the primary colour, and when switched to dark mode, it applies `#2EBAE0` as the dark variant.

This approach is simple yet powerful, allowing you to keep your CSS far tidier and clearly distinguish where colours switch and where permanent colours are applied.

Now it’s time to work on our colour theme switcher.

## HTML – three-way colour theme switcher

My previous colour switcher was based on [The Best Light/Dark Mode Theme Toggle in JavaScript](https://whitep4nth3r.com/blog/best-light-dark-mode-theme-toggle-javascript/) by Salma Alma-Naylor and [It’s Tri-State Switch Time](https://www.brycewray.com/posts/2024/01/its-tri-state-switch-time/) by Bryce Wray.

There is nothing wrong with it, and it works well in both older and modern browsers. The only issue, on my end, was that I needed to consider different ways of serving colours.

For example, when a user has dark mode enabled but wants to switch the website to light mode, or when the site defaults to light mode but the user prefers dark mode.

This introduces a degree of complexity with `[data-theme="dark"]` and `[data-theme="light"]`. I have to think in reverse: when the light theme is set on the user’s device but the switcher is set to dark, the `:root {}` must serve the dark version of the colours, as in that case the `@media` query contradicts the selected option on the switcher.

I have now decided to remove that complexity, with a small trade-off that I will address later.

---

**My new HTML-only switcher**, which does not rely on any JavaScript, looks like this:

```html
<div class="switchTheme">
    <label class="lightLabel" title="{{ T "LightMode" }}">
        <input type="radio" name="switchTheme" value="light" id="lightMode" aria-label="{{ T "SelectLightMode" }}">
        <span class="toggle-switch__control"></span>
    </label>
    <label class="autoLabel" title="{{ T "AutoMode" }}">
        <input type="radio" name="switchTheme" value="light dark" id="autoMode" aria-label="{{ T "SelectAutoMode" }}" checked>
        <span class="toggle-switch__control"></span>
    </label>
    <label class="darkLabel" title="{{ T "DarkMode" }}">
        <input type="radio" name="switchTheme" value="dark" id="darkMode" aria-label="{{ T "SelectDarkMode" }}">
        <span class="toggle-switch__control"></span>
    </label>
</div>
```

> As I use [Hugo](https://gohugo.io) to build my website, I have incorporated translated elements into `aria-label` and `title`.

{{< details-summary "i18n\en.toml" >}}
```toml
[LightMode]
other = "Light mode"
[SelectLightMode]
other = "Select light mode"
[AutoMode]
other = "Auto mode"
[SelectAutoMode]
other = "Select light or dark mode automatically"
[DarkMode]
other = "Dark mode"
[SelectDarkMode]
other = "Select dark mode"
```
{{< /details-summary >}}

Modifying my switcher to the new approach does not require me to change (almost) any of my original CSS code.

{{< details-summary "elements of switchTheme from style.css" >}}
```css
/* tri-state darkmode switch toggle HTML CSS only */

.switchTheme {
	display: flex; /* only this will be moved further */
	flex-direction: row;
	gap: 0;
  white-space: nowrap;
  width: 6rem;
  justify-content: space-around;
}

.lightLabel,
.autoLabel,
.darkLabel {
  display: inline-block;
}

.switchTheme input[type="radio"] {
  display: none;
}

.switchTheme svg {
  fill: var(--black);
  height: 1rem;
  width: 1rem;
}

/* sun */
#lightMode + .toggle-switch__control::after {
  height: 1.5rem;
  width: 1.5rem;
  display: block;
  content: '';
  -webkit-mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Zm326-268Z'/></svg>") no-repeat 50% 50%;
  mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Zm326-268Z'/></svg>") no-repeat 50% 50%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: var(--nightgray);
}

/* auto */
#autoMode + .toggle-switch__control::after {
  height: 1.5rem;
  width: 1.5rem;
  display: block;
  content: '';
  -webkit-mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M276-280h76l40-112h176l40 112h76L520-720h-80L276-280Zm138-176 64-182h4l64 182H414Zm66 376q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q133 0 226.5-93.5T800-480q0-133-93.5-226.5T480-800q-133 0-226.5 93.5T160-480q0 133 93.5 226.5T480-160Z'/></svg>") no-repeat 50% 50%;
  mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M276-280h76l40-112h176l40 112h76L520-720h-80L276-280Zm138-176 64-182h4l64 182H414Zm66 376q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q133 0 226.5-93.5T800-480q0-133-93.5-226.5T480-800q-133 0-226.5 93.5T160-480q0 133 93.5 226.5T480-160Z'/></svg>") no-repeat 50% 50%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: var(--nightgray);
}

/* moon */
#darkMode + .toggle-switch__control::after {
  height: 1.5rem;
  width: 1.5rem;
  display: block;
  content: '';
  -webkit-mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z'/></svg>") no-repeat 50% 50%;
  mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z'/></svg>") no-repeat 50% 50%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: var(--nightgray);
}

/* sun:checked */
#lightMode:checked + .toggle-switch__control::after {
  height: 1.5rem;
  width: 1.5rem;
  display: block;
  content: '';
  -webkit-mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Zm326-268Z'/></svg>") no-repeat 50% 50%;
  mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Zm326-268Z'/></svg>") no-repeat 50% 50%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: var(--yellow);
}

/* auto:checked */
#autoMode:checked + .toggle-switch__control::after {
  height: 1.5rem;
  width: 1.5rem;
  display: block;
  content: '';
  -webkit-mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path  d='M276-280h76l40-112h176l40 112h76L520-720h-80L276-280Zm138-176 64-182h4l64 182H414Zm66 376q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q133 0 226.5-93.5T800-480q0-133-93.5-226.5T480-800q-133 0-226.5 93.5T160-480q0 133 93.5 226.5T480-160Z'/></svg>") no-repeat 50% 50%;
  mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M276-280h76l40-112h176l40 112h76L520-720h-80L276-280Zm138-176 64-182h4l64 182H414Zm66 376q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q133 0 226.5-93.5T800-480q0-133-93.5-226.5T480-800q-133 0-226.5 93.5T160-480q0 133 93.5 226.5T480-160Z'/></svg>") no-repeat 50% 50%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: var(--main);
}

/* moon:checked */
#darkMode:checked + .toggle-switch__control::after {
  height: 1.5rem;
  width: 1.5rem;
  display: block;
  content: '';
  -webkit-mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z'/></svg>") no-repeat 50% 50%;
  mask: url("data:image/svg+xml;charset=UTF-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'><path d='M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z'/></svg>") no-repeat 50% 50%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: var(--yellow);
}

.toggle-switch__control { cursor: pointer;}

/* END tri-state darkmode switch toggle HTML CSS only  */
```
{{< /details-summary >}}

> Some examples of incorporating the `light-dark()` approach and the three-way switcher can be found in the article [CSS colour-scheme-dependent colours with light-dark()](https://web.dev/articles/light-dark) on *web.dev*. For a basic understanding of the `light-dark()` approach, I strongly recommend reading Trys Mudford’s post on [Implementing light-dark()](https://www.trysmudford.com/blog/light-dark/).

To make the switcher work, you need to integrate its state with CSS.

### CSS for three-way colour theme switcher

Here is the essential part of the CSS that enables the switcher to function based on its state.

```css
  /* When the "Auto" (light dark) radio is checked */
  &:has(input[name="switchTheme"][value="light dark"]:checked) {
    color-scheme: light dark;
  }
  
  /* When the "Light" radio is checked */
  &:has(input[name="switchTheme"][value="light"]:checked) {
    color-scheme: light;
  }
  
  /* When the "Dark" radio is checked */
  &:has(input[name="switchTheme"][value="dark"]:checked) {
    color-scheme: dark;
  }
```

That’s not all.

As I have been considering backwards compatibility, I need to remember that for browsers which do not yet support the `light-dark()` syntax, **my switcher will not work**. In such cases, the website’s state (light or dark mode) will rely entirely on the user’s system settings.

## CSS – hiding the switcher for outdated browsers

In the case where a user visits my website with an outdated browser, showing the switcher does not make any sense. Therefore, I decided to reuse the `@supports` approach to conditionally display it only for modern browsers.

I hide my switcher by default and restore it for browsers that support `color-scheme`.

```css
.switchTheme {
  /* Hides the switch from all browsers initially */
  display: none !important; 
}

/* If the browser supports both the color-scheme property */
@supports (color-scheme: light dark) {
  .switchTheme {
    /* Only display the switch in capable browsers */
    display: flex !important; /* this was moved from main CSS for my switcher */
  }
  /* rest CSS from previous part */
}
```

> Be advised that my switcher is positioned using a `flex` element, which has been removed from the main CSS section and moved into the above.

By switching to an HTML- and CSS-only implementation, **I lost one crucial functionality** which, from the user’s perspective, may be slightly annoying. When they change the theme using the switcher and then navigate to another page on my website, the state is not remembered and reverts to the default (system-controlled) setting.

To restore this, I need to add a very minimal amount of JavaScript at the end to incorporate memory.

```
<script defer src="darkmode-toggle-memory.js"></script>
```

## JS (optional) – remembering the state of the switch

To store the state of the switcher in my previous JavaScript-based implementation, I used the browser’s `localStorage`.

I will reuse this part to add memory to my new version.

```js
// A single key to store the user's preference value (e.g., 'dark', 'light', 'light dark')
const THEME_STORAGE_KEY = 'theme-preference';

// Get all the radio buttons
const themeRadios = document.querySelectorAll('input[name="switchTheme"]');

// --- 1. Load State on Page Load ---
const savedTheme = localStorage.getItem(THEME_STORAGE_KEY) || 'light dark'; // Default to 'auto'
const savedRadio = document.querySelector(`input[name="switchTheme"][value="${savedTheme}"]`);

if (savedRadio) {
    // Check the radio button that matches the saved value
    savedRadio.checked = true; 
} 
// Your existing CSS will now pick up this checked state via the :has() selector!

// --- 2. Save State on Click ---
themeRadios.forEach(radio => {
    radio.addEventListener('click', () => {
        // When clicked, save its 'value' to localStorage
        localStorage.setItem(THEME_STORAGE_KEY, radio.value);
    });
});
```

This resolves the memory of state for the switcher, and without adding any noticeable weight, it works smoothly for everyone.

Users who browse with JavaScript disabled by default—and their numbers are steadily increasing—will also be satisfied with this approach.

Regards.


---
## Toilet Paper, Differently – Part 2
- **URL:** https://dariusz.wieckiewicz.org/en/toilet-paper-differently-part-2/
- **Date:** 2025-10-26
- **Tags:** Toilet Paper, Who Gives a Crap, Lidl, Floralys Quilted Toilet Tissue, Quality, Price

### Content

Days are passing by, and rolls are rolling. We invested in new paper, but from the very beginning, there was something unusual about it.

After a few days of use, we still actively compare it with the Lidl brand (Floralys Quilted Toilet Tissue), and suddenly, my wife noticed why Who Gives a Crap (WGaC) toilet paper feels different.

I thought it was nostalgia from the late 80s/early 90s, but **no!**

Although I mentioned that Lidl-branded rolls do not compare with WGaC rolls, due to size, **sometimes size doesn't matter.**

<!--more-->

To be exact about size, I am talking about the number of sheets of 3-ply paper.

**The size indeed matters**, and here was the catch!

The WGaC rolls indeed contain more sheets, but if you look closely, the individual sheets are not the same. **The WGaC sheet is shorter than the Lidl brand!**

> About the size difference in a few moments.

This means that 400 sheets are not 400 sheets when you compare them directly with the Lidl brand.

Because of that, all my previous calculations included errors, and it may be a significant one. Based on its significance, I will rethink whether keeping the subscription is worth it.

The more we use it, the more we notice that the quality and experience are worse. We intended to use the same amount, but to last for longer, yet in reality, it was the total opposite.

{{% ads-in-article %}}

## Size difference

[![Lidl Floralys toilet roll vs Who Gives a Crap](stacked_paper.jpg "Lidl Floralys toilet roll (left) vs Who Gives a Crap (right)")](stacked_paper.jpg)

400 sheets of paper sound impressive. That's, in theory, 2.5 times a Lidl-branded roll in one.

[![QR Code on paper core of the Who Gives a Crap toilet paper](qr_code_core.jpg)](qr_code_core.jpg)

When you finish your roll, you will be presented with a fancy core with a QR code that will lead you to the **farting button**. It may be fun to try this for the first time, but in the long run, you will quickly ignore it.

The core itself is slightly smaller and fits tightly inside the Lidl-branded toilet paper core.

**However, it's all about the details.**

---

[![Toilet paper cores - Lidl Floralys vs Who Gives a Crap](paper_cores.jpg)](paper_cores.jpg)

I did some tests and checked the weight of the core and the paper itself to compare how much my initial calculations were wrong and how much more expensive WGaC is.

> The weights are not super accurate, as they are rounded to the nearest 1g, but it's enough to conclude the difference.

Each **core** (Lidl and WGaC) **weighs ~4g**.

---

[![Who Gives a Crap and Lidl Floralys sheet of paper stacked on each other](stacked_sheets.jpg)](stacked_sheets.jpg)

If you look at the sheets themselves and stack them (Lidl vs WGaC) on top of each other, you will quickly notice the difference!

The Lidl-branded sheets are **130×100mm**, whereas the WGaC sheets are just **100×100mm**. This 30mm (3cm) makes a big difference.

[![Sheet size difference between Lidl Floralys and Who Gives a Crap](sheet_size_difference.jpg)](sheet_size_difference.jpg)

---

Let's see how these 400 sheets of shorter paper compare to the 160-sheet Lidl-branded one, knowing already that **the 2.5× bigger roll is practically a scam**.

**The weight difference:**
- Lidl – **101g** (with core), 97g without core.
- WGaC – **202g** (with core), 198g without core.

Here we see that our 2.5× has shrunk to just 2 rolls in one.

**Let's do some maths!**

---

**Lidl Paper:**
* Total paper weight: 97g (excluding core)
* Number of sheets: 160

Weight per sheet = 97g / 160 sheets = **0.60625g per sheet**

**WGaC Paper:**
* Total paper weight: 198g (excluding core)
* Number of sheets: 400

Weight per sheet = 198g / 400 sheets = **0.495g per sheet**

So, Lidl paper sheets are a bit heavier than WGaC paper sheets, **and you can feel it!**

From our household’s experience, we quickly noticed that **instead of saving, we were using more**. More sheets used means the WGaC paper runs out quickly.

> There were also some complaints about splitting the sheets and the fact that the paper does not flush as well as the Lidl one, forming small clogs, which causes another kind of problem!

**Lidl Paper with WGaC Weight:**
* Weight per Lidl sheet: 0.60625g
* Total WGaC paper weight: 198g

Number of Lidl sheets at WGaC weight = 198g / 0.60625g per sheet ≈ **326.53 sheets**

This simple math exercise shows a stunning difference: 1 roll of Lidl-branded paper, which has 160 sheets, by weight, compares to slightly over 326 sheets of WGaC.

**The initial comparison of 2.5× more paper, which later became just 2×, shrank even further!**

**WGaC Paper with Lidl Weight:**
* Weight per WGaC sheet: 0.495g
* Total Lidl paper weight: 97g

Number of WGaC sheets at Lidl weight = 97g / 0.495g per sheet ≈ **196.97 sheets**

So, if Lidl paper weighed the same as WGaC, there would be approximately 327 Lidl sheets. If the WGaC paper weighed the same as Lidl, there would be about 197 WGaC sheets.

From this exercise, **the WGaC is just 1.23× bigger than Lidl!**

Based on that, the whole price comparison [from my initial post](/en/toilet-paper-differently/) will be significantly different! Let's look at how much.

---

{{% ads-in-article %}}

**Let's break down the cost per sheet and the cost per gram for each paper.**

**Lidl Paper:**
* Total sheets: 16 rolls × 160 sheets = 2560 sheets
* Total cost: £4.99

Cost per sheet = £4.99 / 2560 sheets = **£0.00195 per sheet**

**WGaC Paper:**
* Total sheets: 48 rolls × 400 sheets = 19200 sheets
* Total cost: £44 (standard price)

Cost per sheet = £44 / 19200 sheets = **£0.00229 per sheet**

**Now, let's compare the cost per gram of paper (excluding the core weight).**

**Lidl Paper:**
* Total paper weight: 16 rolls × 97g = 1552g
* Cost per gram = £4.99 / 1552g = £0.00322 per gram

**WGaC Paper:**
* Total paper weight: 48 rolls × 198g = 9504g
* Cost per gram = £44 / 9504g = £0.00463 per gram

**Let's summarise:**

* Cost per sheet – **Lidl is cheaper at £0.00195** vs. WGaC at £0.00229.
* Cost per gram – **Lidl is also cheaper at £0.00322** vs. WGaC at £0.00463.

**Lidl paper is more economical both per sheet and per gram of paper.**

---

Let's calculate the total cost and compare the savings.

**Lidl Paper:**
* Buying 3 sets of 16 rolls (48 rolls): 3 × £4.99 = £14.97

**WGaC Paper:**
* Buying 48 rolls: £44 (standard price)

> Savings by choosing Lidl = £44 − £14.97 = **£29.03**

---

**Per Sheet Comparison:**

* Lidl total sheets for 3 sets: 3 × 2560 sheets = **7680 sheets**
* WGaC total sheets: **19200 sheets**

* Cost per sheet for **Lidl**: £14.97 / 7680 sheets ≈ **£0.00195 per sheet**
* Cost per sheet for **WGaC**: £44 / 19200 sheets ≈ **£0.00229 per sheet**

**Per Weight Comparison:**

* Total weight for Lidl: 3 × 1552g = 4656g
* Total weight for WGaC: 9504g

* Cost per gram for Lidl: £14.97 / 4656g ≈ **£0.00322 per gram**
* Cost per gram for WGaC: £44 / 9504g ≈ **£0.00463 per gram**

Based on the weight differences, you'll **save significantly** by choosing **Lidl**, both in terms of total cost, cost per sheet, and cost per gram.

{{% ads-in-article %}}

## Conclusion

[In my previous post](/en/toilet-paper-differently/), I concluded with _"You may not save money, but you’ll definitely save storage space"._

**This doesn't sound convincing anymore!**

It seems that with the new calculations, Lidl's paper provides significant cost savings, contrary to my initial conclusion. 

By choosing Lidl, you can save a substantial £29.03 directly when purchasing an equivalent number of rolls compared to WGaC. 

Moreover, Lidl is cheaper per sheet and per gram, making it a more economical choice overall.

This new insight highlights the importance of detailed analysis when evaluating product options. If a product needs heavy advertising to gain customers, there is always a catch!

While my initial considerations might have focused on storage space and aesthetic matters, it's clear that Lidl also provides a financial advantage. This makes it an excellent choice for those looking to maximise both budget and value, without compromising on storage efficiency.

**From that conclusion, you know where I am going with it.**

[![This seemed like a nice spot to stop and say... bye!](subscription_cancelled_bye.png)](subscription_cancelled_bye.png)

I like to give new ideas a try, but this needs to work!

I fully understand the whole idea behind WGaC by donating 50% of profits to help everyone gain access to clean water and a toilet; however, this doesn't differ from directly donating to a selected cause, without a middleman.

**I have cancelled my subscription**, and I consider this chapter of my journey closed.


---
## Setting Up Health Notifications for Your Cloudflare Tunnel
- **URL:** https://dariusz.wieckiewicz.org/en/setting-up-health-notifications-cloudflare-tunnel/
- **Date:** 2025-10-18
- **Tags:** Cloudflare, Zero Trust, cloudflared, Tunnel, VPN, VPN alternative, Cloudflare Tunnel, Cloudflare One

### Content

On my current internet connection at home, I do not have direct access to an external IPv4 IP address from my router (only IPv6 is available). Because of this, I am unable to [set up my VPN server using WireGuard](/en/installing-vpn-server-on-router-openwrt-wireguard/) directly. Therefore, I need to support myself with Cloudflare Zero Trust technology.

Following my guide on how to [add a Cloudflare Tunnel to an OpenWrt Router](/en/adding-cloudflare-tunnel-to-openwrt-router/), as a WireGuard VPN alternative, I managed to regain access to my network from outside my home.

There is, however, one issue with this solution.

<!--more-->

Using the dedicated [Cloudflare One app](https://apps.apple.com/us/app/cloudflare-one-agent/id6443476492) (or the reconfigured [1.1.1.1 app](https://apps.apple.com/us/app/1-1-1-1-faster-internet/id1423538627) to use the tunnel), after logging in using my credentials, I can quickly connect to my network.

{{% gallery %}}
[![Cloudflare One app – disconnected](Cloudflare_One_app_disconnected.png)](Cloudflare_One_app_disconnected.png)
[![Cloudflare One app – connected](Cloudflare_One_app_connected.png)](Cloudflare_One_app_connected.png)
{{% /gallery %}}

The only problem is that when you are **connected** using your app, you cannot be sure if your tunnel is working and you have access to your network without checking.

When you toggle the button in the app, you receive information that you are **connected**. This only means that your device is connected to the Cloudflare infrastructure.

If your tunnel goes down, your router goes down, or your internet connection at home fails, you will not notice the difference, and you will still see the **connected** information. Your internet connection remains secured through Cloudflare Zero Trust; however, you do not have access to your local network when your tunnel is down.

The only way to check if everything is working is to load your router homepage (such as 192.168.1.1 for the default IP of an OpenWrt router) in a browser, ping it, or try to access other resources available on your local network.

Another way is to log in to your [Zero Trust homepage](https://one.dash.cloudflare.com), navigate to **Networks** > **Tunnels**, and check if your tunnel displays **status** as **healthy**.

[![Your Cloudflare Tunnels and its Status](Your_Cloudflare_Tunnels.png)](Your_Cloudflare_Tunnels.png)

This is a somewhat time-consuming process either way and can be frustrating in situations when you need to quickly gain access, but you cannot.

I experienced this situation recently when the CityFibre box, which sits between the fibre cable leading to my home and the ethernet cable leading to my router, stopped working.

Despite all the lights on this box being green, the router couldn't access the network.

A power cycle of the CityFibre box solved the problem, but while being outside, despite seeing the **connected** message, I didn't realise my tunnel was down.

I thought it would be helpful to know when my tunnel goes down, preferably by email.

In the past, I have been using (and still use) services like [UptimeRobot](https://uptimerobot.com/?rid=a70f0d8f7559d7) to ping my router's external IPv4 to know when the internet connection is down.

I have set up a similar approach by pinging my router's IPv6 address, which seems to be static, but that only provides information when my internet is down.

The **cloudflared** app runs on my OpenWrt router and sometimes can crash or disconnect, especially when the app performs a self-update from time to time.

It would be nice to know, specifically for Cloudflare Tunnel, when it goes **down**, when it is **degraded** for some reason, or when it is back online and **active**.

Fortunately, there is a solution for that.

Heading to the [Cloudflare dashboard](https://dash.cloudflare.com), there is a section called **Notifications**.

Inside, we can **Add** a notification for a specific product used in the Cloudflare infrastructure.

From the **Product** dropdown box, select **Tunnel** to show only the options relevant to what we need.

Currently, the following alert types are available:
- **Tunnel Creation or Deletion Event**
  - Receive an alert when a new tunnel is created or an existing tunnel is deleted.
- **Tunnel Health Alert**
  - Receive an alert regarding the health of a tunnel.

[![Cloudflare Notifications for Product – Tunnel](Add_Notification.png)](Add_Notification.png)

What we need is **Tunnel Health Alert**.

[![Cloudflare Notifications – Name of notification](Edit_Notification.png)](Edit_Notification.png)

Let's **Select** it and put a friendly and readable **Notification name**, like `Cloudflare Tunnel`.

[![Cloudflare Notifications – Select tunnels for notifications](Select_tunnels_for_Notifications.png)](Select_tunnels_for_Notifications.png)

In **Add tunnel(s)**, tick the box next to your created tunnel.

> I also checked **Include future tunnels**, so the notification will be set once, and we won't need to amend it whenever we decide to make changes in the tunnels section in the future.

The default option for alerts is set to notify when the tunnel **becomes either healthy, degraded, or down**. Adjust it according to your preference.

[![Cloudflare Notifications – Email to be notified](Notification_email.png)](Notification_email.png)

Follow it by setting the **Notification email** and save by pressing the **Save** button.

[![Cloudflare Notifications](Cloudflare_notifications.png)](Cloudflare_notifications.png)

In such a way, your notifications are ready. To see how we will be notified in the future, let's press the **Test** button and check our inbox.

[![Cloudflare Notifications – Test email notification](Test_email_Cloudflare_Tunnel_Notifications.png)](Test_email_Cloudflare_Tunnel_Notifications.png)

In no time, we shall get an email titled **[Alert] Tunnel tunnel-name is now degraded (status change)**. This is how we will be notified when the tunnel is detected to be **down**, **degraded**, or back as **healthy**.

A simple yet useful notification becomes handy and gives you an overview of when you have access to your local resources and when not, despite the app showing a **connected** status.


---
## Windows 10 End-of-Life: Migration Options and Alternatives
- **URL:** https://dariusz.wieckiewicz.org/en/windows-10-end-of-life/
- **Date:** 2025-10-13
- **Tags:** Windows 10, ChromeOS Flex, ChromeOS, Chromebook, Chromebox, Linux, Linux Mint, Lubuntu, Ubuntu, Windows 11, macOS, MacBook, iPad, iPadOS, Extended Security Updates, ESU

### Content

We have been aware of the End of Life (EOL) for Windows 10 for some time. If you don't, and you are still working on it, then you must be living under a rock for some time.

Microsoft already spammed you with full-screen advice to purchase Windows 11, even on hardware that is not suitable for it!

Migration to Windows 11 has caused a lot of headaches, as it often requires users, even with very powerful hardware, to seek an upgrade.

In a business environment, it's even more difficult, as all changes of this sort require extensive testing, but what's more challenging, they require users to adapt to changes, which are not always the easiest ones.

Personally, I have been doing migration in a business environment for some time, before even the deadline was on the horizon (like it is now).

One year before the deadline (14th October 2025), all computers in my main place of work will have already been upgraded or replaced, and everybody will have been adjusting to work with Windows 11 for some time.

> "Windows 10 end-of-life (EOL) is October 14, 2025. After this date, Microsoft will no longer provide free security updates, bug fixes, or technical support for Windows 10. While your Windows 10 PC will still function, it will become increasingly vulnerable to security risks and less compatible with new software and hardware."

<!--more-->

If your company right now is still telling you to work on a computer running Windows 10 (or even older), you need to tell yourself something clearly: your IT team (if they even exist) is not doing their job right, as they should already be on top of it. On the other hand, it may not always be the IT team's fault if they got their hands tied behind their back by people above them, people with money, who do not see the need for change, and they will pay when it is really necessary. Sometimes it's too late.

In a business setting, migration is difficult due to the need for extensive testing and user adaptation, often exacerbated by budget holders ("people with money") who delay necessary change. Ignoring the deadline places the company in an insecure position, akin to running Windows 11 on unsupported hardware, where updates are missed and Microsoft support is unavailable.

Whereas in a business environment, you may not have such power to make a change; however, in your home, if you are still utilising Windows 10, you should think right now about what to do.

Here are some of my thoughts on where you can go with it.

---

If you are just a casual computer user, you use it to use the internet, write and print some stuff, contact others, and invest in new hardware that is compatible with Windows 11, maybe a bit of overkill.

Buying a new computer, only because you need to update to Windows 11, even though you are not using the computer above 5% of its capability, is a waste of money, resources, and definitely not helping the environment.

In that case, why not think about keeping your hardware by putting a new life into it? It's especially beneficial if your computer is still running quite well, and you may be a bit tight on your budget.

One of the options can be to remove Windows 10 from your computer and replace it with something else.

## ChromeOS Flex

One of the things you may consider is installing ChromeOS Flex. This operating system is very similar to those seen on Chromebooks, but it is intended for ordinary hardware with some limitations.

It's a nice and simple operating system that just requires an internet connection to do all the things you may need, as a less advanced user.

You can browse the internet, organise your files either on the computer itself or through integrated Google services and Google Drive.

There are plenty of things available that will allow you, in the new system, to be productive as you were on Windows.

> Assuming that you are a user whose journey finishes with the software that has been supplied with the computer itself.

ChromeOS Flex is very fast, even on very old hardware. It's updated regularly, so you will not feel left behind, and is prone to typical infections that you may come across using Windows computers.

Flex, however, is not full Google ChromeOS as seen on dedicated Chromebooks (or Chromeboxes).

If you are an Android user, you will miss access to the Play Store. Having the Google Play Store adds additional power to your device, allowing you to install everything that is typically available for Android Phones and Android Tablets. It also allows you to better integrate your devices. The work is just going to the next new level.

Despite the lack of the Google Play Store, there is a store for Web Applications that can run and fill the gap. The only caveat is that you will need to have an active internet connection to cherish all that you get.

ChromeOS Flex is free to download and use, and to start, you will just need a USB Memory Stick, a minimum of 8GB, to put the installer into it and install the system on your computer from it.

> Make sure to make a backup of all your crucial files from your current hard drive, as the ChromeOS Flex installer will clean your hard drive upon installation.

If you tried ChromeOS Flex and you like the ChromeOS experience, but need a bit more, or you are missing some things, you may think about moving into the Chromebook world.

There is plenty of hardware available to buy that is a couple of years old, but has support for it going past 2030, securing your productivity for times to come.

## ChromeOS on Chromebook

Moving into the ChromeOS world, which allows you to cherish the Android environment and access to the Google Play Store, will require you to invest in hardware.

However, some low-end devices, for ordinary users, are quite cheap to get. In most cases, Chromebooks are much cheaper than their Windows 11 alternatives. Of course, with Windows 11, you can do way more, but this is why it's important to see what type of user you are and what your needs are.

Chromebooks like Lenovo IdeaPad Flex 3, 14" non-touch (2020), you can buy used for way below £100 now. Unless you damage it mechanically or something unexpected happens, this device will serve you until June 2030!

Before you buy any Chromebook, check on [Auto Update policy website](https://support.google.com/chrome/a/answer/6220366) for how long the device will be supported. You will know in advance how long it will work for you. 

Freshly released Chromebooks, at the start, receive ten years of updates, but sometimes even that is moved past that point.

The hardest part of using the ChromeOS environment is changing your own behaviours inherited from other operating systems, but if there is a will to learn, there is always a way.

ChromeOS is another operating system that allows running apps from the Google Play Store; it's just an option to add an Android environment through (not directly visible) virtualisation.

There has been a lot of discussion recently suggesting that Google is planning to combine ChromeOS and Android into a single platform. This isn't about ending ChromeOS entirely, but rather a long-term project to unify the two operating systems.

This will make sense performance-wise, hence interesting plans brewing ahead.

At the end of the day, ChromeOS looks like a separate system, and Google will plan to get it closer to Android (Android on its own is not a system optimised for desktop computers) to be able to compete with the Apple ecosystem, where iPhones and iPads work in better symbiosis with MacBooks and macOS than it is currently happening in ChromeOS. We will see how it will go.

Even though that, I think the positive change is coming, and if you are planning to buy a device that will still be supported in 2035, you will see the value for money in moving into the ChromeOS environment.

{{% ads-in-article %}}

## Linux (Mint, Ubuntu, Lubuntu)

If you think about yourself as a more advanced user, you may think about stepping into the Linux world.

It is never easier than now to install Linux on your computer.

I am a long-time supporter of Ubuntu Linux, and this, along with Linux Mint, is something that I would recommend trying. If your hardware is over ten years old, maybe a lighter version of Lubuntu will work better.

There is plenty of software working on Linux, but also plenty that you will struggle to find. This is why it's worth checking what you're using your computer for before deciding where to go. Or simply, try and see. If it will not work with one approach, move to another.

Most Linux operating systems come with a desktop environment that can be selected to satisfy its user rather than forcing you to accept what is provided.

Linux, I would say, is more for people who are ok with tinkering daily. If breaking stuff and finding a way to fix it on your own, to learn something, is something that you are fancy about and you have time for, go for it.

The majority of Linux operating systems are distributed for free to download and use. You will just need a USB memory stick, a minimum of 8GB, to put the installer on it and install the system on your computer from it.

If you are looking for stability and rely on specific software that will keep you moving (the software is not available on ChromeOS or Linux), you may think further.

There are still some options.

## New computer with Windows 11

Assuming you analysed your options and you decided that you need to upgrade. This decision doesn't mean you need to spend hundreds of pounds on new hardware.

There are many pre-pandemic devices with Intel Core 8th generation computers, laptops, that are fully compatible with Windows 11, and they will cost you around £60-80, only!

This Intel Core 8th Generation may not be the fastest device available, yet if you follow widely acknowledged minimum recommendations of 8GB of RAM and 256GB SSD, you cannot go wrong with it.

If your budget is up to £100, you can, with a bit of luck, buy a laptop with Intel Core 11th Generation that will last a bit longer.

If you do not know what you need, but you know that you want a device compatible with Windows 11, just follow this:

 - minimum 8GB of RAM, recommended 16GB
 - minimum 256GB SSD storage, recommended 512GB

The rest is up to you and your budget.

If you, however, don't want to spend money on new hardware, you can, theoretically, put Windows 11 on your unsupported hardware. This is a route that I would not recommend, especially in a business environment, but it's easy to do.

You will not have a pleasant usage experience the longer you use it, but that's the consequence of your actions.

## Windows 11 on unsupported hardware

Let me remind you at the beginning:

**Don’t go the route of updating to Windows 11 on unsupported hardware.**

If your computer is not designed to run Windows 11, by installing it (it is possible), you will not suddenly make it supported!

**Be aware also!**

There are plenty of rubbish sellers around selling old hardware with Windows 11 pre-installed, even on Amazon UK!

This is a waste of money and puts you at risk of being left behind.

This is a tough cookie. A used device, only because the seller put Windows 11 on it, doesn't mean that it can, or should, be used with it.

Microsoft prepared a handy website, where you can check if the processor (Intel, AMD or Qualcomm) is designed/supported with Windows 11. Simply check it before you buy it!

> [https://learn.microsoft.com/en-us/windows-hardware/design/minimum/windows-processor-requirements](https://learn.microsoft.com/en-us/windows-hardware/design/minimum/windows-processor-requirements)

If you decide, however, to go this route or you have been sold unsupported hardware with Windows 11, there are consequences.

> Don't waste your time complaining that your computer is not supported, but Windows 11 is working fine. It will, but at some point, things will start falling short, and Microsoft will be sure to put a log on front of you, with a new update, to make sure you will not have an easy life.

You will be missing relevant updates to the system, things will be breaking, and you will not have support for it, even if you pay Microsoft to help you. What's more important, if you are missing some security updates, you are putting yourself in the same boat if you stay on Windows 10 after its end of life.

I've been doing my research about Windows 11 on unsupported hardware only to learn where the limits are. Even though I tried and worked on it for some time, in the end, I decided to change the hardware to a compatible one to have a more pleasant experience.

A simple computer with Intel Core i5, 8th Generation (from roughly 2018) is at the bottom of the supported hardware list that will run Windows 11 without any tricks or hacks. This hardware is very cheap to buy. You can get a laptop, fully compatible with Windows 11, starting from just £60 on eBay!

However, if you have enough Windows altogether, there are viable options to try right now, especially if you are not tight on the budget.

{{% ads-in-article %}}

## macOS - Your First MacBook

If you use your computer for an extended period of time, and you are not really rushing into changing hardware very often, you have another option. If you are looking for stability and software availability, and, in the case of laptops, enormous battery life, it's worth thinking about moving into macOS.

The hardware from Apple is never cheap; however, it is designed to last and supported for a very long time.

The problem is not a price, as you may initially think. If you look into putting your purchase into instalments and then see how long your device, when handled properly, will last you, it will be good value for money.

However, macOS is not for everybody!

Apple hardware is like buying a Porsche. You may like how it looks, how it works, but if you utilise it only for going to the bakery for bread every morning, is that money well spent? Of course, it depends; however, from a practical point of view, this may be overkill for you.

If you know what you are using your computer for, you may quickly see how a computer with macOS will do its job. What's important about macOS is its stability and higher security than Windows devices. 

If you are using your device professionally, you need to rely on it when you need it most. If you are suddenly forced to restart, to install updates, when you are in the middle of work, that's not a great way for the device to work for you, and not you, bending your workload to the needs of the device.

The stability of Apple devices is key, and after-service support, which is something that you can always rely on, is what sold me my first Apple devices years back.

But a laptop or desktop is not the only device that you can consider as a replacement for your Windows 10 device. There are other options.

## Your first tablet

Sometimes you will need to have a device at hand, ready in just a second, to do something where using a computer is not really practical. 

This is where tablets come into play.

If your workload is oriented towards communication, browsing emails, casual document work, and some specific apps, tablets, some as a blend between functionality and portability, are suitable.

They are designed to be ready at the first press of a finger.

This device may not be able to replace all your workload, depending on how much you tend to use your computer for.

It's all about self-assessment, how you've been using your computer in the first place.

In regards to tablets, you have options between Android and Apple hardware. With Android, it is a bit hit and miss, as if you work with a price tag, you will get a device that will not last you long. Shortly after the warranty expires, it will not be supported anymore, no further critical system updates, and you will be forced to buy another one.

The Apple tablets are a bit of a different story. Even with a basic model of iPad, you cannot go wrong. The device will last you, when handled properly, for years and will be supported for years as well.

Till now, iPadOS 26, the operating system on iPads, is available for devices released going back to March 2019. The experience of the latest operating system will not be marvellous, and you will be missing some recent features, but it will still work. What's important is that when the latest operating system is still supported, so are the apps in the App Store!

Buying an iPad from £329 (base model, 128GB storage) that will last you for 7-ish years is a great investment; let's not cheat ourselves.

{{% ads-in-article %}}

## Overview

You have an option, and it strictly depends on your current use of your Windows 10 device. To simplify things, you would need to ask yourself honestly what type of user you are.

 - **Novice** - users who use their computers at their basics, browsing the internet, checking emails, playing games, writing simple documents.
 - **Intermediate** - some advanced, specialised uses, but not going into the extreme of specialised software. They do stuff, design, create and generally can do stuff with their hardware wherever it's needed for it.
 - **Professional** - users to the max, know what they need, using specific software in a specific way, to achieve the goal.

> I classify myself between **B** and **C**, this is why my current main hardware is MacBook Air M4, with VMware for virtualised Windows 11 and access to Windows 11 devices through work and some Linux at hand.

**Your choice:**

### ChromeOS Flex

Turn your current, aged device into a machine with a new heart, that will allow you to work online, browse websites, write emails, documents, work with files, **without spending a dime!**

Good for: **Novice** to **Intermediate**

**Gains:** No money spent, same hardware with new life for a few years, with possible limitations.

ChromeOS Flex is ideal for the **Novice** user who focuses on basic tasks like **browsing the internet**, **writing**, and **printing**.

The use of devices strongly depends on an active internet connection for web applications, contrasting with the ability of Windows or Linux to run locally installed, specific software, offering greater offline functionality necessary for **Intermediate** or even **Professional** users.

---

### ChromeOS

With a portion of your budget, enjoy the stability of the Google infrastructure with a touch of Android in the form of a laptop. Do things that you normally do on your laptop and on your mobile with ease.

Good for: **Novice** and **Intermediate**

**Gains:** Spend within a reasonable budget with the ability to achieve more when it's needed, thanks to the Android and Linux subsystem.

### Linux

Another way to put a new life into your old device **without spending any money on it!**. If you are not afraid of tinkering, looking for answers on how to do stuff, but also, you do not strictly rely on software that is only available in a Windows environment, this is the option for you.

Good for: **Intermediate** to **Professional**

**Gains:** No money spent, same hardware with new life for a few years, with the option to extend its functionality when required, but at the risk of breaking stuff. A good learning curve for those who are not afraid to learn from their mistakes, but also are ready to try new ways of doing the same things, as some software may not always be available.

Linux is great for **Professionals** (e.g., developers, system administrators) who:

 - Value **customisation** and **open-source environments**.
 - Are prepared for **daily tinkering** and the **risk of breaking stuff**.
 - Do **not strictly rely on specific software only available in a Windows environment**.

### Windows 11

New hardware, new life, new possibilities. Do what you've been doing and explore new possibilities thanks to new technologies and solutions available.

Good for: all types of users, but aimed at **Intermediate** and **Professionals**.

**Gains:** With a reasonable budget, gaining access to the latest operating system allows you to do stuff that you're used to doing and even more.

### macOS

The computer that is always ready for you and will make sure not to let you down under stress. A learning curve for Windows users and some compromises on the availability of software may be needed.

Good for: all types of users, but aimed at **Intermediate** and **Professionals**.

**Gains:** Stability, prestige of premium look and feel. A device that will prove its value over time and help you be more focused and productive when needed.

### iPadOS

A compromise between a computer and a mobile phone, but without a lack of functionality. Ready wherever you need it most, and wherever you are. Customisable to your needs on the go.

Good for: **all types of users**.

**Gains:** long support, stability, and wide availability of software to fulfil your needs wherever it's needed to do so. With some familiarisation, additional equipment can be a successful replacement for an ordinary computer.

{{% ads-in-article %}}

## Afterword

You may think that the whole thing with Windows 10 and its end of life is a bit of a scam. It is for in some aspects, Microsoft, let's say this honestly, lied to its users at the time, stating that this would be the last Windows and all would be just upgrades to it.

But if you look at it from another perspective, Windows 10 was released on the 29th of July 2015 – that's over 10 years ago. Technology has gone massively forward since then. Releasing Windows 11 and implementing minimum hardware requirements was a point to move from old PCs, pre-AI era, into new times (at a cost).

If you look further, Windows 11 was released on 5 October 2021. At the time when Windows 10 hits end of life, this system will be on the market for over four years. I will not expect it to go further than six years before we see the next major Windows version, putting us in the same position of scrapping our old hardware and doing this all again. In the next two years, we may see another change on the horizon, or simply, Windows 11 will start raising its minimum requirements after another major version update.

Currently, a large number of computers released in 2018 and later can be updated (still, for free!) to Windows 11 at no cost. They will not be the fastest device available, but they will do their job and will be fully supported (the OS) by Microsoft if you have a problem. This is very important in a business environment when your business also relies on Microsoft services.

Forcing Windows 11 into hardware that is dead already is like reviving a corpse. They will live for a short period of time, but they will start falling apart really quickly. This is why, at the retirement of your old hardware, there are ways to cherish the remaining time in this world.

ChromeOS and Linux are a chance to put a new spirit into the old body before adding it to the landfill.

Start with ChromeOS Flex, where you will just need to prepare it by installing it on a USB drive and converting your laptop to it. If you find it, even with an enabled Linux environment, not sufficient, or too much tied to Google services, try variations of Linux systems available.

I personally operate on macOS, with ChromeOS Flex and Linux Mint devices at the reach of a hand and Windows 11 environment, either through virtualisation on macOS or at the workplace, hence I have all my options open wherever I need.

Before spending money, think and try new things. It doesn't hurt, and through the process, you will learn what type of user you are and what your real needs are. At the end, you may figure out that Windows 11 and a new computer are not really needed for the things you are doing.

## Postscriptum

If you really need to stay on a Windows 10 device for a bit longer, and you are not a business user, Microsoft will soon offer you extended support for a year, at a price.

The cost of that will be around £30, but you will still be in the same boat year after year.

Microsoft has also announced that many users can enrol for the Extended Security Updates (ESU) programme for free, provided they sync their PC settings to the cloud using a Microsoft account.

{{% ads-in-article %}}

### Extended Security Updates (ESU) for Windows 10

If you sync your PC settings to the cloud using a Microsoft account (i.e. using Windows Backup / OneDrive features), then you become eligible for the free ESU enrolment. 

To enrol in ESU, you must sign in with a Microsoft account (a local-only Windows user account will not suffice). 

The devices must already be on the latest supported version/updates to qualify – must run Windows 10 version 22H2 (with certain updates).

So the **catch** is that Microsoft is tying the free ESU to cloud-syncing (i.e. backing up settings via OneDrive or Windows Backup) and to having a Microsoft account, which helps them associate the ESU **license** or entitlement with your account rather than just the device.

ESU only provides **critical** and **important** security updates after October 2025; it does not deliver new features, general support, or **nonsecurity** updates.

Over time, you may miss bug fixes, performance improvements, but you will have some more time to search for alternatives.

The free option (and all ESU enrolment options) extends support only until October 13, 2026.

The option is being rolled out gradually — an **enrollment wizard** will appear via Windows Update/settings.

It may not show up immediately on all PCs; there may be a delay depending on your update channel or region.

Once you enrol, you can use the ESU **license** on up to 10 devices signed in with that Microsoft account (for consumer ESU).

You don’t need to pay separately per PC if within those limits.

Syncing settings means more data about your PC settings (and perhaps some system state) is backed up to Microsoft’s cloud. Some users may regard that as undesirable.

The free ESU is not just for allowing users to stay on Windows, but rather gives them a bit more time before the transition.

I would not expect this to go any further after October 2026; hence, think about, analyse what you are using your computer for and consider your options.


---
## Toilet Paper, Differently
- **URL:** https://dariusz.wieckiewicz.org/en/toilet-paper-differently/
- **Date:** 2025-09-28
- **Tags:** Toilet Paper, Who Gives a Crap, Lidl, Floralys Quilted Toilet Tissue, Quality, Price

### Content

This post differs slightly from my usual contributions on this website.

> For those who might not read to the end, here's a 15% off referral link for your first order: [whogivesacrap.mention-me.com/m/ns/xg6os-dariusz-wieckiewicz](https://whogivesacrap.mention-me.com/m/ns/xg6os-dariusz-wieckiewicz)

Recently, my wife convinced me to try a company called 'Who Gives a Crap,' which offers products like toilet paper, tissues, and kitchen towels. Their products are designed to be either 100% bamboo or 100% recycled, with the following aim:

> **"50% of profits are donated to help everyone gain access to clean water and a toilet - over £9 million raised to date!"**

I'm eager to give it a try, as long as it doesn't significantly increase our household expenses.

<!--more-->

> In the past, I considered some advertisements from Modern Milkman, but paying £4.40 for 4 pints of whole milk compared to £1.60 at Lidl didn't make economic sense. That's quite a steep difference!

Our household shopping is primarily done at Asda and Lidl, with occasional purchases from other discount brands. Since Lidl is the closest store to where we live, we often buy most of our basic items there. Overall, Lidl maintains a good balance between quality and price.

[![Lidl's Floralys Quilted Toilet Tissue](Floralys_Quilted_Toilet_Tissue.jpg)](Floralys_Quilted_Toilet_Tissue.jpg)

At Lidl, we discovered our family's favourite toilet paper, Floralys Quilted Toilet Tissue, which suits most of us well. Our usual choice is the 16-roll pack (3-ply) for just £4.99. To consider switching to a similar quality product, it would need to be priced comparably to convince us.

On Who Gives a Crap (WGaC), I considered purchasing 48 rolls of 100% Recycled Toilet Paper to save on postage and compare it with Lidl's brand, not only in terms of price but also quality. 

Let's start with the cost comparison.

## Cost comparison

When you first use Who Gives a Crap, they offer a £5 discount on your initial subscription order, and the subscription is [**very flexible**](https://support.whogivesacrap.org/hc/en-gb/articles/11932267324953-Managing-your-subscription-status).

Before diving into the cost, it's important to note that a single roll from Who Gives a Crap isn't equivalent to a Lidl roll.

Their 100% recycled paper roll boasts 400 sheets of 3-ply paper.

> Each roll of Floralys Quilted toilet paper contains 160 sheets of 3-ply paper.

[![Floralys Quilted roll (left) vs Who Gives a Crap Recycled (right)](Floralys_Quilted_vs_Who_Gives_a_Crap_Recycled.jpg "Floralys Quilted roll (left) vs Who Gives a Crap Recycled (right)")](Floralys_Quilted_vs_Who_Gives_a_Crap_Recycled.jpg)

### Lidl cost

* 16 rolls for £4.99
* Each roll has 160 sheets (3-ply).

So total sheets = 16 × 160 = **2,560 sheets.**

Cost per sheet = £4.99 ÷ 2,560 ≈ **£0.001949 per sheet** (about 0.195p).

**WGaC rolls are:**

* 48 rolls
* Each roll has 400 sheets.

Total sheets = 48 × 400 = **19,200 sheets.**

**Cost at same sheet price:**

19,200 sheets × £0.001949 ≈ **£37.40**.

That's the price we would pay for Lidl's Quilted toilet paper with the same number of sheets.

{{% ads-in-article %}}

### Who Gives a Crap cost

Spending £39 at once for toilet paper (after a £5 discount on the first subscription order) isn't appealing to everyone, especially when you can purchase it at Lidl for £4.99 each time.

WGaC at £39 is already more expensive than Lidl at £37.40. Paying the full price of £44 versus £37.40 makes sticking with Lidl an obvious choice if you're only considering price.

Quality is also crucial and must be carefully considered, but we'll address that later.

As someone who enjoys seeking additional discounts, I applied a **15% discount code** instead of the £5 off my first order, bringing my total to **£37.40** at checkout.

> **Want 15% off your first order?** Use this referral link: [whogivesacrap.mention-me.com/m/ns/xg6os-dariusz-wieckiewicz](https://whogivesacrap.mention-me.com/m/ns/xg6os-dariusz-wieckiewicz)

Without yet knowing the quality of the 100% recycled toilet paper, I've already matched the price of Lidl's premium branded paper.

Even with a **£39 starting price**, it would look like this:

* £39 for 48 rolls
* Each roll = 400 sheets
* Total sheets = 48 × 400 = **19,200 sheets.**

Cost per sheet = £39 ÷ 19,200 = **£0.00203125 per sheet** (about 0.203p).

That's **0.203p** WGaC **vs** about **0.195p** Lidl per sheet.

Let's calculate the cost: if each roll has 160 sheets and there are 16 rolls, like Lidl's.

* 16 rolls
* Each roll = 160 sheets
* Total sheets = 16 × 160 = **2,560 sheets.**

Cost = 2,560 × £0.00203125 = **£5.20** (rounded to nearest penny).

At this stage, WGaC costs just **£0.21 more than Lidl**.

---

If we were to pay **the full WGaC price of £44**, it would look like this:

* Total sheets = 48 × 400 = 19,200 sheets.
* Cost per sheet = £44 ÷ 19,200 = 0.0022916p (about 0.229p per sheet).

* Cost per sheet: ~£0.00229 (0.229p).
* Cost for a 16-roll, 160-sheet pack: **~£5.87**

In that scenario, **WGaC is £0.88 more expensive than Lidl**.

---

With a [flexible subscription](https://support.whogivesacrap.org/hc/en-gb/articles/11932267324953-Managing-your-subscription-status), you can receive your next order sooner, delay it, or cancel anytime, so you're not obligated to stick to a higher price.

The next question is: **how does the quality compare?**

{{% ads-in-article %}}

## Quality comparison

> The comparison is strictly subjective, relying on personal feelings, opinions, and experiences.

I have ordered my first subscription and initially aimed for repeated orders every 3 months.

[![Who Gives a Crap logos all over the cardboard box](Who_Gives_a_Crap.png)](Who_Gives_a_Crap.png)

The order arrived in a big cardboard box with "Who Gives a Crap" written all over it. It's a clever piece of intentional advertising that doesn’t cost much. **Well done!**

[![Each Who Gives a Crap toilet paper wrapped in colourful sleeve](WGaC_wrapped_toilet_paper.jpg)](WGaC_wrapped_toilet_paper.jpg)

Each toilet paper roll in the box is wrapped in a colourful paper sleeve. Although this feature might seem irrelevant, it adds a unique touch to the goods you've just purchased. If you have a toilet paper stand in your bathroom, this will introduce a vibrant splash of colour and style to an otherwise typically dull space.

Lids' toilet paper is packaged in an additional plastic sleeve, which, once opened, ends up in the bin and contributes to the plastic pollution that we are inundated with.

The roll is firmer, thicker, and larger than Lidl's toilet paper. When you press it down with two fingers, you can easily notice the difference. The Lidl brand squashes like a feather, whereas the WGaC brand is much harder to compress.

This is due to having 400 sheets of 3-ply paper on one roll compared to just 160 sheets.

Yet, despite its initial hardness, the paper is very soft to the touch and surprisingly strong.

[![Who Gives a Crap (left) vs Floralys Quilted (right)](Who_Gives_a_Crap_Recycled_vs_Floralys_Quilted.jpg "Who Gives a Crap (left) vs Floralys Quilted (right)")](Who_Gives_a_Crap_Recycled_vs_Floralys_Quilted.jpg)

While the Lidl brand chose a large circular pattern for their paper, which looks better overall, the WGaC paper features a small dotted design.

The paper itself, once the colourful sleeve is removed, doesn't look particularly appealing and personally reminds me of my childhood days when we collected newspapers, took them to recycling points, and received either a small amount of money or exchanged them for toilet paper. However, the quality of that paper was nowhere near that of WGaC. Back in the late '80s and early '90s, your bottom would certainly protest with each use!

Despite its external appearance, the paper is much softer in use and surprisingly strong. The pattern on the paper must be carefully chosen to achieve the optimal balance between strength, appearance, and softness.

When comparing 400 sheets to 160 sheets per roll, you might not immediately notice the difference. However, it becomes apparent how quickly the Lidl rolls disappear compared to those offered by Who Gives a Crap.

While the comparison is quite subjective, you'll quickly notice from initial use that two sheets are often sufficient, whereas with other brands, you might risk a mess and end up using more sheets to achieve the same result.

I mentioned the stand for toilet paper earlier. If your toilet area is integrated into the same room as your shower or bath, having paper packed individually offers another advantage.

Despite the external sleeve on the paper, it's easy to fit onto a pole or storage rod. This adds practicality by better protecting the paper against water splashes and the moisture that's always present in a bathroom.

Wet toilet paper, even slightly damp, loses its softness and strength. It doesn't look good from a hygiene perspective either. Here, having them individually packed makes more sense, especially since wetting a roll is like losing 2.5 rolls of Lidl-branded paper.

With 400 sheets compared to 160 sheets, that's exactly 2.5 rolls in one!

{{% ads-in-article %}}

## Conclusion

Take your time to decide whether to stick with the subscription or return to purchasing from Lidl. Weighing the pros and cons of each option will help you make the best choice for your needs.

Both papers feel comparable, although Who Gives a Crap is slightly stronger. Ultimately, the decision depends on how quickly your household goes through the 48 rolls (which might last more than the initially set three months) and what deal you get on the next delivery.

The jump from £37.40 to £44.00 needs justification. While the price increase isn't massive, evaluating how effectively this paper lasts compared to the other one is crucial. If it lasts much longer than expected and requires fewer sheets per use, the invisible savings could compensate for the slightly higher price tag.

The great news for anyone wanting to give it a try is that with the referral code, you can get 15% off your first subscription. This makes it cost about the same as buying Lidl Floralys Quilted Toilet Tissue, so it's a great opportunity to test it out without spending extra.

At £37.40 for 48 rolls with 400 sheets per roll (totalling 19,200 sheets), it's equivalent to buying 120 rolls of Lidl-branded toilet paper, which is priced at £4.99 for 16 rolls. This comparison highlights the value you get in terms of sheet count for the price.

> With 15% off your first subscription order, it's an appealing option to try and compare to your usual choices: [whogivesacrap.mention-me.com/m/ns/xg6os-dariusz-wieckiewicz](https://whogivesacrap.mention-me.com/m/ns/xg6os-dariusz-wieckiewicz)

You may not save money, but you'll definitely save storage space.


---
## How to Backup Your OpenWrt Router When Built-in Tools Fail
- **URL:** https://dariusz.wieckiewicz.org/en/how-to-backup-your-openwrt-router/
- **Date:** 2025-09-03
- **Tags:** OpenWrt, Backup, sysupgrade, tar, SFTP

### Content

In the past, I have followed [a method of updating OpenWrt devices with an option to restore all installed packages and their configurations][] without needing to spend hours on reconfiguring and testing everything.

[a method of updating OpenWrt devices with an option to restore all installed packages and their configurations]: /en/firmware-update-openwrt/

This method uses a simple script run in the terminal to generate a list of installed packages, followed by a web interface to generate a backup file used to restore everything.

**As long as the backup file is generated correctly, the restoration process works well, but the problem arises when it isn't!**

On several routers with OpenWrt (24.10.x) that I worked with over recent weeks, I experienced a strange issue that caused me to rethink how I generate a backup file to later use to restore all packages and settings after updating OpenWrt to the latest version.

I discovered this issue the hard way when I wanted to extract a backup to retrieve some configuration from individual files. I noticed that the backup failed to extract correctly.

> This was fixed in OpenWrt 25.12; however, I have left it for reference. If you are upgrading from 24.10 to 25.12 and your backup is generated incorrectly, you will not be able to upgrade to 25.12 while retaining packages using [Attended Sysupgrade](/en/attended-sysupgrade-openwrt/).

<!--more-->

## Generating (backup) archive – LuCI

Typically, when you generate a backup file of your configuration, you navigate to:
- **System > Backup / Flash Firmware**

From there, you simply need to click **Generate archive** to obtain your backup.

If you want to include an additional folder in your archive, click the **Configuration** tab, where you can specify an additional location to be included, with each entry on a separate line.

My current content looks as follows:

```
## This file contains files and directories that should
## be preserved during an upgrade.

# /etc/example.conf
# /etc/openvpn/
/etc/ssl/
/etc/cloudflared/
/etc/sysctl.d/
/etc/init.d/
/etc/config/
/root/
```

This can be found in the `/etc/sysupgrade.conf` file.

{{% ads-in-article %}}

> Modified files in /etc/config/ and certain other configurations are automatically preserved by OpenWrt, so you don't need to explicitly include this folder.

I have tested numerous variations of generating a backup file, with and without some additional folders mentioned above. Each time, at some stage, the backup becomes corrupted.

The main problem is that this issue is **unrepeatable** (unable to reproduce using the same steps).

You can document all the steps you took until you encountered the issue, perform a factory reset on your router, and repeat them, yet you might not face the issue again—or you might encounter it much earlier.

The cause remains **unknown**.

## Corrupted (backup) archive - LuCI

Returning to the generated archive of your backup.

Typically, after pressing the **Generate archive** button, your browser will automatically download the file:
- `backup-OpenWrt-2025-09-01.tar.gz`

After extracting this file using any available tool (such as 7Zip on Windows or Keka on macOS), you should see a folder containing `/etc` and `/root`.

Each of these folders will include plain text files that you can view with any software to access the settings.

The problem arises when you try to extract the file and end up with a single TAR file instead of folders and files. Further extraction attempts from this TAR file result in an error.

```
tar: Error opening archive: Unrecognised archive format
```

When I run `file backup-OpenWrt-2025-09-01.tar.gz`, the system recognizes it as a valid archive:

```
backup-OpenWrt-2025-09-01.tar.gz: gzip compressed data, from Unix, original size modulo 2^32 895035
```

Some people suggested that the web browser or operating system used might be the cause. I have tried on different computers and browsers, with the same results.

> Interestingly, you can open this TAR file in VS Code using Text Preview, where you can see the content of each file amidst a lot of garbage. So, in the worst-case scenario, you can retrieve what you need from there. It seems that the files and folder structure are corrupted upon extraction.

## Generating (backup) archive – terminal

I attempted to generate a backup directly on the router to eliminate any impact from an internet browser or operating system.

I followed the suggested method:

```bash
# Generate backup
umask go=
sysupgrade -b /tmp/backup-${HOSTNAME}-$(date +%F).tar.gz
ls /tmp/backup-*.tar.gz
```

## Corrupted (backup) archive - terminal

Once the file was generated, I attempted to unpack it in the `/tmp` folder on the router:

```bash
tar -zxvf backup-OpenWrt-2025-09-01.tar.gz
```

and got

```
tar: invalid tar magic
```

Since some OpenWrt installations don't include the latest or full version of the TAR command, I installed it:

```bash
opkg update
opkg install tar
```

> From OpenWrt 25.12, using `apk` instead `opkg`

```bash
apk update
apk add tar
```

Repeating my extraction command `tar -zxvf`, I get:

```
tar: This does not look like a tar archive
tar: Skipping to next header
tar: Exiting with failure status due to previous errors
```

## Analysing corruption with AI

Running out of options and unable to pinpoint a specific package causing the issue, I used AI to analyse the extracted TAR file to see its suggestions:

> Based on your provided summary and excerpt, the tar file (**backup-OpenWrt-2025-08-20.tar**) contains mostly valid OpenWrt config and init files, but there are signs of corruption:
>
> - **Binary junk and misplaced null bytes:** Many files have trailing or embedded null bytes (\x00) and binary junk, which is not normal for text config files.
> - **File boundaries and padding:** Some files appear to have excessive padding or are not properly terminated, which can confuse tar extraction tools.
> - **File size mismatches:** The tar headers specify file sizes, but the actual content may not match, causing extraction errors.
>
> **Most likely cause of extraction failure:**
>
> - The corruption is probably due to improper file boundaries, excessive null padding, or truncated files, especially in binary files like .tdb or key files.
> - If you see errors like Unexpected EOF or tar: Skipping to next header, it's usually because the tar stream is interrupted or a file's declared size does not match its actual content.

## Alternative way of generating (backup) archive

While searching the OpenWrt forum and other sites, I came across various methods for generating a backup directly from the router.

```bash
sysupgrade -l | tar -czf backup.tar.gz -T -
```

Based on that, I built my file, which generates a valid archive with my backup files that can be extracted correctly, despite the official method of generating a backup (over a web browser or through the official command in the terminal) returning a corrupted file.

I created a `gen_backup` file in my `/root` folder and added execution rights with `chmod +x gen_backup`. The file contained:

```bash
# Generate backup
umask go=
sysupgrade -l -v | tar -czf /tmp/backup-${HOSTNAME}-$(date +%F).tar.gz -T -
ls /tmp/backup-*.tar.gz
```

Once the command runs correctly, I am presented with my backup file `backup-OpenWrt-2025-09-01.tar.gz` in my `/tmp` folder.

Now, I need to retrieve this file and save it locally.

{{% ads-in-article %}}

## Copying generated (backup) archive - SFTP

To copy the file from the router, I need to [install FTP server][].

[install FTP server]: /en/firmware-update-openwrt/#uploading-files-via-sftp

```bash
opkg update
opkg install openssh-sftp-server
```

> From OpenWrt 25.12, using `apk` instead `opkg`

```bash
apk update
apk add openssh-sftp-server
```

Now, with the preferred FTP client (I am using CyberDuck on macOS), I need to initiate an SFTP connection (on your SSH port, default 22), logging in using root credentials.

By heading to the `/tmp` folder, you can easily drag the file to your computer.

Locally, double-clicking on the downloaded file will extract it in the way it should have been originally, presenting you with folders containing config files.

If your file extracts correctly in such a manner, [restoring your settings with the installed packages, as described][], will work correctly.

[restoring your settings with the installed packages, as described]: /en/firmware-update-openwrt/

Even if you change the device, and thus cannot restore using the described method, by extracting it locally and examining each config file, you can swiftly prepare your new device to function as it did on the old one.

---

The issue is very intriguing and is a head-scratcher for me.

I am trying to engage on [OpenWrt Forum post #235434][] to get this issue resolved; however, so far, nothing suggests the root cause and a possible long-term solution. If you cannot replicate the issue, it's difficult to find the cause.

[OpenWrt Forum post #235434]: https://forum.openwrt.org/t/extracting-unpack-backup-file-in-openwrt-24-10-series/235434

In the meantime, I've got a working backup solution that I need to stick with.

Regards.


---
## Setting hreflang and x-default on a multilingual site (with Hugo) - part 2
- **URL:** https://dariusz.wieckiewicz.org/en/setting-hreflang-and-x-default-on-multilingual-site-part-2/
- **Date:** 2025-07-19
- **Tags:** Google, hreflang, international SEO, multilingual SEO, language targeting, hreflang attributes, hreflang links, hreflang annotations, hreflang validation, hreflang use cases, x-default, default language, fallback language, multilingual sites, WebDev, Hugo

### Content

Back in 2023, I have looked at how to add relevant hreflang tags to my personal website, which considered adding self-reference to the current language, reference to a translated page (if available), and falling back with x-default to a page that is designed as a language switcher page.

Since then, I thought that this approach was correct, but found out that this solution, on my website, where not all content is 100% translated, is not good for sites fully translated by default.

Here is how I learned from it and how I optimised hreflang and x-default on websites built with Hugo.

<!--more-->

---

I recently made "**yet another Hugo**" website. My friend, who is a highly skilled auditor in multiple standards, needs to have a website to advertise what she can offer to potential new customers.

She is from Poland, lives in Sweden, working for a British body of the company, and offering her services to the whole world.

The website needs to be in English by default, to have a global reach; however, it needs to be available in her home language (Polish) as well as in the place of her main residence (Swedish).

With such an approach, the website [emiliawardach.com](https://emiliawardach.com) comes to life.

As always, after finishing the website, the work is not done. There are always some small fixes and TLCs. When I started running it through various validators and tools like [ahrefs.com](https://ahrefs.com), to my surprise, I was faced with excessive issues reported as **Missing reciprocal hreflang (no return-tag)**.

> I also looked at my other friend's website, [yummyrecipes.uk](https://yummyrecipes.uk), that was fully translated some time ago and found similar issues.

I thought that I implemented things correctly as per my previous post [Setting hreflang and x-default on a multilingual site (with Hugo)](/en/setting-hreflang-and-x-default-on-multilingual-site/).

Once I started to re-read what I wrote, I found some mistakes that resulted in this approach.

---

Firstly, the start of the website in Hugo contained the following:

```html
<!DOCTYPE html>
<html lang="{{ .Language.Locale }}" xml:lang="{{ .Language.Locale }}">
```

This generates the following code for the English part.

```html
<!DOCTYPE html>
<html lang="en-GB" xml:lang="en-GB">
```

As you will notice, I am not only targeting English visitors, but I am going more specifically and reflecting that the site is in British English, which is more than correct.

The problem was the initial implementation.

```html
<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}">
{{ range .Translations }}
<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}">
{{ end }}
```

> I will exclude `x-default` from this for now, as I will come back to that later.
> 
> Also, I moved from using the relative link `{{ .RelPermalink }}` and stuck with the full link to the site using `{{ .Permalink }}`.

The above code will generate something like this:

```html
<link rel="alternate" hreflang="en" href="https://emiliawardach.com/">
<link rel="alternate" hreflang="pl" href="https://emiliawardach.com/pl/">
<link rel="alternate" hreflang="sv" href="https://emiliawardach.com/sv/">
```

The first mismatch was here.

As I am specifying the language using `{{ .Language.Locale }}` in the `<html>` tag, the English site will return `en-GB`, Polish will have `pl-PL`, and Swedish will have `sv-SE`.

As I am specifying document languages in the `<html>` tag more specifically, indicating that the English is not just English but British English, I should follow this in any `hreflang` references that I am using on the website.

The `{{ .Lang }}` will only return two characters of the language; for English, it will be just `en`, and this is a mismatch to what I am advising in the first place.

---

To clarify, the `locale` I have specified in `hugo.conf` is as follows for the English part:

```toml
  [languages.en]
    locale = "en-GB"
```

---

Of course, I can change `local` to be more universal (just `en`), but I prefer to stick to the correct way to accurately reflect British English rather than generic English.

In that case, I need to amend my code with `.Language.Locale` instead of just `.Lang` as follows:

```html
<link rel="alternate" hreflang="{{ .Language.Locale }}" href="{{ .Permalink }}">
{{ range .Translations }}
<link rel="alternate" hreflang="{{ .Language.Locale }}" href="{{ .Permalink }}">
{{ end }}
```

Notice that I am reporting the first `link rel="alternate"` as a self-reference to the site that I am currently on in the selected language.

The second, within `{{ range .Translations }}`, will return all other languages available for the selected page (`/about/`), as shown below:

```html
<link rel="alternate" hreflang="en-GB" href="https://emiliawardach.com/about/">
<link rel="alternate" hreflang="pl-PL" href="https://emiliawardach.com/pl/o-mnie/">
<link rel="alternate" hreflang="sv-SE" href="https://emiliawardach.com/sv/om/">
```

The `hreflang` will match the language specified at the document level in the `<html>` tag. It will self-reference the currently visited page `/about` in British English and list other available links to translated pages.

First issue fixed.

Now, we need to rethink the use of `x-default`.

In my [previous post](/en/setting-hreflang-and-x-default-on-multilingual-site/), I referenced a specially designed page where users can decide on selecting the language:

```html
<link rel="alternate" href="{{ .Site.Params.langSelector | absURL }}" hreflang="x-default">
```

This will look as follows on my site:

```html
<link rel="alternate" href="https://dariusz.wieckiewicz.org/en/language-selector/" hreflang="x-default">
```

This is not a perfect solution, but on my site, where not everything is (nor must be) translated, it's a sort of compromise.

The `x-default` should always work as a fallback.

Remember that I have specified languages as specific. English is not just English; it's British English.

If a person whose language set on their device is English but they come from Liberia, it will be reported as `en-LR`.

This will, of course, not match with `pl-PL` and `sv-SE`, but it will also not match with `en-GB`.

In that case, we need to provide a default fallback.

As English is much more universal than Polish or Swedish, if the person lands, through a search engine or direct link, on `/pl/o-mnie/`, which doesn't match their main language, the `x-default` should suggest that they view another language as their default page.

In that case, the default language will be English in the form of British English.

While on `/pl/o-mnie`, the `x-default` should report as follows:

```html
<link rel="alternate" href="https://emiliawardach.com/about/" hreflang="x-default">
```

In Hugo, we can achieve this in various ways, as reported by [Joe Mooring](https://discourse.gohugo.io/u/jmooring/summary) on the Hugo Support forum, in response to the question [How to get a specific translation?](https://discourse.gohugo.io/t/how-to-get-a-specific-translation/32433/5).

I liked the option provided with the `index` function, and for my purpose, I added the following into my code:

```html
{{ $p := index (where .AllTranslations "Language.Lang" "en") 0 }}
<link rel="alternate" href="{{ $p.Permalink }}" hreflang="x-default">
```

This code will list all translations (`.AllTranslations`) but limit the output to a single selected language, which in this case is English `en`.

{{% ads-in-article %}}

The full code will look like this:

```html
<link rel="alternate" hreflang="{{ .Language.Locale }}" href="{{ .Permalink }}">
{{ range .Translations -}}
<link rel="alternate" hreflang="{{ .Language.Locale }}" href="{{ .Permalink }}">
{{ end -}}
{{ $p := index (where .AllTranslations "Language.Lang" "en") 0 }}
<link rel="alternate" href="{{ $p.Permalink }}" hreflang="x-default">
```

This approach will use `x-default` for its intended purpose. It will ensure consistency across content (pages) and follow what is known as common practice.

> "It's common practice for the primary or most generic language version (often English) to serve as the x-default."

For my Polish page `/pl/o-mnie/`, the output will look as follows:

```html
<link rel="alternate" hreflang="en-GB" href="https://emiliawardach.com/about/">
<link rel="alternate" hreflang="pl-PL" href="https://emiliawardach.com/pl/o-mnie/">
<link rel="alternate" hreflang="sv-SE" href="https://emiliawardach.com/sv/om/">

<link rel="alternate" href="https://emiliawardach.com/about/" hreflang="x-default">
```

This resolves the issue with **Missing reciprocal hreflang (no return-tag)** once and for all.

Regards.


---
## Toob 900Mbps Full Fibre on my router – Linksys MX4200
- **URL:** https://dariusz.wieckiewicz.org/en/toob-900mbps-full-fibre-on-linksys-mx4200/
- **Date:** 2025-06-29
- **Tags:** OpenWrt, router, Linksys, Linksys MX4200, Linksys MX4200v2, TP-Link RE700X, Linksys SPNMX56TB, Bufferbloat, Toob, Full Fibre, CityFibre

### Content

The day has come when my [£25pm Toob Fibre 900/900Mbps](https://rewards.toob.co.uk/dariuszw-120n), via CityFibre infrastructure, was finally installed.

After all the wiring was done, the new Toob router was connected, and I started testing.

To my surprise, Toob switched to a different Linksys Velop model than I initially expected. I have been supplied with Linksys SPNMX56 ([**SPNMX56TB**](https://support.linksys.com/kb/article/926-en/) to be exact), which, by default, comes with a 2.5 Gbps WAN port.

From my previous post, where I chose [£40 Linksys MX4200 as my next router](/en/linksys-mx4200-a-40-openwrt-powerhouse/), I did an analysis of my needs, and I concluded that I am fine with a 1Gbps WAN port. Toob's approach to go with 2.5Gbit is more future-proof thinking. If they want to offer higher plans, they will not need to replace hardware. For my needs and 900Mbps connection, the 1Gbps (1000Mbps) port is more value for money.

Going back to the initial Toob setup.

Their device is equipped with the following:

**Processor:** Quad‑core CPU running at 1 GHz\
**Flash memory:** 128MB (not officially disclosed)\
**RAM:** 256 or 512MB (not officially disclosed)\
**WAN:** 1 × 2.5 Gbps WAN port\
**LAN:** 3 × 1 Gbps Ethernet ports\
No USB ports\
**Dimensions:** Size: 3.385× 3.385× 7.3 in (86 × 86 × 185 mm) 

I knew that I would not be using their router, hence quickly, after the installers finished and the service went live, I hooked up an Ethernet cable from the CityFibre box into my (currently used with VirginMedia) Askey RT4230W REV6 (RAC2V1K) WAN port and the network started working like it was before.

> I have used [Toob One Touch Switch service](https://www.toob.co.uk/home-broadband/one-touch-switch/) to move away from Virgin Media. Straight after my Toob fibre went live, I received an email from Toob stating that it's live, and my Virgin router stopped providing internet.

To my surprise, there was no configuration needed; all was resolved by the CityFibre box, which provided, over DHCP, all that's needed. There was no need to contact Toob Customer Service to get this done (they are officially advising on their website that you can use your own router, but you need to speak with them first), not even the need to clone the MAC:ID of the Toob router to the new one to get service. That's great!

I hooked up quickly the Linksys MX4200v2, which I will be using as my new device, to see that this one also worked just after plugging in an Ethernet cable going from the CityFibre box to the WAN port on the router. I didn't even need to reboot the CityFibre box. Super!

---

Toob is provided by default, over CityFibre service, IPv6 along with IPv4. However, you are placed behind [Toob CG-NAT](https://www.toob.co.uk/blog/ipv4-ipv6-and-cgnat-explained/), so you will not be provided with a public IP.

> If you take the Toob 18-month product, you can buy a static IPv4 address, which isn’t part of CG-NAT.

It is great to be able to finally reach the internet over IPv6 without the need to use tunnels!

Because of the lack of an external IPv4 address, I need to forget about using [WireGuard](/en/installing-vpn-server-on-router-openwrt-wireguard/) to connect to my network over VPN, but I can still do this using an alternative approach with [CloudFlare Zero Trust, VPN alternative](/en/adding-cloudflare-tunnel-to-openwrt-router/). 

This, and other things, I will be testing intensively over the following days.

I quickly noticed that the maximum download speeds, connecting through Wi-Fi provided by the Access Point set with TP-Link RE700x, were in the range of 500Mbps on download and slightly over 600Mbps on upload. I started thinking, is it because of this one difference that it is a 2.5Gbit WAN?

I hooked up to the router over an Ethernet cable. I could reach the maximum without a problem; hence, that's not the issue.

I connected the Toob router to do some measurements, and over Ethernet and Wi-Fi provided through the router itself, I could reach maximum speeds as advertised.

---

After further investigation, I connected back to the router and checked, once again, speeds over Wi-Fi.

I noticed that Wi-Fi on it was working at 160MHz on 5GHz, which will produce a maximum speed of 2400Mbps.

---

I am using a handy app called [WiFi Signal: Strength Analyzer](https://apps.apple.com/gb/app/wifi-signal-strength-analyzer/id525912054) to show statistics for nerds like me.

---

Checked speeds on the speedtest website and managed to get what was advertised, 900/900, easily.

[![SpeedTest 17906497141](SpeedTest_17906497141.png)](SpeedTest_17906497141.png)

Leaving the Toob router plugged in, I hooked up MX4200v2 to the LAN port and my laptop also over the LAN port to it (MX4200v2) to see if I can get full speeds even when I put **router behind the router**.

The answer was **Yes!**

The MX4200v2 produced, over the LAN port, maximum speeds, the same as when connected to the LAN port directly with the Toob router.

[![SpeedTest 17906659518](SpeedTest_17906659518.png)](SpeedTest_17906659518.png)

That's great!

----

Then I noticed that over my WiFi with TP-Link RE700X **I got a problem**.

Despite it working as an Access Point and being hacked by a Cat.6 Ethernet cable directly to the router, the WiFi speeds on 5GHz are limited to 80MHz, and the true speeds that I can get are around 500Mbps download and a bit more on upload.

**The RE700X is advertised as supporting 160MHz but why is it not working?**

I headed to the RE700X configuration panel to change – force 160MHz for the 5GHz network, in settings, as this was not possible through the Tether app.

[![TP-Link RE700X with 160MHz on 5GHz](TP-Link_RE700X_160MHz.png)](TP-Link_RE700X_160MHz.png)

Finally, that pushed speeds a bit more.

[![WiFi Signal on macOS and RE700X after enabling 160MHz](WiFi_Signal_RE700X.png)](WiFi_Signal_RE700X.png)

And the speed tests improved as well.

[![SpeedTest 17906814172](SpeedTest_17906814172.png)](SpeedTest_17906814172.png)

Considering that I already have multiple other devices connected over 5GHz and using this frequency, the results are acceptable. It's a shame that 160MHz is not enabled by default.

---

It was time to remove the Toob router from the equation and hook up the MX4200v2 directly again and repeat some testing.

Now, using the Linksys MX4200v2 directly with a Fibre connection, I get what I want, 900Mbps on download and 900Mbps on upload, **both reached!**

---

{{% ads-in-article %}}

## Linksys MX4200v2 – Tweaks

Earlier on my website, when I was using Linksys MR8300, [I wrote down how to enable the usage of all CPUs for packet steering](/en/optimising-cpu-usage-on-openwrt-router/) on a router that had more than two processor cores.

The MX4200v2 is another router where this would benefit, but there are a few changes in the recent OpenWRT 24.10 series, which make these things easier and available over a web browser.

If you go to **Network** > **Interfaces**, in the **Global network options** tab, there is an option, enabled by default, for **Packet Steering**.

However, there is an additional option there that can be changed, so let's do this, let's set this to **Enabled (all CPUs)**.

I also changed **Steering flows (RPS)** from **Standard: none** to **Suggested: 128**.

[![OpenWrt Packet Steering and Steering flows RPS](OpenWrt_Packet_Steering_flows_RPS.png)](OpenWrt_Packet_Steering_flows_RPS.png)

But that's not all.

I headed to **Network** > **Firewall** and in the section **Routing/NAT Offloading** I set **Flow offloading type** to **Hardware flow offloading**, as this device (MX4200v2) has some extra features behind the scenes, and if the option is available there, it's worth trying, instead of just relying on **Software flow offloading**.

[![OpenWrt Routing NAT Offloading Hardware flow offloading](OpenWrt_Routing_NAT_Offloading.png)](OpenWrt_Routing_NAT_Offloading.png)

---

{{% ads-in-article %}}

## Bufferbloat test

It's time for wider tests, as requested in comments on my other post.

With just a few tweaks applied, which I think are a must, I followed up with [Bufferbloat and Internet Speed Test](https://www.waveform.com/tools/bufferbloat).

I did that by hooking myself up with an Ethernet cable directly to the Linksys MX4200v2 router using an ANKER 1Gbps Network adapter with my Mac. The test was done when other household members were not using the connection, or using it in a very minimal capacity. The test was run in Google Chrome Canary and Incognito window.

The speeds have been fluctuating a bit, but overall all peak speeds were achieved and the result was A.

[![Bufferbloat Result](Bufferbloat_Result.png)](Bufferbloat_Result.png)

The results were good, so I don't even need to bother with looking, what I described in my post [Optimising the Internet connection on a router with OpenWrt](/en/optimising-internet-connection-router-openwrt/), but I may pick this up later when needed.

---

My connection is sorted for now.

I definitely will be looking forward to some inexpensive OpenWrt router, that is much more powerful than Linksys MX4200v2, but for now, for a £40 router, I cannot complain.

My next investment will be the replacement of TP-Link RE700X with something that can offer WiFi 7. Currently, the only decent device that is compact enough yet powerful is [RE655BE (BE11000 Tri-Band Wi-Fi 7 Range Extender)](https://www.tp-link.com/uk/home-networking/range-extender/re655be/), but somehow it's not yet available in Europe/UK, hence I need to keep looking or wait.


---
## Linksys MX4200: A £40 OpenWrt Powerhouse
- **URL:** https://dariusz.wieckiewicz.org/en/linksys-mx4200-a-40-openwrt-powerhouse/
- **Date:** 2025-06-10
- **Tags:** OpenWrt, router, Linksys, Linksys MX4200, Linksys MX4300, Linksys SPNMX42, Linksys AX4200, Linksys Velop, Askey RT4230W REV6, RAC2V1K, GL.iNet, Brume 2, GL-MT2500, Qualcomm IPQ8174, MediaTek MT7981B

### Content

In my previous post, [In search of the perfect OpenWrt router](/en/in-search-of-the-perfect-openwrt-router/), I discussed my potential future router. When I started researching it more thoroughly, I **paused** purchasing the Brume 2 and tried to think of what would be better.

I looked into the Brume 2 when I began researching a potential change of broadband provider from Virgin Media to a full (synchronous) fibre connection (CityFibre).

With the provider (reseller) that I am currently considering ([Toob](https://rewards.toob.co.uk/dariuszw-120n)), a 900/900Mbps connection offered the best value for money (£25 per month with no price **increases** over the whole contract period). However, to achieve that speed, they need to provide me with the right hardware.

I've noticed that most resellers of CityFibre services utilise Linksys devices, particularly the [MX4200](https://openwrt.org/toh/linksys/mx4200_v1_and_v2) in its second version (v2). This model is sometimes branded as the Linksys Velop MX4200 (AX4200) or ISP-branded as the Linksys SPNMX42, which is simply a v2 in disguise. However, Linksys has already discontinued this device.

<!--more-->

> There is a problem identifying which MX4200 is version 1 and which is version 2. The v2 is the only one I'm considering, due to its 1GB of RAM, instead of 512MB in v1. The easiest way to identify v1 from v2 is by looking at the dimensions of the devices themselves. If your device is around 24.3cm (9.57 inches) high and 11cm (4.45 inches) wide, it's a **v2** (**buy**). If it is 18.5cm (7.3 inches) high and 7.9cm (3.1 inches) wide, it's a **v1** (**don't buy**).

The Brume 2 initially appealed to me with its 2.5 Gbit WAN port, 1GB of DDR4 RAM, 8GB of eMMC storage, and a USB 3.0 port. The downside, however, was a limited number of LAN ports, which would require me to purchase a network switch to connect all my devices correctly.

The Linksys MX4200, despite having four Gigabit ports (one WAN and three LAN), also features a quad-core processor (1.4GHz). Compared to the dual-core 1.3GHz processor on the Brume 2, this offers a better starting point for handling such demanding internet connection speeds.

I've also been concerned about the small dimensions of the Brume 2 device itself and its enclosure, which I believe won't provide sufficient heat exchange for proper cooling. I've read through some online discussions where people mentioned that this device tends to get hot, and when it does, performance, especially network traffic, drops.

This made me ponder. I also started asking myself: do I actually need a 2.5 Gbit port? None of the devices from other resellers that provide connections near 1 Gbps utilise a 2.5 Gbit WAN port, as they don't see the benefit of it, arguing it only generates additional manufacturing costs.

I've indulged myself in digging out information regarding whether a Gigabit WAN port is sufficient for a 900/900Mbps connection, and all evidence points to yes.

---

* **Gigabit Ethernet Throughput:** A Gigabit Ethernet port has a theoretical maximum speed of 1000 Mbps.
* **Overheads:** Network protocols have some overhead (data used for managing the connection, error checking, etc.). This means you'll never quite achieve the full 1000 Mbps for actual data transfer.
* **Real-World Speeds:** For a 900/900 Mbps connection, a Gigabit WAN port is typically sufficient to deliver close to those advertised speeds. You might see variations (e.g., in the 850-950 Mbps range) due to these overheads and other factors like your computer's capabilities, the server you're connecting to, and general network congestion. This is normal.

**A 2.5 Gbit WAN port would offer more headroom** and could potentially allow you to consistently achieve speeds slightly above 900 Mbps if your service delivers that. However, for a service advertised as 900/900 Mbps, a Gigabit port is well-matched and shouldn't be a bottleneck preventing you from getting the speeds you're paying for.

Essentially, while 900 Mbps is close to the practical limit of a 1000 Mbps Gigabit port, it's still well within its capability to deliver those speeds effectively. Internet Service Providers (ISPs) supply routers with Gigabit WAN ports for these plans because they are adequate.

---

Considering all the above from my research, I've abandoned the idea that my next router "needs" to have a 2.5 Gbit port (at least for now).

I did some further research into processors, especially comparing the **Qualcomm IPQ8174**, used in the MX4200, and the **MediaTek MT7981B (Filogic 820)**, used in the Brume 2. I've concluded that the Qualcomm will perform well, and the design of its device will be much better at maintaining performance under stress (heat).

---

When comparing the **Qualcomm IPQ8174** and the **MediaTek MT7981B** for use in a router handling a 900/900 Mbps internet connection, I delved into the specifications of both processors.

Each of these processors utilises its own solution to improve traffic, thanks to hardware offloading capabilities. The main differences will become apparent in CPU-intensive tasks beyond simple NAT and forwarding, and in their general CPU headroom.

The **Qualcomm IPQ8174 offers** a Qualcomm Packet Processing Engine (PPE), a security engine, and other network acceleration features.

The **MediaTek MT7981B (Filogic 820) offers** MediaTek HNAT (Hardware Network Address Translation), HQoS (Hardware Quality of Service), an NPU (Network Processing Unit), and MediaTek FastPath™.

Both chips rely heavily on their respective hardware engines to accelerate packet forwarding and NAT. This means the main CPU cores are largely bypassed for these routine tasks, allowing for high speeds with low CPU utilisation.

* The **MT7981B** is explicitly designed for multi-gigabit routing (often found in devices with 2.5GbE ports), and its HNAT/NPU is very effective.
* The **IPQ8174**, as part of Qualcomm's "Networking Pro" family lineage, also has robust packet processing engines capable of gigabit-plus speeds.

> However, remember that not all options for hardware implementations are, or will be, implemented into OpenWrt.

At 900/900 Mbps with offloading active, CPU utilisation on the main cores should be relatively low for both. This is crucial as it leaves CPU resources available for other tasks the router might be performing.

Both are suitable, and you should achieve your full connection speed for typical internet use, assuming well-optimised firmware is used. For that purpose, I will be using pure OpenWrt, rather than the firmware provided with the devices by manufacturers.

If you look at the **Raw CPU Power**, the Qualcomm IPQ8174 has a clear advantage with its quad-core A53 configuration at 1.4 GHz compared to the MT7981B's dual-core A53 at 1.3 GHz. This equates to approximately double the general-purpose multi-core CPU processing capability.

I am planning to maintain my VPN (either [WireGuard](/en/installing-vpn-server-on-router-openwrt-wireguard/) or through [Cloudflare Zero Trust](/en/adding-cloudflare-tunnel-to-openwrt-router/)). Hence, the number of cores (CPU overhead) will hugely impact the speeds that can be achieved through the tunnel.

The IPQ8174's extra cores and slightly higher clock speed will provide significantly better performance. Encrypting and decrypting VPN traffic is CPU-intensive and often cannot be fully offloaded in the same way as basic NAT.

Overall, the IPQ8174 would handle more demanding shaping tasks with less performance impact.

My router also has other services added, so I will need to consider a better processor if I want to adopt a future-proof approach. The extra CPU power of the IPQ8174 provides more headroom for future firmware updates that might introduce new features, or if my usage pattern becomes more hardware-demanding.

Both processors are based on ARM64 architecture (ARMv8), backwards compatible to run 32-bit software where needed.

Given the CPU-intensive services I plan to run, the decision to go with the MX4200 is the stronger choice.

> Personally, I would prefer to go with the [MX4300](https://openwrt.org/toh/linksys/mx4300), due to its doubled storage and RAM; however, I'm struggling to find it available in the UK marketplace, and importing from the US is impossible due to very high shipping costs.

Also, the Linksys MX4200, due to its wide availability on eBay (as branded through different providers), will allow me to acquire it for around **£40** as a starting point, which is another benefit over the Brume 2.

> I personally suggest buying the non-branded Linksys Velop MX4200, which can be purchased starting from £40 at [CeX](https://uk.webuy.com/search?stext=mx4200). If you opt for branded ones, be careful, as most of them are not easy to unlock and install clean OpenWrt. The one that is somewhat manageable is from [Community Fibre](https://github.com/ishi0/Community-Fibre-WHW03CFv2/wiki), though it may not always be straightforward.

The Brume 2 does not have any Wi-Fi capabilities, which I don't mind as I utilise an external Access Point for that. However, for other people, having an all-in-one solution like the Linksys MX4200 will be a no-brainer.

---

**Reminder:** If you decide to go with the MX4200, always make sure to purchase the second version (v2). Ask the seller and compare the dimensions between v1 and v2 to avoid disappointment later. Many v2 devices do not even state this on the label. Mine, however, arrived with 'V2' clearly stated after the model number on the bottom label. The dimensions, however, will tell you a bit more.

[![Linksys MX4200 with clearely marked V2 on a label](Linksys_MX4200_V2_label.jpg)](Linksys_MX4200_V2_label.jpg)

{{% ads-in-article %}}

**The Downgrade**

Linksys devices are a bit different from other brands due to their dual flash capability. Effectively, the device has two partitions for firmware. This is important during the initial flash of `squashfs-factory.bin`. Once you've installed your initial firmware and successfully run the device from OpenWrt, you need to remember to follow additional steps and repeat the flashing with `squashfs-factory.bin` on the second flash partition. If you do not do this, your router will not run after the next OpenWrt firmware upgrade, which is performed using a round-robin logic, and subsequent reboot. You will then need to perform a power cycle method to manually switch to the partition on which OpenWrt was initially run.

For that purpose, it's important to follow the [**Flash OpenWrt to Alternate Partition**](https://openwrt.org/toh/linksys/mx4200_v1_and_v2#flash_openwrt_to_alternate_partition) step. This involves checking which partition OpenWrt is currently running from, sending `squashfs-factory.bin` to the router using the SCP protocol (or `wget` if you have internet access on the device), and then flashing it to the other partition. Luckily, you only need to do this once.

Dual flash does offer a benefit: you can prepare working software on both partitions. If something goes wrong with the initial partition, you can simply switch over and boot the router from the alternative one.

However, dual flash also comes at a cost. The storage available on the MX4200, which is 512MB NAND, will be halved. Each firmware installation will only have half of the total storage available for data.

This means your disk space (**Storage**) available on your router will effectively be around 110MB for applications that you wish to install.

Comparing this to my single-flash router, the [Askey RT4230W REV6 (RAC2V1K)](https://openwrt.org/inbox/toh/askey/rt4230w_rev6?s[]=procd) from Spectrum (imported from the US), which I repurposed with OpenWrt, I have almost 354MB of storage available for my applications.

This implies that, by upgrading my router to newer technology (processor), I am getting a third of the storage. This is precisely why the MX4300 model would be much better to purchase, if available in the UK.

Luckily, on my current router, I am only using slightly over 42MB of storage. Hence, 110MB available in total will not be an issue for now, but it would be better to have some room for future needs.

---

From the discussion on my other post, some people suggested looking into NanoPi. If I were to go down this route, I would currently only consider the **NanoPi R6S** due to its superiority in every aspect, also providing, by default, three LAN ports (one native Gigabit Ethernet and two PCIe 2.5G Ethernet, each over separately designed network chips).

If you're looking for a budget-friendly option for use in your home network, consider a second-hand Linksys MX4200, to which you will change the firmware from Linksys to pure OpenWrt.

If money is not a problem, or you require much more processing power, especially in a business environment, then the NanoPi R6S is the device you should consider. This is particularly relevant as it's also natively supported by the latest OpenWrt.


---
## Updating Software in macOS (2025)
- **URL:** https://dariusz.wieckiewicz.org/en/updating-software-in-macos-2025/
- **Date:** 2025-05-13
- **Tags:** macOS, App Store, Updates, MacUpdater, Latest, TrashMe 3

### Content

At the beginning of 2021, I [wrote](/en/updating-software-in-macos/) on my site about how I manage software madness on macOS. 

The problem with software on macOS, but also in Windows, is that there is no central way from which software is installed and updated.

Not like on Android with Google Play and iOS/iPadOS where installations and updates are managed through App Store. On macOS, there is App Store, but the majority of apps are downloaded and installed from other sources. Same as Windows. Windows has Microsoft Store; however, still, there are plenty of things done outside of it.

With Windows Microsoft Store, developers can list their products, which are not directly installing through Microsoft Store, but are just links to installers. Even so, it's a great way to keep apps always up to date.

With macOS, I have been using MacUpdater. I even purchased a licence, as it was good value for money.

Sadly, without warning, and only discovering it by accident, by the end of 2025, the MacUpdater will be no more.

Ok, "will be no more" is a bit of too much, as software will still be working, but the developer does not guarantee that it will function as required.

> MacUpdater, the popular software update utility for macOS, has been discontinued by its developer, CoreCode, and will no longer be actively developed after January 1, 2026. However, all existing MacUpdater 3 licences will continue to be supported until that date. The developers are looking for potential buyers for the software's code and technology. 

<!--more-->

As a licensed user, I would expect an email with that info, not just discovering it when I updated my Mac and I need to re-enter licence information to notice a warning about what is happening from 1st January 2026.

Quickly heading into their website, I come to the conclusion that they have enough and are looking actively to sell this software and the backend related to it. I wish them all the best and hope somebody will be able to continue, but if not, I will need to look for an alternative really shortly.

I have been running MacUpdater from time to time to update 10-20 apps each time. This app shows how poorly software is maintained. The lack of automatic update features implemented by developers and swift updates to the latest version are a big pain for Mac users.

Most issues that you may experience are related to the fact that you are using outdated software.

Enough about that. I need to know where to go next with it.

{{% ads-in-article %}}

If you start searching for alternatives, it has been quickly suggested through various other solutions, from which two keep repeating.

One of them is [**TrashMe 3**](https://www.jibapps.com/apps/trashme3/), which is a tool for cleaning and uninstalling apps as its main purpose, but also an updater.

Apart from that, I have been pointed to an app called [**Latest**](https://max.codes/latest/).

The first one is paid, whereas the second is released as an Open Source project relying on donations.

Also, **TrashMe 3** is available to download as a DMG and to be purchased ($14.99) through macOS App Store, whereas **Latest** is available to be downloaded as a DMG only.

Before I decide in which direction to go, I decided to do some testing of both.

The **Latest** was first.

Since the last time I ran MacUpdater, I just got three outstanding updates. In the first run of **Latest**, I got two out of three identified by it, but after pressing the refresh button, I was also prompted with updates for apps available through the App Store.

The annoying part of the App Store on macOS is the fact that apps do not update themselves with the same frequency as on iOS.

When an update is released on iOS, it will take a day or two for updates to be applied. Typically, it happens when I put my phone to charge overnight.

On macOS, it's inconsistent and, sadly, unreliable. This is why it's great to see the updates waiting in the macOS App Store in the **Latest** app as well.

> MacUpdater has been showing updates available on the App Store, but I miss a lot of them.

I run **TrashMe 3** next. As I downloaded it over the website as a DMG file, I was given a 15-day trial period, so I can decide which one to use.

Concentrating solely on updates, I compared **9** found by **Latest** to **7** found by **TrashMe 3**.

[![Latest app - main window](latest_app.png)](latest_app.png)

From **9** found by **Latest**, 3 of them were related to software not available through the App Store.

[![TrashMe 3 App - window with update section](trashme_3_app.png)](trashme_3_app.png)

From **7** updated found by **TrashMe 3**, only 1 was related to software installed by other means and the other 6 directly to an app updated over the App Store.

> One software update for iA Writer was only shown in **TrashMe 3** and not in **Latest**.

I am using **MEGA** to store some files in the cloud. Apart from MacUpdater, none of the other apps see an update for this app. To be honest, this is the app that I would personally not update through MacUpdater, as most of the time it causes a crash and needs to be reinstalled from the source. It is no surprise that it is missed or excluded in both other solutions.

At this stage, the winner is **Latest**; however, even if the software is better and free, I always worry about its sustainability.

Where you are paying a licence, you are supporting the developer and giving him motivation to invest in the project. There you rely on open source; you must prioritise your time on things that will maintain your daily needs over the project that is not the main source of your income.

Overall, if you look on [**Latest on GitHub**](https://github.com/mangerlahn/latest), in the **Releases** section, you will notice that the app was updated the last time in **February 2024**.

Of course, the update of the app is not as important as the software database behind it and the way the app checks for the latest version and updates available.

Overall, **Latest** has a simplistic interface, pleasant for the eye; hence, there is nothing missing from it, so there is no need to update as often as you may think.

> I quickly launched the [**Silicon** app](https://github.com/DigiDNA/Silicon) and found out that both apps, **TrashMe 3** and **Latest**, are universal apps working on Intel and Apple Silicon apps without problems.

For me, **TrashMe 3** is a bit of overkill, as I am using other apps for cleaning and uninstalling purposes, and I am fine with them.

{{% ads-in-article %}}

Going back to the numbers, 9 vs 7, you will quickly see that the **Update** button on **Latest** is not always pointing you to update the app but, like with Microsoft Edge, will just open the app and let it update itself in the background, in theory.

Microsoft Edge, in the About section, reported to me that it is in the latest version despite **Latest** saying differently.

Next one, **balenaEtcher**, the Update button also just opens the app and does not update it, which is a bit confusing, as this app does not have an updater built in, so you need to find a way to do this.

The **Latest** for information purposes about updates available is more than enough for me, but in matters of updating apps for us, like **MacUpdater** used to do, this is not this app's main purpose.

Overall, the way apps are installed, and in the majority, updated, in macOS is just limited to opening a DMG file and dragging and dropping the app to the Applications folder. Simple as it can be.

If you look at the apps updated available in the App Store, the update button in **Latest** is doing what it is intended to, updating the app, without the need to open the App Store, whereas in **TrashMe 3** you are only greeted with a button to **View in App Store** from where you need to click the update button.

I updated all the apps highlighted and decided to wait and see which app to keep, or shall I look further.

I doubt that in the 15 days of the **TrashMe 3** trial period I will be able to assess which app is better, so I decided to stick with **Latest** for now and over the next month compare its output to sunsetting **MacUpdater**.

If in fact **Latest** will be my go-to app, I will likely consider donation and will recommend others to do the same.

The optimistic matter of the **Latest** app is a text written on the author's [donation page](https://max.codes/latest/donate/):

> "Latest is a free and open source application I work on in my free time. **I never planned to earn any money with it, so I am happy if you are happy using it.** However, if you like the app and would like to support its development, **feel free to think about donating**. **I am super thankful for that!** I support donations via bank transfer (EU), PayPal as well as direct credit card donations."

This reminds me of myself a bit.

I am writing and publishing what I can, helping others wherever I can, most of the time for free. I do not intend to earn money from knowledge that I want to share, as I have a full-time job that provides it to me. However, I admit that it is encouraging to receive from time to time a small incentive, especially in times that you least expect it, to boost your confidence and to know that there are people who benefit from your work and really appreciate it.


---
## OpenWrt, mwan3 and default route for IPsec (strongSwan) tunnel
- **URL:** https://dariusz.wieckiewicz.org/en/openwrt-mwan3-default-route-ipsec/
- **Date:** 2025-05-01
- **Tags:** OpenWrt, ipsec, strongSwan, wireguard, mwan3, defaultroute, iproute, failover

### Content

Recently, I faced an issue with **mwan3**, a package on OpenWrt routers that is designed to manage multiple internet connections, either for load balancing or a failover.

At work, we have two fibre connections, where the main one is used primarily and the second is online, but only activated when the first goes down – typical failover approach.

> First connection (lets call it **fibre**) is with metric 10 wheras second connection (**fibre2**) is with metric 20.

> For tech guys, first fibre is **uncontended** with static IP, whereas our backup fibre is **contended** over PPPoE.

My main **policy** in **mwan3** is **fibre_fibre2**.

> **fibre_fibre2** policy contain **fibre_m1_w3** (Metric 1, Weight 3) and **fibre2_m2_w2** (Metric 2, Weight 2) member.

When **fibre** is down, the **fibre2** takes over and all traffic flows through nicely, **almost**.

<!--more-->

I said almost, as there are some instances where traffic is flown through the wrong interface, even if the interface is down.

I also have [WireGuard server set on my router](/en/installing-vpn-server-on-router-openwrt-wireguard/), so when one connection goes down, WireGuard starts accepting connections on the second IP.

It is a known issue when you are using **mwan3** with a balanced approach, that it is not possible to have WireGuard accepting connections on both connections at once with **mwan3** active.

The flaw in **mwan3**, which is not as easy to sort as it sounds, is that if the main connection is down and backup is activated, any connections initiated by things running on the router itself are still trying to connect through the **default route**.

If you run the command:
```bash
ip route show
```

You will get something like that:
```
default via 1.2.3.4 dev wan metric 10 
default via 4.5.6.7 dev wan2 metric 20 
```

> Whereas wan is my **fibre**, and wan2 is my **fibre2**.
> 1.2.3.4 is theoretical IP of **gateway** for wan interface and 4.5.6.7 is a theoretical IP of **gateway** for wan2 interface.

When the main connection goes down, all LAN traffic is neatly redirected through the second connection. Local traffic and VoIP phones in business keep working.

However, locally run services may still want to try to send traffic through the default route.

The problem is that when the main connection is down, the default route with the lowest metric is still shown in the routing table; hence, locally run services still think that it is the default, through which traffic shall be sent and received.

The problem is that **mwan3** cannot directly amend these default routes; hence, some router traffic will still be pushed through the route with the lowest metric, even if that connection is down.

This issue affects services like **IPsec** tunnels that I have implemented on the router to allow the whole LAN network to access specific services used in business through RemoteApp.

I got two IPsec tunnels in place. One for the main connection (`left=1.2.3.5`) and the second for backup (`left=4.5.6.8`).

> 1.2.3.5 is the theoretical IP of the WAN interface (**fibre**), and 4.5.6.8 is a theoretical IP for the WAN2 interface (**fibre2**).

These tunnels cannot work together as they share the same left subnet (`leftsubnet=192.168.1.0/24`).

The first IPsec tunnel is activated (`ipsec up tunnel1`) when the main fibre is up. The second tunnel (`ipsec up tunnel2`) is activated when the main fibre goes down and **fibre2** takes over (after... `ipsec down tunnel1`) – **in theory**.

When my main fibre goes down and **mwan3** redirects all traffic through fibre2, the **ipsec** connection is still sent through the **default route** even though the _left_ IP states which IP to use.

The fault is the **default route** and the lowest metric of the interface.

Let's recall our command:
```bash
ip route show
```

And look at that again:
```
default via 1.2.3.4 dev wan metric 10 
default via 4.5.6.7 dev wan2 metric 20 
```

Even though **mwan3** is nicely redirecting all the traffic, and the second IPsec tunnel is connecting nicely through the second connection (`left=4.5.6.8`), the traffic that comes from the IPsec tunnel itself, like ping to IP on the other side of the IPsec tunnel, still utilises the default route with the lowest metric (going over the wrong interface).

You are doing `ping 10.1.2.3`... which is sent through the currently active fibre connection (fibre2/WAN2), but the ping response is directed through the default route with the lowest metric, which belongs to the fibre connection (fibre/WAN) that is currently down.

This was a bit of a head-scratcher for me one day. I tried to understand what's going on, as IPsec tunnel2 was connected correctly, both ends see it, but LAN traffic through the tunnel was not flowing.

I decided to shut down the main interface, that is currently marked as down, with `ifdown wan`.

Once I executed that, local traffic through the IPsec tunnel started flowing, and ping started responding correctly.

When I looked at `ip route show` I noticed that once you put down an interface, the default route, which was with a metric of 10 for WAN, was removed, and only the default route, with a metric of 20, was for WAN2.

Thanks to that, I understand the problem and the limitation of **mwan3** when it comes to the **default route**.

I need to get this sorted, and after a bit of reading, I did it with the use of [mwan3 Alerts/notifications through mwan3.user](https://openwrt.org/docs/guide-user/network/wan/multiwan/mwan3#alertsnotifications) located in `/etc/mwan3.user`, that can be edited through Terminal or over the web interface (**Network** > **MultiWAN Manager** > **Notify** tab).

{{% ads-in-article %}}

## Theoretical approach

The idea was, when **fibre** goes down (controlled and notified through mwan3), the metric for this connection changes, so the **fibre2** (second connection that will take over by mwan3) becomes the lowest metric.

This will allow traffic to flow through the connection with the lowest metric, which, in that instance, will be the connection that is currently active as a backup (**fibre2**).

## Practical solution

To change the metric of the interface, you need to remove the **default route** first for the first connection.

> Sadly, it is not possible to just amend the metric, which would be ideal in that case.

In that case, when the main connection (fibre) goes down and traffic is re-routed (by **mwan3**) to the backup connection, I need to change the metric from 10 to higher than 20.

> I decided to just add zero to the current metric.

I am doing that by executing the following commands.

```bash
ip route del default via 1.2.3.4
ip route add default via 1.2.3.4 metric 100
```

> This will also redirect the default response of the Wireguard Server to go through the connection with the lowest metric.

## IPsec failover

In my `/etc/ipsec.conf` file, I specified two tunnels, one for each IP of each connection.

Tunnel `conn tunnel1` for `left=1.2.3.5` (main, **fibre**)‌ and `conn tunnel2` for `left=4.5.6.8` (backup, **fibre2**).

Because both tunnels share the same subnet (`leftsubnet=192.168.1.0/24`), they cannot work simultaneously (at the same time). I need to set tunnel1 with `auto=start` and tunnel 2 with `auto=add`.

In that scenario, when for some reason tunnel1 fails or disconnects, the IPsec will re-try to reconnect to it straight away. The second tunnel will only be able to connect by doing it manually via `ipsec down tunnel1` and executing `ipsec up tunnel2`.

This is not a perfect solution because when my main connection goes down, I will need to go to the router and manually bring tunnel2 up. 

The problem is that sometimes there needs to be a time before the other end will notice that tunnel1 is actually down. As if I try to connect tunnel2 when the other end still sees tunnel1 active, there will be a failure running tunnel2 due to an authentication error (even when both tunnels share different access passwords stored in... `/etc/ipsec.secrets`).

I decided to put both tunnels into separate files.

```
/etc/ipsec.conf.tunnel1
/etc/ipsec.conf.tunnel2
```

I set it in both files `auto=start`. When the second tunnel is meant to be up but fails due to a premature connection and authentication error, it will keep retrying until it succeeds.

Of course, putting the tunnels in separate config files will not make them work, as the IPSEC service will always be ready only from `/etc/ipsec.conf`.

In that case, like I executed a change of metric for the first connection, when it goes down, I will need to tell which IPSec tunnel needs to be used by copying. `ipsec.conf.tunnel2` in place of `ipsec.conf` file when fibre2 becomes an active connection. When the main fibre goes back online, I will need to copy `ipsec.conf.tunnel1` into `ipsec.conf` to make tunnel1 the default connection.

Of course, each time after copying, I need to restart the IPSEC service using the `ipsec restart` command.

> If you using strongSwan, using `swanctl restart`

Now I need to combine all the above to do this automatically with [MWAN3 Alerts/notifications feature](https://openwrt.org/docs/guide-user/network/wan/multiwan/mwan3#alertsnotifications)

{{% ads-in-article %}}

## mwan3.user script

Let's put the script below into the `/etc/mwan3.user` file either by editing it through Terminal, or pasting the content through the web interface (**Network** > **MultiWAN Manager** > **Notify** tab).

> All the IP addresses here are fake and need to be adjusted to whatever you are using. For your information, all of my connections use a static external IP address in the IPv4 range.

```bash
#!/bin/sh
if [ "${ACTION}" = "disconnected" ] && [ "${INTERFACE}" = "fibre" ] ; then
    # When FIBRE down - set FIBRE2 as primary
    ip route del default via 1.2.3.4 2>/dev/null
    ip route add default via 1.2.3.4 metric 100 2>/dev/null
    cp /etc/ipsec.conf.tunnel2 /etc/ipsec.conf; ipsec restart 2>/dev/null
fi

if [ "${ACTION}" = "connected" ] && [ "${INTERFACE}" = "fibre" ] ; then
    # When FIBRE up - remove FIBRE2 priority route
    ip route del default via 1.2.3.4 2>/dev/null
    ip route add default via 1.2.3.4 metric 10 2>/dev/null
    cp /etc/ipsec.conf.tunnel1 /etc/ipsec.conf; ipsec restart 2>/dev/null
fi

if [ "${ACTION}" = "disconnected" ] && [ "${INTERFACE}" = "fibre2" ] ; then
    # When FIBRE2 down - set FIBRE as primary
    ip route del default via 4.5.6.7 2>/dev/null
    ip route add default via 4.5.6.7 metric 200 2>/dev/null
fi

if [ "${ACTION}" = "connected" ] && [ "${INTERFACE}" = "fibre2" ] ; then
    # When FIBRE2 up - remove FIBRE priority route
    ip route del default via 4.5.6.7 2>/dev/null
    ip route add default via 4.5.6.7 metric 20 2>/dev/null
fi
```

> **Remember!** When migrating to the newer `swanctl` framework, ensure you replace any `ipsec restart` commands with `swanctl restart`. It is crucial to stop and disable the legacy `ipsec` service (`/etc/init.d/ipsec stop` and `/etc/init.d/ipsec disable`), whilst enabling and starting `swanctl` (`/etc/init.d/swanctl enable` and `/etc/init.d/swanctl start`). This is important, as upon reboot, `swanctl` will cause a port conflict with the legacy `ipsec` daemon if both try to start at the same time.

You can see that there are four rules here.

1. When the main fibre goes down, the following things happen:
a. Remove the default route for the main fibre
b. Re-add the default route with a high metric of 100
c. Copy `ipsec.conf.tunnel2` into `ipsec.conf` (so the second tunnel, designed to work with fibre2 connection, will be used) and restart the IPsec service.

2. When the main fibre goes back online, the following things happen:
a. Remove the default route for the main fibre with a high metric of 100
b. Re-add the default route with the original metric 10
c. Copy `ipsec.conf.tunnel1` into `ipsec.conf` and restart the IPsec service

The third and fourth rules are optional and used to bump up the default metric from 20 to 200 when the connection is down, just in case, so even unintentional traffic will not be sent through the interface that is not operational.

> Default metrics for each connections are set in **Network** > **Interfaces**, by editing each interface and in **Advanced Settings** specifying metric in position **Use gateway metric**.

This way I have functioning **mwan3** for managing internet connections and re-routing traffic accordingly, and a failsafe for IPsec tunnels, to use the right tunnel for the right "active" connection, with directing traffic through the right route (default) of the connection that is currently in use.

The issue with **mwan3** and sending traffic through the wrong interface is not new, and sorting it is not as easy as it sounds, because it depends on many different scenarios. This is why, if we cannot have one solution to fit all, we need to build our own solution to fit what we need, thanks to **mwan3.user**.

Regards.


---
## In a Search of a Favorite Start Page (2025)
- **URL:** https://dariusz.wieckiewicz.org/en/in-search-of-a-favorite-start-page-2025/
- **Date:** 2025-03-14
- **Tags:** Blog, Bookmarks, chrome, Fast Dial, Favorites, Favorites New Tab, macOS, New Tab Page, Safari, Speed Dial, Windows

### Content

{{< tldr >}}
See [Favorites Start Page](https://chromewebstore.google.com/detail/favorites-start-page/cijiljolaemabjeaklgnfgofglfbonpa) by Jimmy Lye in chrome web store.
{{< /tldr >}}

There's been a lot going on recently with Google Chrome (and Microsoft Edge) browser extensions.

Things really heated up when new requirements were introduced, dictating how Chrome extensions are built and what they can do – Manifest V3.

Think of Manifest V3 as a blueprint or set of guidelines for extension developers, with a strong focus on boosting security, privacy, and performance.

While the shift to Manifest V3 is a whole other story, the PayPal Honey scandal prompted Google to take a much closer look at how Chrome extensions behave, especially those involved in affiliate marketing.

<!--more-->


It's highly likely that all this commotion has caused extensions like [Favorites New Tab](https://chrome.google.com/webstore/detail/favorites-new-tab-page/kjkbcegjfanmgocnecnngfcmmojheiam) from [web-accessories.com](https://www.web-accessories.com/), which I wrote about back in [2019](/en/in-search-of-a-favorite-start-page/), to throw up errors and become unavailable for download.

[![This item is not available](This_item_is_not_available.png)](This_item_is_not_available.png)

Those who have it installed can keep using it as long as it works, but unfortunately, it's impossible to install on new computers.

It might just be temporary, until the developer updates their extension to meet the new requirements, or changes whatever caused the extension to be removed.

Manifest V3 has been a hot topic for a long time now, so I suspect if the developer hasn't done it by now (like many others), it's possible it won't happen. Unless the extension was doing something more than it advertised, and Google removed it for security reasons. It's hard to say.

It's a shame, because I use this extension daily on my Windows 11 computers in a corporate environment.

[![Fast Dial – Safari - macOS Sequois](Fast_Dial_Safari_macOS_Sequoia.png)](Fast_Dial_Safari_macOS_Sequoia.png)

"As I'm a big fan of this kind of solution, and on my personal macOS computer I use Safari, which has a fast dial feature built-in for years, I decided to look for an alternative.

Unfortunately, it's not as easy as it might seem.

The current extensions, to put it politely, are poor. They look like they were made using capabilities from 20 years ago, or they require significant computing power to display everything nicely – unnecessarily!

{{% ads-in-article %}}

In my search, I tried various solutions, until I finally came across [Favorites Start Page](https://chromewebstore.google.com/detail/favorites-start-page/cijiljolaemabjeaklgnfgofglfbonpa) by Jimmy Lye.

[![Favorites Start Page in Microsoft Edge](Favorites_Start_Page.png)](Favorites_Start_Page.png)

Inspired by Safari's fast dial on macOS (specifically Big Sur), Jimmy Lye created his own kind of clone of the Safari solution some time ago.

In terms of appearance and behaviour, it resembles the current macOS solution, but it's adapted as an add-on for Chromium-based browsers.

Even though the solution is at version 0.3 beta 1, and the last update was on 20 October 2022, it still works excellently. It integrates with the default bookmarks, and the icons are refreshed from the websites.

> Here's one point that would require some work to make the icons display a bit better, and in the case of sites without proper icons, to have some colour variation, as everything looks very 'grey'.

I also suspect that this solution isn't yet adapted to Manifest V3 (I could be wrong), but I hope that if it needs to be, it will be, and we won't lose it like I lost Favorites New Tab.

As a thank you, I sent an email to the extension's developer, hoping it reaches them, and that the extension will be updated a bit and serve others for years to come!

For now, I have something that works, and I'm keeping my fingers crossed for the future.

Or perhaps you know of any recommendable solutions that both look good and work flawlessly?


---
## Windows 11 - CPU stuck at the minimal frequency (0.60GHz on Intel i7 11th Gen)
- **URL:** https://dariusz.wieckiewicz.org/en/windows-11-cpu-stuck-at-the-minimal-frequency/
- **Date:** 2025-03-11
- **Tags:** Windows 11, CPU, Rescuezilla, Power Plan, Power Options

### Content

I recently upgraded my work computer from i5 8th Generation to i7 11th Generation. In the opposite of installing OS from scratch and setting it all up again, as I haven't got time, I decided to use Rescuezilla and simply clone my system from the old hard drive to the new computer.

All goes well. 

After the first run, some drivers needed to be updated. I needed to detach the Windows 11 license from the old computer and pair it with one that had been delivered (embedded) with it.

All seems to be working really well until I start putting a bit of a stressful task into it.

<!--more-->

Quickly I noticed that the performance of the 11th Gen i7 was way below what I had experienced with an older device. I thought initially that it was due to drivers, so I updated them, including Iris Graphics, BIOS, and whatever I could, including Windows updates.

Sadly, this did not resolve the issue.

In Task Manager, the Performance tab, I noticed a very low default clock speed of the CPU. From time to time it peeked, but not as I expected and almost all the time stayed at the 0.60GHz speed.

That explained a lot why I had experienced such dragging performance.

I thought that I had missed enabling something. Maybe something related to turbo boost of the processor. I tried various suggestions found on the web, but I couldn't force the processor to work at High Performance all the time.

I went into `Settings > System > Power`, where I noticed that it's set at the High Performance and there was nothing else to change there.

It was a bit of a surprise, as I couldn't set up other modes, like it is by default there (see picture below on how it shall be).

[![Windows 11 - Settings - System - Power & Battery](Win11_Setting_System_Power_and_Battery.png)](Win11_Setting_System_Power_and_Battery.png)

I remember that I can set the performance plan from abandoned, but still handy, old Control Panel.

{{% ads-in-article %}}

I head to `Start > search for Control Panel (by typing) > Hardware and Sound > Power Options`I, and there I found a few plans. One was Balanced, and one of the others was High Performance.

[![Windows 11 - Power Options - Power Plan](Win11_Power_Options_power_plan.png)](Win11_Power_Options_power_plan.png)

It was very interesting that I could change settings there but not from Settings, where by default Microsoft is pushing users to go for such options.

Changing it between Balanced and High Performance does nothing. The The CPU keeps at 0.60GHz. I even went into the Advanced settings of each plan to change the minimum processor speed but setting it to 100%. Even that, nothing changed.

I have been intrigued.

Of course, my issue stands from the fact that I transferred the whole system from one computer to another, hence some stuff may not be working correctly.

I quickly discovered that this issue, however, is very common. A clean installation of the OS most likely will fix that; however, I do not want to go through that route, and good that I didn't.

I recalled that through Settings I couldn't change the power plan but I could change it through the old settings found in the control panel.

That is strange.

I looked on another computer in the company and noticed that there are options in Settings where you can set a specific plan for when the computer is used on battery and when it is plugged in. I have been missing them. I got them in the old place, but they haven't been working at all.

I decided to head back to the control panel and remove the High Performance plan (I got the option to remove it, where on the other computer I haven't had that option), leaving only the default Balanced.

I headed later into the Balanced plan and selected the option to reset it to default settings.

{{% ads-in-article %}}

> If you got more than one plan there, and you don't have option to remove them, make sure you choose `Reset default settings for this plan` for all of them.

[![Windows 11 - Power Options - Edit Plan Settings](Win11_Power_Options_Edit_Plan_Settings.png)](Win11_Power_Options_Edit_Plan_Settings.png)

I get only one option there, but to my surprise, the processor moved significantly and I even started hearing noise from the fans. The The Task Manager in the Performance tab quickly showed the computer working with speeds like 3.6GHz and even 4GHz.

It worked. The performance in places where I had been noticing it a lot improved drastically.

Heading back to Settings and Power, I noticed that previously unavailable options for different power modes, based on use, became available.

There, for when the computer was used on battery, I could select Balanced or High Performance. Same for when plugged in.

In my instance (in yours, it may be different), it was clearly a mess with power management plans. Removing extra plans and restoring other plans to their primary settings did the trick, reverting some options back to how they should be. This restored Power settings and revealed options that hadn't been accessible through Settings.

Of course, I was forced to review other settings, to see what happens when I close the laptop lid or when the computer is going into sleep and turning off the screen.

The goal achieved, problem resolved, happy days!


---
## The Skype Shutdown: Why Teams Sounds Like a Downgrade for Some Users
- **URL:** https://dariusz.wieckiewicz.org/en/the-skype-shutdown-why-teams-sounds-like-a-downgrade/
- **Date:** 2025-03-06
- **Tags:** Skype, Microsoft Teams, Skype Shutdown, Downgrade

### Content

With [very short notice](https://www.microsoft.com/en-us/microsoft-365/blog/2025/02/28/the-next-chapter-moving-from-skype-to-microsoft-teams/), Microsoft finally made a move to kill Skype altogether and concentrate on something that, by default, is integrated with Windows 11 – Teams.

I personally tried to move a few people out of Skype to Teams years back, but now there are no ifs or buts, as Microsoft is pulling the plug. There is no going back.

As much as I am happy, I quickly started feeling that removing Skype is putting some users back.

If you are not paying anything extra to Microsoft, you will quickly notice that you are missing some crucial features in Teams that have been available in Skype for years.

<!--more-->

## Portrait mode limitation

I tend to communicate over Skype with my parents abroad. They are using a laptop to connect to the call, whereas I am always calling from my mobile.

It's not really convenient for the other side, whose screen is by default in a horizontal orientation, to see only a portion of the other person when holding the phone in portrait mode. This is why, once I initiate a call, I quickly rotate my phone into a horizontal orientation and everybody is happy.

Something as trivial as screen rotation should not even be considered a feature, but rather a standard thing that all other communicators, like WhatsApp or Facebook Messenger, have as standard.

With Microsoft Teams, it is not the case.

If you are using Teams with your personal Microsoft account, without paying any Microsoft 365 subscription, you will quickly notice that once you connect to a person who is in a horizontal orientation, you cannot rotate your screen.

You are stuck in portrait mode, as if this is the only mode possible.

If you are joining webinars and somebody starts to present their screen, and the presentation is in horizontal mode, you are unable to rotate the screen to utilise the whole space available. This is a bit of nonsense.

I initially thought that there was something wrong with my app or some settings, but switching (inside that same app) from a personal account to a business account, with an attached Microsoft 365 licence, I quickly noticed that the whole screen of Microsoft Teams can be rotated. Messages can be typed in horizontal mode, and during calls, you do not have any issues rotating the screen.

Switching back to a personal account, even though this is inside the same app, your ability to do standard things is gone.

## Low-cost calls

If you ever used Skype Credits to make international calls to landlines or mobiles, at a fraction of the price, this is another feature that you will lose once migrated to Teams.

Without thinking about it and bringing an alternative approach, personal Teams users will be worse off once again.

## Real-time translation

Despite the fact that I never used this feature, Skype apparently offered voice and video call real-time translation.

This is something that will also be missing when you are forced to use Microsoft Teams.

{{% ads-in-article %}}

## SMS Connect

With this feature, you could send and receive SMS messages. Similar to low-cost calls, this is something that is not offered in Teams at all.

## Voicemail

In line with low-cost calls and SMS Connect, voicemail is another feature that will be missed.

In the past, you could even integrate some desk phones to use Skype, as well as purchase a Skype number to have a landline where it was not available through normal means. All of which marks an end to a certain era and certain features lost forever.

## Calls recording

Once again, Microsoft will want us to spend some money with them. Call recording is another feature that, in Teams (Personal), will only be available with a Microsoft 365 subscription.

---

Not all things are bad. By migrating from Skype, you will gain more collaboration tools, meeting features, and better security for calls.

However, most basic users do not bother as much with this. They want to use it to make calls in a way that they like, not how it is available, without paying.

Overall, I don't see any sense in not just sticking with WhatsApp or Facebook Messenger, where both of them can offer video calls in the Windows 11 environment without most annoying restrictions, like the limitation of calls to only portrait mode.

---

I found myself a bit disappointed with all of this.

Skype has been a tool that has worked as simply as possible and as easily as it could be, so even elderly people could operate it without excessive knowledge.

---

On their own blog, Microsoft wrote:

> "We’re excited about the new opportunities that Teams brings and are committed to helping you stay connected in new and meaningful ways."

This "new and meaningful ways," as I see it, for personal Skype users, is one step forward, two steps back.


---
## When email deliverability matters – Gomailify.com
- **URL:** https://dariusz.wieckiewicz.org/en/when-email-deliverability-matter-gomailify-com/
- **Date:** 2025-02-20
- **Tags:** Cloudflare, Cloudflare Email Routing, Email, Email Routing, Gmail, Gmailify, Gomailify.com

### Content

> **Update 14/03/2026**\
> Due to [changes by Google](https://support.google.com/mail/answer/16604719?hl=en) and a decision to make life more difficult for users, they have decided to shut down the excellent Gmailify service and the ability to fetch emails from other mailboxes using POP. Consequently, the team behind Gomailify has had to rebuild their entire service to meet these new requirements. They are now using the Google API to push emails to our inboxes. While it was a bumpy road at the start, the service now works brilliantly. I still highly recommend it and use it daily.

> **Update 01/07/2025**\
> Because Gmailify.com was just too spicy for the trademark police, the owner of the service been forced to rename it to Gomailify. Apart of the nothing change, Same trusted service, same mission to supercharge your Gmail, just with a dash more go!

After years of using a free Google Workspace account, and after ups and downs with it, due to Google's decision to kill it and then keep it alive, I decided to move my emails and other files back to my personal Gmail account.

My main reason for using Google Workspace was the ability to use my domain across Google services, mainly concentrating on the ability to send and receive emails within my domain, but still using the Gmail interface.

After extensive work I had done to move my data from Google Workspace back to my Gmail account, I set up an option for me to receive and send emails within my domain.

<!--more-->

I chose [Cloudflare Email Routing](/en/cloudflare-email-in-your-own-domain/) for that purpose and it mainly worked, for almost three years. 

Cloudflare Email Routing is designed to receive emails sent to my address at my domain; however, it's not truly designed for sending them or replying from the email address at the domain.

I implemented a ["sort of" hack](/en/cloudflare-email-in-your-own-domain/#sending-and-replying-from-a-domain-gmail) to be able to send and reply to emails from a domain in Gmail and it worked quite well, **until it didn't**.

Implementing hacks to services that are not designed for such purposes may cause problems. Even if it didn't for a few months, things on the internet change (evolve) and problems occur.

> Apart from Email Routing, Cloudflare recently started working on an Email Sending service. It is currently in beta, and you need an invitation to use it. In the near future, this may become a great additional alternative, though it will depend on how much it costs.

Firstly, I experienced problems with the receipt of messages.

I quickly noticed that some emails had not been delivered and they had been lost forever. Due to various reasons, I needed to figure out a backup plan to get emails back on track and into my inbox.

To resolve this problem, I implemented [Multipath Routing in Cloudflare Email Routing](/en/when-things-start-to-fail-cloudflare-email-routing/) by implementing email workers.

Once Cloudflare failed to deliver emails, for various reasons, to my Gmail address, I forced workers to move them to my backup email in Microsoft services (@outlook.com). From there, using Gmailify (from Google) - a service inside Gmail, I synchronised both mailboxes and all messages started flowing back again.

The number of emails that I lost dropped significantly and the backup measures seem to work nicely.

Shortly after, I noticed other issues when I was sending emails. Some recipients started claiming that they never received emails, and others had been noticing that they had been put into spam folders.

Once this started happening rarely, I didn't bother too much, until I started getting problems with deliverability to emails operated on Microsoft services.

A lot of companies use Microsoft 365 for Business that operate their emails on their domain. Some government organisations also use their solutions (I am using it at my workplace), and the fact that I was sending them emails with some important documents that they never received (as they landed in spam or were quarantined before even being delivered to the recipient) started causing a lot of problems.

The problem was so significant, that the percentage of emails that I sent and emails that were delivered was sometimes like the flip of a coin. That's very bad and I decided to make a move.

The cause of the problem was the "hack" that I implemented. I had been sending emails from my domain through "Send mail as" in Gmail, but I am still using Cloudflare infrastructure to receive them.

Even though I had the most crucial email security aspects set on my domain DNS records (SPF, DMARC), I still faced an issue.

After investigation, I found a problem that lay in DKIM signatures.

> "DKIM is an authentication method that ensures the message was not modified since it was accepted for delivery, as well as that it was authorised by the owner of the domain. It does so by adding a digital signature to the message for both the metadata (headers) as well as the content. The digital signature is based on public cryptography which works with a pair of keys, public and private. The private key is kept secret by the domain owner or the email service, while the public key is exposed in the DNS publicly as a TXT record. Once the receiving side receives the message, the public DKIM key is looked up and used for verifying the digital signature."

When I send emails from my domain in Google Workspace, the service digitally signs and matches all records with the Google service I have been using. But that was because Google Workspace was directly set at the DNS levels to use their services, including DKIM.

When I was using Cloudflare Email Routing and ordinary Gmail to send emails, Google services were signing emails with their own DKIM signature that didn't match whatever I set at the DNS level for the domain. This is because personal Gmail doesn't allow you to set up a custom domain, and as a result, a signature mismatch occurs.

Despite trying various options to bypass that, the fact remains that if I do not sort the DKIM signature, then most Microsoft services will class my emails as "Unverified" and direct them to the Spam folder, or in the worst case scenario (which has been happening very often recently), with very strict spam rules applied, will quarantine the message on their servers and not deliver it, even to the Spam folder, to the recipient.

This is terrible and has started causing, once again, serious issues not only for me but also for other people that I help to use the same approach to set up their emails on their domain.

All of this leads to the point that I need to stop using this service and explore a better solution.

The solution that I always had in mind was **Gomailify.com** (previously Gmailify.com).

> Here, do not confuse Gmailify (the Google solution) with Gomailify.com (a service not from Google). Google used to offer, inside their Gmail account, a service with the same name that is used for linking Outlook and Yahoo accounts with Gmail.

Before Cloudflare Email Forwarding I had been using Google Domains with their free option called Email Routing. But as it goes with Google, [they are killing this service](/en/google-killing-another-service-google-domains/) and scrapping it, selling it to the highest bidder.

I tend to always explore free solutions before reaching for paid ones. If the free solution does what is asked, then I generally don't see the reason for paying anyone else. 

The free solution sometimes works to a certain extent, and then you need to make a move and decide what's important.

I need to rely on my emails. The emails that I send must be delivered to their destination, which is a critical matter to me. There are no compromises here. 

With every service, some emails may be misclassified and not delivered as intended, but the ratio shall be as low as possible where the majority shall work (be delivered) as intended, unless you are genuinely sending spam.

With my current solution, this had started to become hit-and-miss and the percentage of emails that I sent that were affected was too high to accept.

{{% ads-in-article %}}

**Gomailify.com service is not free;** however, it costs only $12/year for up to 2 linked Gmail accounts, then $6/year for each additional (without domain limits).

> Some big players are offering this kind of service with similar price ranges, mostly charging per user and typically per month. This quickly becomes very expensive. Here you are getting a bit better value for money.

After turning off Cloudflare Email Routing and removing redundant DNS settings (mostly SPF and DMARC) I started setting up my domain.

> Spoiler alert: The text below is not a guide through this service or even a tutorial on how to set things up. I will not repeat something that is [well documented](https://www.gomailify.com/docs) already.

**Gomailify.com** is set up in a very nice manner. Everything is described to such a great extent that you can easily go from start to finish in less than 15 minutes, so your ability to receive emails will not be affected for too long.

> Even if it is longer, generally, servers, if they struggle to deliver, will try to reattempt after a short period, hence the chance that you will miss anything important is slim.

Setting up is limited to adding relevant DNS settings to our domain. Once that is done, we need to set up our main inbox and connect it with your Gmail account so you can receive emails at your domain ( almost instantly) but also send emails through it using smtp.gomailify.com. No hack is needed.

Their service provides a temporary mailbox, a middleman, from which the service is grabbing them and pushing to Gmail account using Google API. They also provide an outbound server for sending emails and, through that, applying relevant signatures so their emails do not look like spam.

The whole setup process can be started and tested throughout the day without the need to pay (14 days trial). Throughout that period, you have the option to set things up and then decide. I decided very quickly when I noticed that recipients, who typically have problems receiving my emails, started receiving them without any issues.

The best part is that you only need to per linked Gmail account. At the starting price of $12, you can link up to 2 Gmail accounts, then $6/year for each additional. Link all domains you need without paying extra.

I have two domains. I have set up my main one and the second I added as an alias domain.

Automatically, my user `dariusz` in domain `wieckiewicz.org` will inherit access to the second domain in the same manner.

This solution is not specifically designed to manage domains separately by default, but it can be configured to do so. For example, if you want `dariusz@domain1.com` sent to `user1` and `dariusz@domain2.com` sent to a different user, the `dariusz@` prefix is typically directed to the same user (unless you are using delegation). However, if you want to manage domains separately, you can; you just need to account for the number of connected Gmail accounts, as that determines what you will be paying for.

I currently have 5 domains connected, of which 2 have active mailboxes. One of them hosts 5 mailboxes across 3 domains, which will cost me $30 per year ($12 + 3 × $6). The other has 3 mailboxes across 2 domains, which will cost me $18 per year ($12 + 1 × $6). Not bad at all!

This makes this kind of service even more value for money.

The service is designed with Gmail in mind and only Gmail. There are some limitations to the service, like the ability to send emails from a domain only through a web interface or the official Gmail app on mobile platforms, or not being able to set an email to send from on devices like photocopiers. You can read about all the limitations in the [very detailed documentation](https://www.gomailify.com/docs).

Apart from just a mailbox, you can also set plenty of aliases and use these aliases across Gmail, to send emails through them. Aliases can be in the main domain or even just in the additional domain. The only aspect to remember is when setting "Send email as" that you set an additional domain using authentication login and password for the main domain.

> You can also set up delegations, in such a way that one user has his mailbox, where copies of emails sent to them are delivered to other users. This is a good solution for setting up email for kids, which gives you the ability to see what type of emails are sent to them.

During setup, you may experience some problems from time to time, but even when that happens you can count on support from real `humans`. 

I had one issue while setting up an additional mailbox, and they helped me very swiftly. Later, I experienced some problems with passwords and sending emails from aliases, and they were right on the ball, helping me get everything sorted. It was the same when they migrated from the old method of pushing and fetching emails via POP — before Google shut it down — to relying solely on the Google API. They have been there when needed most.

Customer support, which is unusual for such an inexpensive service, is hard to find in solutions from big players.

Overall, once the service is set up, you forget that it is there, as you are using it through your Gmail account. Logging on to their service is mostly needed when you add additional aliases or want to track some logs.

> Remember, when you set up "Send mail as" in Gmail, you can set your own domain email as the default, so you don't need to switch it every time you compose a new message. The same applies to your Google Account itself; in the settings, you can add [alternative emails](https://myaccount.google.com/email) that can be used to log in to your Gmail account. By doing so, you will be able to log in to Gmail using your own domain's email address.

What I had been missing on Cloudflare Email Routing is a decent monitoring system of emails sent to the domain and sent from the domain. Of course, there are no sent-from-domain stats, as Cloudflare Email Routing is not designed for that, but for emails received, it is still not the best one, especially when emails are failing to be delivered, and you cannot do anything about it.

There is another aspect that is worth mentioning.

The people behind this service reside in Europe (Switzerland), hence, for data processing and privacy, we may be a little less worried, especially now, when we see how things are evolving (in not a good direction) on the other side of the Atlantic Ocean.

I have been using their service for a while now, and I am amazed by its reliability. This is the most important factor to take into consideration when choosing where to manage emails for your own domain. over time, I discovered a few mistakes I had made, but I was able to resolve them quickly with generous help from real "human" support.

Right now, this has become a "set and forget" service (though, of course, don't forget to pay the following year!).

I highly recommend it.


---
## Physical Camera Control button and an Inherited Habit (iPhone 16 models)
- **URL:** https://dariusz.wieckiewicz.org/en/physical-camera-control-button-and-an-inherited-habit/
- **Date:** 2025-01-29
- **Tags:** iPhone 16, Camera Button, Camera Control, Shutter

### Content

Adding a physical camera button to the iPhone 16 series was a great step towards people using it as a main device for photography and making videos, and believe it or not, there are a lot of them. Some people have even successfully made full movies with iPhones.

When I upgraded my 13 Pro Max to the 16 Pro Max, the camera button was something I had been looking forward to until I noticed that I was not using it at all!

<!--more-->

In the very distant past, I had been using a digital camera, and the trigger button was always under my slightly bent index finger on my right hand.

Here, as a user with "history" I found myself in a position where the button was not accessible for use in daily life.

I do not have small hands, and my fingers are not short, but reaching the camera button while placing my hand on the side of the phone without covering the screen was a bit of a challenge.

I would personally prefer if the button were moved much further down, to the bottom of the phone by the full height of it, especially on the iPhone 16 Pro Max, which is bigger than the 13 Pro Max that I used before.

This move would allow me to have an experience similar to what I had in the past with digital cameras.

Currently, to reach and press the camera button, I need to keep my finger straight and stretch slightly to press it firmly. Unless I decide to press it by placing part of my hand on the bottom of the screen, then it's not a problem. It looks like a habit I will need to develop to use it in a comfortable way.

But that's not the reason I want to write about inherited habits.

By placing a physical button for the camera on the side of the phone, Apple didn't take it a step further and remove the camera shortcut button from the lock screen.

For the last three months, I noticed that I hadn't been using the camera button at all. Instead, I had been pressing and holding the camera shortcut on the lock screen.

This is a trivial approach, but it adds a split-second delay before the camera is up and running, ready to take pictures.

The physical button launches the camera app much quicker.

Also, when taking pictures, I still tend to press the capture button on the screen rather than using the physical button.

It is hard to break a habit that I inherited since my first iPhone 6, but I decided to make life harder for myself to change it.

As in iOS 18 we can easily customise lock screens, including the bottom two shortcuts, one of which is the camera shortcut, I decided to remove it altogether.

I initially replaced it with another app, like ChatGPT, but then I found that, through muscle memory, I was automatically pressing the ChatGPT icon to open the camera.

Removing it — at least until I change my habit — will hopefully help me and force me to use the physical button much more.

{{% ads-in-article %}}

But that's not all.

If I want to quickly open the camera and take a picture, the physical button helps with that. However, when I use the camera to take more than one picture, I quickly notice that I press the shutter button on the screen, and it makes perfect sense.

If you hold your phone with one hand, then utilising the physical button makes sense, but I found that I do not take pictures by holding the phone in one hand.

This may be due to the era of digital cameras, but it could also be because of the weight of the phone itself. When taking multiple pictures with the iPhone 16 Pro Max in your right hand, you will quickly notice how heavy it is and how your wrist starts hurting.

In the long run, I found that I hold my phone in photo mode with both hands, positioning my hands on the left and right in horizontal mode.

In this way of holding the phone, reaching for the awkwardly positioned physical button is a bit of a stretch, and I know I will not use it because my thumb is already naturally positioned, ready to press the shutter.

Maybe it's just me, but moving the button further down (to the right, when held horizontally) would make sense for me, although it might not work for people taking photos and pictures in portrait mode.

In that mode, the position of the button is optimised for the middle finger, allowing you to use the phone with one hand (left), without needing to stretch your thumb to reach the shutter.

I think that through the whole process of implementing the button, Apple needed to go through a thorough process to find the optimal position.

Overall, more people are taking photos and videos in portrait mode now, and for them, this button is perfectly positioned, right under their finger.

I am a bit of a dinosaur and still prefer horizontal mode in daily use.

This reminds me of a meme from Apple's past, when people complained about losing reception on their phones because they covered the antennas with their hand. Apple's response — from Steve himself at the time — was that "you're holding your phone wrong." That didn’t go down well, but as phones grew in size, it made perfect sense.

Due to my habit, I wouldn't be surprised if, from the grave, Steve Jobs were telling me the same thing — that "I'm using it wrong".

It's a tough job, and the older you get, the harder it is to change habits.

What do you think?


---
## In search of the perfect OpenWrt router
- **URL:** https://dariusz.wieckiewicz.org/en/in-search-of-the-perfect-openwrt-router/
- **Date:** 2025-01-12
- **Tags:** OpenWrt, router, Asus RT-AC57U, Linksys WRT3200, Linksys MR8300, Linksys WRT32x, Askey RT4230W REV6, RAC2V1K, OpenWrt One, GL.iNet, Brume 2, GL-MT2500, WiFi 6, WiFi 7

### Content

A router with custom firmware (OpenWrt) is a basic device on my home network, but I am also using it in the business environment as a main device, and all works great.

> In the past I used DD-WRT on my routers. Despite that their project is still ongoing, I found it lacking behind current needs.

OpenWrt use strictly depends on the device – router, that I am using. I always choose a device that will work for me and it will not bend under spikes of load.

<!--more-->

When I started my experience with OpenWrt, I used quite a cheap device like the Asus RT-AC57U. Quickly I realised, that I need more storage, more RAM and more processing power. I moved to Linksys WRT3200, shortly switched to Linksys MR8300 and went back to Linksys WRT32x (older brother of WRT3200). The WRT3200 is working at my work to this day, as it is a very powerful device.

At home, I decided to import from the US an Askey RT4230W REV6 (called also RAC2V1K) and change the firmware to OpenWrt.

This device, originally from Spectrum, is fitted with 1GB of RAM, 512MB of storage and a Dual-Core processor (Qualcomm Atheros IPQ8065) rated at 1700Mhz.

> It also has 1 port of USB 3.0, which is in my opinion a minimum that the router shall have. Buying routers with USB 2.0, especially, when you planning to connect a hard drive through this port, is in my opinion waste of money, not to mention the speed!

These parameters I found to be a bare minimum for advanced users (like me), who want to work with OpenWrt, in a way that is beyond the basic setup.

However, in all of these devices, I found a main flaw, which was WiFi. Asus WiFi was just ok, the Linksys caused a lot of issues and the signal strength and its range were very poor. The Askey (RAC2V1K), due to its construction, has WiFi chips positioned just under the fan (which is at the bottom of it). The cooling process of the whole system causes the WiFi 2.4GHz chip to overheat and fail from time to time.

I decided, that I will not be using WiFi on this, and other of my devices, either with Askey (RAC2V1K) at home or Linksys WRT3200 at work.

My decision to simply disable WiFi on them is also due to other reasons.

Currently, WiFi technology becoming another marketing point for broadband providers. From WiFi 5 to WiFi 6, right now selling point is WiFi 7, even though only a small amount of devices support it and even fewer WiFi routers on the market provide this technology.

My router processing power, storage and memory are enough for the near future, and I don't want to go and search for OpenWrt that got WiFi 7 but also met all other requirements. This is very difficult and becoming very expensive.

At my work, I am using dedicated WiFi devices to create a mesh network. The main device is connected to the router by a LAN cable. WiFi works independently to OpenWrt but all remain managed from the router end (DHCP). This allows me to upgrade the technology of the WiFi network, when needed, independently of the router. The network, all computers connected via cables, can work uninterrupted for longer.

At home, I made the same approach. Due to the unreliability of Askey (RAC2V1K) WiFi chips, I decided to go with TP-Link RE700X to create my home wireless network (WiFi 6).

I need to admit that TP-Link RE700X met all the expectations thrown at it and reduced the burden of WiFi from my OpenWrt router. It has great speeds and range.

> I use different SSIDs (WiFi network names) for 2.4GHz networks and 5GHz networks.

Of course, I have set this device into Access Point Mode and I have disabled DHCP, so all still rely on the OpenWrt to manage the network IP addresses, traffic etc.

At work, WRT3200 have two USB ports, one 2.0 and the other 3.0. I utilise them both, once for [4G backup](/en/adding-second-internet-connection-router-openwrt/) and the other to [connect the APC backup battery](/en/connecting-ups-battery-backup-to-router-openwrt/).

At home, I just need one port, but it has to be USB 3.0, as I am using it to [incorporate extra storage in my local network](/en/adding-usb-drive-to-router-openwrt/).

Most of the devices that I am using at home are connected using a Wireless network. Over the wire, I got only connected to my TP-Link RE700X and Apple TV (however I can move back to Wireless with it). So, apart from the WAN port, I will need at least 1-2 spare LAN ports on my "perfect" router, but even this can be sorted by adding a simple unmanaged switch.

> 2.5Gigabit Switch like [TP-Link TL-SG105-M2](https://www.tp-link.com/uk/business-networking/unmanaged-switch/tl-sg105-m2/v1/) cost £69.99, where Gigabit Network Switch like [TP-Link TL-SG105S](https://www.tp-link.com/uk/business-networking/unmanaged-switch/tl-sg105s/v4/) cost around £16 on Amazon UK.

{{% ads-in-article %}}

## OpenWrt One

Not far back (29th November 2024), the people behind the OpenWrt project presented their first device dedicated to OpenWrt and called it [OpenWrt One](https://openwrt.org/toh/openwrt/one).

It is great to see that there is a dedicated device available and in an affordable price range, **however**, I didn't find it interesting for me for a few reasons.

| | |
| :-: | :-: |
| CPU | MT7981B |
| CPU Mhz | 1300 |
| CPU Cores_numcores | 2 |

It has a Dual Core processor that should provide enough processing power for most users.

> I got in past Linksys MR8300 that was equipped with a Quad-Core processor but rated at 717Mhz and its performance (processing power) was poor.

| | |
| :-: | :-: |
| Flash MB | 256MB |

Here is a first lack of this device. 256GB of storage without "obvious" options to extend it, quickly will disappoint users who want to add more packages to it and make their devices work for longer. I noticed when working with WRT3200 (256MB) at work and RAC2V1K (512MB), this will require some compromises. Getting a device that is created in the mind of OpenWrt and has been limited at the start is a bit disappointing. I understand that they want to maintain a good ratio value for money, but still, I doubt this will work for a long time, and I will let you know why.

> Theoretically, you can expand that and use other storage options, like through M.2 2242/2230 socket for NVMe SSD (PCIe gen 2 x1).

| | |
| :-: | :-: |
| RAM MB | 1024 |

At least this device is equipped with enough RAM, that satisfy the majority of users yet still, in conjunction with low storage is a shot in the foot at the start.

| | |
| :-: | :-: |
| USB ports | 1x 2.0 |

Another shot into the foot of this device is equipping it with a slow USB port 2.0.

That's crazy, as even devices like Raspberry Pi incorporated USB 3.0 a while back. Ignoring the WiFi capability of this device (as I described at the start), I don't see the point for me to invest in OpenWrt One where Raspberry Pi 5 (released on 23 October 2023) will do a better job (and when they, on 9th January 2025, announced model with 16GB RAM).

| | |
| :-: | :-: |
| Ethernet 1Gbit ports | 1 |
| Ethernet 2.5Gbit ports | 1 |

The device, is not like a typical router, only with two LAN ports, one that will be utilised for the main internet connection (WAN, 2.5Gbit) and the other for local network (1Gbit).

We all used to have at least 5 ports, one WAN and 4 LAN ports. This limitation will throw us into the need to implement a switch if we want to connect more than one device over the LAN cable. Even though this is the compromise that I will understand, advanced users, will have this in place already.

As mentioned, WiFi is not needed for me on the OpenWrt router itself, and I personally, with the current speed of implementation of the new WiFi standards, would strongly suggest dropping Wifi support and the cost of it put towards greater storage and faster USB port.

It's a shame that OpenWrt One will not be something that I would recommend, however, the hopes are not lost.

---

One thing worth mentioning here is that OpenWrt One is **not** officially supported in the **Current stable** version of OpenWrt 23.05. There are works in progress with version **24.10**, which at the time of writing is in the **rc5** stage (Release Candidate 5). Not a big issue as I expect **24.10** will be finalised in no time, but that means that the device is released, but not designed do implementation into the production environment yet.

---

I started to look further for a device that would more likely meet my needs but would not break my budget.

I have always been interested in a company called GL.iNet and their devices that, by standard, are supplied with their software that works based on a bit outdated but modified OpenWrt software (21.02, released on 4th September 2021).

Their devices are widely supported in the OpenWrt community allowing us to put the latest stable version of OpenWrt and making it a great base device for implementation of OpenWrt in production.

However, over the past, the devices (especially the ones in the budget range) dragged behind in their specifications and the one that I found, that could potentially replace my RAC2V1K or WRT3200, was beyond my affordability.

Things changed recently when the company presented some refreshed devices. I am not monitoring their products daily and only when OpenWrt One was released did I search for something that they offer, to find a potentially **perfect OpenWrt router**.

{{% ads-in-article %}}

## GL.iNet Brume 2

Brume 2, or [GL-MT2500](https://www.gl-inet.com/products/gl-mt2500/), is not a new device (released October 2022), but when first Release Candidate version of upcoming [OpenWrt 24.10](https://openwrt.org/releases/24.10/changelog-24.10.0-rc1) was released, added support for GL.iNet GL-MT2500 point me to check what it is and how much it cost. I was positively surprised but at the same time, I started to question the point of releasing the OpenWrt One device after all.

| | |
| :-: | :-: |
| CPU | MT7981B |
| CPU Mhz | 1300 |
| CPU Cores_numcores | 2 |

Brume 2 carries the same processor as OpenWrt One.

| | |
| :-: | :-: |
| Flash MB | EMMC 8GB |

Here is a big difference. For OpenWrt and storage of packages, you are equipped with 8GB (8192 MB) storage. Compared to 256MB on OpenWrt One, this is a no-brainer.

| | |
| :-: | :-: |
| RAM MB | DDR4 1GB |

This device is equipped with 1GB of DDR4 RAM (1024MB), the same as OpenWrt One.

| | |
| :-: | :-: |
| USB ports | 1x 3.0 |

Compared to OpenWrt One, it has USB 3.0 as opposed to 2.0. That is a huge difference and quite a crucial aspect for people like me, who want to utilise it to connect a USB hard drive for network file storage.

| | |
| :-: | :-: |
| Ethernet 1Gbit ports | 1 |
| Ethernet 2.5Gbit ports | 1 |

Similar to OpenWrt One, it contains only 2 ports, WAN with 2.5Gbit and LAN with 1Gbit. As mentioned, I will probably require a switch to connect more devices in my network by wire, but that's not a problem after all (as mentioned earlier).

---

Brume 2 does not have any WiFi capability, but that's a benefit for me. As I mentioned at the beginning, with the current state of development of WiFi standards, if I want to move from WiFi 6 (OpenWrt One) to WiFi 7, I will just need to change my TP-Link RE700X rather than replace the whole OpenWrt router.

Interestingly, OpenWrt officially "just" added support to Brume 2 in the upcoming 24.10 where on [official website](https://www.gl-inet.com/products/gl-mt2500/) it stated that is working based on OpenWrt 21.02, which is probably directly modified by GL.iNet company for their devices.

I will not be interested in using their software and rather I would like to jump into their hardware once 24.10 becomes a stable version (expect to happen in the following weeks).

---

As mentioned earlier, when OpenWrt One was releaser, their creators wanted to create an All-In-One device compromising on components to maintain price range.

They added Wifi but sacrificed it with poor storage and a slow USB port. This landed them at a price tag of $89 (approx. £73) after virtually applying a 50% discount, on AliExpress, on the price that was never there!

Brume 2 is available in two versions, one in a plastic case and the other in aluminium alloy.

The aluminium alloy is a bit more expensive, costing £63.90 compared to ABS plastic, which ranges at £50.90 in [official store](https://store-uk.gl-inet.com/collections/security-gateways).

Going on budget, £50.90 (even £63.90) is a great price for such a piece of hardware. Even if you need to invest in a Wifi device (like the TP-Link RE700X that I got), still, for the long term, I found it a better approach than investing in OpenWrt One.

Once I decide to move away from WiFi 6 into WiFi 7, I will not  need to do anything with my OpenWrt device (Brume 2) and will just replace it with such devices:

- [RE800BE (BE19000 Tri-Band Wi-Fi 7 Range Extender)](https://www.tp-link.com/uk/home-networking/range-extender/re800be/)
- [RE655BE (BE11000 Tri-Band Wi-Fi 7 Range Extender)](https://www.tp-link.com/uk/home-networking/range-extender/re655be/)
- [RE550BE (BE9300 Tri-Band Wi-Fi 7 Range Extender)](https://www.tp-link.com/us/home-networking/range-extender/re550be/)

Or, being on budget, I will more likely look into:
- [RE235BE (BE3600 Dual-Band Wi-Fi 7 Range Extender)](https://www.tp-link.com/us/home-networking/range-extender/re235be/)

--- 

When I started thinking about replacing my RAC2V1K, I was also thinking about the power consumption of my current device. Prices of energy go up so badly, hence every watt saved is crucial.

RAC2V1K is powered by 12V DV 2.5A, the maximum peak usage is 30 watts.

Brume 2 uses a standard USB-C Charger rated at 5V 2A, which is 10 watts maximum needed for the device.

OpenWrt One utilised USB-PD at the rate of 15V 2A, that's 30 watts.

---

For now, I am not replacing anything yet, as I am waiting for the stable release of OpenWrt 24.10, but I have a plan already, of what to use (which device) for that purpose.

The year 2025 looks exciting already.

> The stable version of OpenWrt 24.10.0 has been [released](https://forum.openwrt.org/t/openwrt-24-10-0-first-stable-release/223845) on 6th of february 2025.


---
## My Stars of GitHub at the End of 2024
- **URL:** https://dariusz.wieckiewicz.org/en/my-stars-of-github-at-the-end-of-2024/
- **Date:** 2024-12-31
- **Tags:** github, github stars, wgcf, sniffnet, hugo, giscus, modern font stacks, google webfonts helper, minify, instant.page, ai.robots.txt, snow fall, country flag emoji polyfill, PowerToys, Microsoft Activation Scripts, WhyNotWin11, Files, WindowsAppsUnfukker, CapsLockIndicator, pdfsam, brew, Keka, cryptomator, Monolingual, mac-cleanup-py, marktext, maestral, Silicon, UTM, pika, Lockdown iOS, toolz, stats, AmazeFileManager, log2ram, jan, yt-dlp, YoutubeDownloader

### Content

GitHub is a great place to find some good resources and solutions. Whenever I need it personally or professionally, if the solution is really useful, I make sure to add a star to it.

I review my stars from time to time, and it wasn't any different on the 31st of December 2024.

By the end of 2024, I had accumulated the following, which are really worth looking at.

> The list is curated, and I pick the ones that are worth knowing for the following year, 2025.

<!--more-->

## Network

### [ViRb3 / wgcf](https://github.com/ViRb3/wgcf)

> 🚤 Cross-platform, unofficial CLI for Cloudflare Warp

**wgcf** is a shell script to register and generate credentials for Cloudflare Warp for use in the WireGuard app instead of the official app.

I have written a bit about it in my post about [Turbocharge your internet connection (WARP, IPv6, OpenWrt)](/en/turbocharge-your-internet-connection/).

### [GyulyVGC / sniffnet](https://github.com/GyulyVGC/sniffnet)

> Comfortably monitor your Internet traffic 🕵️‍♂️

Whenever I need to analyse network traffic, I reach for Wireshark first. However, in some instances, especially on macOS, when analysing traffic generated by specific apps, I prefer Sniffnet, mostly due to its simpler interface compared to Wireshark.

{{% ads-in-article %}}

## WebDev

### [gohugoio / hugo](https://github.com/gohugoio/hugo)

> The world’s fastest framework for building websites.

Hugo is a framework that builds all of my websites. From [private ones](/en/yummyrecipes-uk/) to professional [business websites](/en/andrews-fasteners-going-hugo/), this tool generates static websites that can handle increasing traffic without compromises. In the past, I struggled daily with WordPress and hosting resources, but since migrating to Hugo, all of that is behind me, and I have no intention of going back.

Of course, building sites with Hugo requires you to "think differently". However, once you understand it, you will quickly realise that these websites are not as "static" as they sound.

### [giscus / giscus](https://github.com/giscus/giscus)

> A comment system powered by GitHub Discussions. :octocat: 💬 💎

GitHub provides a solution for Discussions for all its repositories. It's a sort of community forum where people can discuss various topics. Giscus integrates Discussions into your website. This way, you have a great solution for a comments system that is easy, accessible, and offers a simple integration with static websites built with Hugo and other SSGs.

### [system-fonts / modern-font-stacks](https://github.com/system-fonts/modern-font-stacks)

> System font stack CSS organized by typeface classification for every modern operating system

Fonts on websites create a unique look for them. People, when interacting with them, get a feel for the website within the first seconds of it loading. Sometimes, when building websites, you may struggle with choosing the right font that looks good across the devices users are using. System Stack fonts allows you to serve a website that looks as close as possible to the system on which it is being browsed. If it's iOS, you'll notice that the system-wide font matches the website font. This creates a great user experience without the need to serve any extra resources to make it look "okay".

### [majodev / google-webfonts-helper](https://github.com/majodev/google-webfonts-helper)

> A Hassle-Free Way to Self-Host Google Fonts. Get eot, ttf, svg, woff and woff2 files + CSS snippets

While System Stack fonts have their benefits, there are some environments where we want to maintain the same visual experience for users, regardless of which device the website is opened on. [Google Fonts](https://fonts.google.com) are great tools for adding custom fonts to websites; however, they may negatively impact performance. Sometimes, loading fonts from Google's servers can take much longer than serving them from the same server as the website. Google WebFonts Helper is a handy tool that allows you to download Google Fonts and serve them with your website (or app) from the same origin, making it faster and easier to manage and maintain.

### [tdewolff / minify](https://github.com/tdewolff/minify)

> Go minifiers for web formats

This repository is a minifier written in the Go language. The main purpose of it is to re-process files (such as those used on websites and web apps) to remove unnecessary elements and make them smaller by replacing some variable names with simpler alternatives that use less space.

When I publish my website with [Hugo](https://github.com/gohugoio/hugo), I automatically minify all necessary files through it to improve website performance.

Even though I do not use this repository in my day-to-day work, it is crucial for me when re-processing my [Minimal Google Analytics 4 Snippet](/en/minimal-google-analytics-4-snippet/) before it is published. Using the [Online Demo](https://go.tacodewolff.nl/minify), I prepare a finished, minified version of the snippet that is not re-processed again later, avoiding various compatibility issues that may arise.

### [instantpage / instant.page](https://github.com/instantpage/instant.page)

> Make your site’s pages instant in 1 minute and improve your conversion rate by 1%.

This repository is a source of a great script that, when added to a website or web application, can significantly improve user experience when navigating between subpages of a website.

When you land on a website and want to follow a link from it, you typically hover over the link before clicking. With instantpage, the destination page is already preloaded as soon as you hover over the link. When you click the link, you are greeted with a fully loaded page without the need to wait for resources to load. This may sound minor, but on large sites, where users navigate beyond a single page, it helps serve content as quickly as possible. I actively use this on my [employer's website](https://andrewsfasteners.uk).

### [ai-robots-txt / ai.robots.txt](https://github.com/ai-robots-txt/ai.robots.txt)

> A list of AI agents and robots to block.

This repository is a community-collected list of identifiers for web crawlers associated with AI companies that use website content to train AI. If we don't want this to happen, we can incorporate some of the lines into our `robots.txt` file to limit their ability to use our content without explicit permission.

Even though following the rules in `robots.txt` is not mandatory, there are times when we may want to protect our own creativity, and this is where this repository helps in addressing that.

### [zachleat / snow-fall](https://github.com/zachleat/snow-fall)

> A web component to add snow to your web site (or to an element on your web site).

This is a simple festive addition to websites and web applications, allowing falling snow to be added to them. When we are all in a festive, pre-Christmas mood, it's nice to see that some websites share the same cheerful spirit as we do.

### [talkjs / country-flag-emoji-polyfill](https://github.com/talkjs/country-flag-emoji-polyfill)

> Add country flag emojis to Chromium-based browsers on Windows

When creating websites, I like to use country flags where possible, instead of loading unnecessary resources for something already built into most operating systems. I say most because, while this works well on Apple and Android devices — just like emojis — on Windows, for years, flags have been displayed as text like "PL" (🇵🇱) or "GB" for the flag 🇬🇧. This simple script helps to resolve this issue.

{{% ads-in-article %}}

## Windows

### [microsoft / PowerToys](https://github.com/microsoft/PowerToys)

> Windows system utilities to maximize productivity

PowerToys is a great and free Swiss Army knife from Microsoft. This app is a collection of mini-apps that enable various features in the system and help boost your productivity on a Windows machine. I actively use it in business for tasks such as batch renaming files, resizing images, preventing the device from going to sleep, or using a single keyboard and mouse across two separate Windows computers.

This tool is a must-have for those who don't want to waste time on unnecessary tasks and want to ensure their device works with them, not against them, throughout a productive day.

### [massgravel / Microsoft-Activation-Scripts](https://github.com/massgravel/Microsoft-Activation-Scripts)

> Open-source Windows and Office activator featuring HWID, Ohook, KMS38, and Online KMS activation methods, along with advanced troubleshooting.

Sometimes, despite having purchased all the necessary licences, Microsoft's activation servers can cause issues that are difficult to resolve. This script offers advanced troubleshooting solutions to help resolve such problems on users' computers.

_Of course, there may be other (less legitimate) uses for this script, but as I see it, Microsoft, on a platform they own (GitHub), doesn't seem to mind. Therefore, there is nothing against recommending it, just as with [alsyundawy / Microsoft-Office-For-MacOS](https://github.com/alsyundawy/Microsoft-Office-For-MacOS)._

### [rcmaehl / WhyNotWin11](https://github.com/rcmaehl/WhyNotWin11)

> Detection Script to help identify why your PC is not Windows 11 Release Ready. Now Supporting Update Checks!

This non-Microsoft tool is a great app to help you understand why your device cannot be updated to Windows 11 from Windows 10. As the end of life for Windows 10 is set for October 2025, this tool is a must for anyone who wants to know what changes (if possible) are needed to make their device ready for Windows 11.

### [files-community / Files](https://github.com/files-community/Files)

> A modern file manager that helps users organize their files and folders.

Windows Explorer is the default way of browsing files in the Windows operating system. However, more advanced users often use other tools to boost their productivity. I personally remember when [Total Commander](https://www.ghisler.com) was a must-have app for me. Files App is a modern equivalent of an advanced Windows Explorer, with a much more pleasant interface for (currently) younger advanced users who haven't experienced Norton Commander in DOS. This was back in a time when AI was just fiction from the *Terminator* movie, and many of them probably hadn't even been born yet.

### [AgentRev / WindowsAppsUnfukker](https://github.com/AgentRev/WindowsAppsUnfukker)

> PowerShell script to fix WindowsApps-related permission errors and crashes.

Recently, I helped someone whose Windows 10 device was affected by an issue with file and folder permissions. Despite performing repairs and reinstalls, I still struggled to get the Microsoft Store running, along with all the built-in Windows apps like Photos.

It was a very annoying issue, and I spent far too much time trying to resolve it. This app helped me restore all permissions to their proper state, and everything started working correctly, including the ability to install and run newly installed apps from the Microsoft Store.

It was an incredibly frustrating issue, but this tool was fantastic in resolving it. I still feel the frustration I experienced when things weren’t working, and I completely understand why this app includes "unfukker" in its name. Totally understandable!

### [jonaskohl / CapsLockIndicator](https://github.com/jonaskohl/CapsLockIndicator)

> A small utility that indicates the state of the Num lock, Caps lock and Scroll lock key.

When working on multiple screens and you don’t have time to look at the keyboard to check if CapsLock or NumLock is turned on, you might want some sort of visual prompt about their status. Sometimes, you may also have keyboards without an LED indicator for the CapsLock state, making it really hard to guess whether you are typing in capitals or not. This simple, yet customisable and free app adds the ability to provide visual notifications when certain system keys are pressed and includes a tray icon to quickly show what is active and what’s not.

### [torakiki / pdfsam](https://github.com/torakiki/pdfsam)

> PDFsam, a desktop application to split, merge, mix, rotate PDF files and extract pages

I work with PDF files on a daily basis. Sometimes, I need to rearrange, split, remove, or extract pages from them. Without needing to invest in Adobe Acrobat, I can complete these tasks effortlessly using PDFsam. It's a great tool for users who want to maximise their productivity without spending extra money on software that doesn't offer good value for money.

{{% ads-in-article %}}

## Apple

### [Homebrew / brew](https://github.com/Homebrew/brew)

> 🍺 The missing package manager for macOS (or Linux)

If you’ve ever used Linux, like Debian or Debian-based distributions, with the terminal and installed apps using `apk`, you know how great this tool is.

In macOS, most apps are installed using specific installation packages downloaded from developers' websites. Sometimes, you can find them in the App Store; however, the macOS App Store is far from perfect as plenty of software simply isn’t available there.

Apple’s system for computers isn’t as locked down as iOS and iPadOS, so you can install the apps you need rather than relying solely on what’s available in the App Stores.

If you want to extend the functionality of your operating system, you’ll often turn to the Terminal, where you can run more advanced apps. This is where Brew comes in handy. Once added to the system, it extends the library of available software, which can be installed with just a simple command.

It reminds me of `apk`, but in the macOS environment.

You’ll start your experience with [brew.sh](https://brew.sh) rather than this repository, but it certainly deserves a star on its own.

### [aonez / Keka](https://github.com/aonez/Keka)

> The macOS & iOS file archiver

Just as Windows had compressors and decompressors like WinZip and WinRar in the past — until basic compression and decompression features were built into the system itself — macOS also has its own decompressor and compressor.

However, these basic tools are limited in functionality. To extend this, I use [7zip](https://www.7-zip.org) in the Windows environment. Although 7zip is not officially available for macOS, Keka is the closest alternative, offering a nice interface with all the options needed to achieve what you require.

### [cryptomator / cryptomator](https://github.com/cryptomator/cryptomator)

> Cryptomator for Windows, macOS, and Linux: Secure client-side encryption for your cloud storage, ensuring privacy and control over your data.

Cryptomator is a great tool that allows you to store encrypted files in various cloud storage services without the risk of them being intercepted or scanned by third parties, or their content being leaked.

By creating a folder with a master password and key, all items inside are saved in encrypted form. When accessed directly, they appear as gibberish files, but when opened through Cryptomator, they reveal their content.

A great tool for storing highly sensitive data.

### [IngmarStein / Monolingual](https://github.com/IngmarStein/Monolingual)

> Remove unnecessary language resources from macOS.

A handy tool to remove unnecessary languages and resources from macOS, helping to regain some precious disk space.

This tool may not be needed for the average user. However, if you're running low on space, alongside other tools like [OnyX](https://www.titanium-software.fr/en/onyx.html), this is a good place to start.

### [mac-cleanup / mac-cleanup-py](https://github.com/mac-cleanup/mac-cleanup-py)

> 👨‍💻 Python cleanup script for macOS

Mac-Cleanup is another cleaning utility installed via Brew and run through the terminal. It allows you to remove a lot of junk from your computer that simply takes up space unnecessarily.

### [marktext / marktext](https://github.com/marktext/marktext)

> 📝A simple and elegant markdown editor, available for Linux, macOS and Windows.

I like Markdown for its simplicity and compatibility. With simple elements, you can write text in a Markdown-compatible format even using a notepad, but true Markdown editors reveal the full potential of Markdown.

I use Markdown for the content of my websites built with Hugo, as well as for writing drafts before processing them into their final format.

In my day-to-day editing, I use [iA Writer](https://ia.net/writer). However, this is a paid solution, and if you want to save some money, Marktext is an editor worth starting with.

### [samschott / maestral](https://github.com/samschott/maestral)

> Open-source Dropbox client for macOS and Linux

If you're using Dropbox, you're probably using its client app to sync files with your computer. When I switched to an Apple Silicon MacBook, I struggled with the official client, which lacked native support and drained resources excessively. While this has improved over the years, I decided to switch to something much simpler, that works natively and doesn’t excessively consume system resources. Maestral is a lightweight Dropbox client designed to sync the files you need on your Mac.

### [DigiDNA / Silicon](https://github.com/DigiDNA/Silicon)

Silicon is a simple app that scans your system applications to identify which ones are natively compatible with Apple chips and which ones are running through emulation for Intel apps. Apps that haven’t been optimised typically use more resources than necessary, as emulation requires extra computing power, which also impacts battery life. This app quickly lets you know which apps you should update or replace with properly compatible ones to maintain your device's performance and battery life at the optimal level throughout your productive day.

### [utmapp / UTM](https://github.com/utmapp/UTM)

> Virtual machines for iOS and macOS

UTM is a free emulation software that allows you to run various operating systems on macOS. I used it as [an alternative to Parallels Desktop to run Windows 11](/en/installing-windows-11-macos-apple-mac-m1-utm/) and recommend it to anyone who wants to explore the emulation route. Although I am not actively using UTM anymore, as I switched to VMware Fusion once it became free for home users, I still keep it installed and use it as my first choice whenever I need to emulate a Linux system within macOS.

### [superhighfives / pika](https://github.com/superhighfives/pika)

> An open-source colour picker app for macOS

Pika is a simple colour picker that includes extra features such as a Contrast Ratio checker, WCAG Compliance meter, and a converter between different colour formats. A simple yet very handy tool, it is a must-have for anyone working with graphics and/or websites.

### [confirmedcode / Lockdown-iOS](https://github.com/confirmedcode/Lockdown-iOS)

Lockdown is my favourite app for iOS to block system-wide ads. I use it to block intrusive ads in games that are overloaded with them, often making you want to give up and uninstall the game rather than continue and watch them.

I wrote more about it in my post [Firewall for iPhone, iPad and Mac - Lockdown Privacy](/en/firewall-iphone-ipad-mac-lockdown-privacy/).

### [d3ward / toolz](https://github.com/d3ward/toolz)

> Easy-to-use interface and extensive collection of testing tools for optimizing performance and user experience.

This repository is a place to test how effective your AdBlocker is. Regardless of which one you are using, after a [short test](https://d3ward.github.io/toolz/adblock), you can see how good or bad it performs and decide if it’s time to choose something better.

### [exelban / stats](https://github.com/exelban/stats)

> macOS system monitor in your menu bar

Stats is a handy tool for adding useful statistics to the macOS menu bar. I personally use it to display disk space, network activity, and battery status with more detailed information than what is provided by the system.

## Android

### [TeamAmaze / AmazeFileManager](https://github.com/TeamAmaze/AmazeFileManager)

> Material design file manager for Android

Even though I don't use the Android system every day, when I need to, especially when working with files, Amaze File Manager is the file manager app I turn to first.

{{% ads-in-article %}}

## Linux

### [azlux / log2ram](https://github.com/azlux/log2ram)

> ramlog like for systemd (Put log into a ram folder)

When creating custom solutions with Raspberry Pis, I occasionally encounter situations where the SD card or USB memory stick becomes corrupted. Without a proper backup, I could face hours of work to restore everything as it was. The problem with Raspberry Pi OS (previously called Raspbian) is that it writes extensively to local storage. With a Raspberry Pi and a larger RAM size, we can utilise device memory to store certain logs that don’t need to be preserved for a long period of time. This handy utility helps with that and prevents our storage from degrading.

## AI

### [janhq / jan](https://github.com/janhq/jan)

> Jan is an open source alternative to ChatGPT that runs 100% offline on your computer. Multiple engine support (llama.cpp, TensorRT-LLM)

If you are looking to run AI, like ChatGPT, locally on your computer and offline, Jan is a good place to start. Although I am not using it extensively yet—since Apple Intelligence and ChatGPT are leading the game—it’s nice to know that there is an alternative.

## YouTube

### [yt-dlp / yt-dlp](https://github.com/yt-dlp/yt-dlp)

> A feature-rich command-line audio/video downloader

When I wanted to download a clip from YouTube, I struggled to find a decent solution. Most online downloaders are terrible—filled with ads, attempting to steal your data, and rarely offering the ability to download in the highest resolution without paying extra.

Yt-dlp comes to the rescue. It can be run locally in the terminal and does exactly what it’s intended to do.

### [Tyrrrz / YoutubeDownloader](https://github.com/Tyrrrz/YoutubeDownloader)

> Downloads videos and playlists from YouTube

YoutubeDownloader is another great solution for downloading clips from YouTube. While it can be run from the terminal, it presents you with a GUI (Graphical User Interface) afterwards, making it much easier for people to use.

----

And that's all.

I hope you find something useful here as well. If you do, drop a star on the relevant repository and let its creators know that their work is highly appreciated.


---
## RCS on iPhone with iOS 18.2 - Hopes Restored
- **URL:** https://dariusz.wieckiewicz.org/en/rcs-on-iphone-with-ios-18-2-hopes-restored/
- **Date:** 2024-12-20
- **Tags:** RCS, iMessage, Apple, iOS 18.2, GiffGaff

### Content

The announcement of RCS support on iPhone with iOS 18 was a very big disappointment for me, as I mentioned in my [earlier post](/en/rcs-on-iphone-with-ios-18-lost-hopes/); however, in recent days, the situation has changed.

<!--more-->

With iOS 18.2, most major networks in the United Kingdom rushed to announce that, with this update, compatible devices can now enjoy messaging with Android users using RCS technology.

It came as a surprise to me, as during the pre-Christmas period, I missed a post on the GiffGaff Community titled [RCS services between iPhone and Android is here](https://community.giffgaff.com/d/34221681-rcs-services-between-iphone-and-android-is-here).

I discovered this when I decided to send a text message to one of my friends, and it suddenly appeared as Text Message - RCS.

I rushed to check the settings for Messages and noticed that, indeed, I had RCS Messaging enabled. Yuppie!

Together with widely enabled WiFi Calling on GiffGaff, RCS also works when you are in a spot where the reception is poor, but you still have access to the internet over WiFi.

For me, this came as an early Christmas gift as well as a great birthday present, as I noticed it on the 20th of December!

Apple [keeps track of what features](https://support.apple.com/en-gb/108048) are available on their phones based on which provider the user is using. Despite the fact that these updates are not too frequent — for example, in the United Kingdom, RCS is not listed for O2/GiffGaff (even though it is for O2 in other countries, like Germany) — it's nice to know that information like this is shared between members of the network.

What's important is that when an iPhone is updated to iOS 18.2 and the network has enabled RCS, this feature will be enabled by default, so the user doesn't need to do anything extra.

Despite some networks in the United Kingdom trying to persuade users with cheap plans that last only a few months, GiffGaff continues to hold steady. They know they are offering value for money and are thinking long-term about the sustainability of their business and services, rather than chasing quick pre-Christmas gains like some other loss-making virtual operators in the UK.


---
## Securing DNS Traffic on Windows 11 with Cloudflare for Families
- **URL:** https://dariusz.wieckiewicz.org/en/securing-dns-traffic-on-windows-11-with-cloudflare-for-families/
- **Date:** 2024-11-23
- **Tags:** Windows 11, 1.1.1.1, DNS over HTTPS, DoH, Cloudflare, Cloudflare for Families, DNS, encrypted DNS

### Content

Cloudflare's DNS service, known as 1.1.1.1, has transformed the internet for the better and continues to make a significant impact every day.

From setting DNS on your device to installing the dedicated app for using WARP technology, you can make your connections faster by choosing optimised routes for traffic.

If you are an advanced user, you can secure your entire network at home or in the workplace by implementing Cloudflare technology [at your router](/en/secure-dns/).

For some users, this may feel too overwhelming.

Windows 11 introduced built-in integration for Secured DNS (Encrypted) that can be implemented at the interface level (your network card, whether wired or wireless). Thanks to this, all the DNS requests going through it will be encrypted.

<!--more-->

Cloudflare offers the so-called [1.1.1.1 for Families](https://one.one.one.one/family/), which, with additional DNS addresses, allows you to implement unmanaged protection against malware or even add adult content blocking alongside malware protection.

[![Options — Cloudflare DNS for Families](Options_Cloudflare_DNS_for_Families.png)](Options_Cloudflare_DNS_for_Families.png)

In addition to providing specific addresses for malware and adult content blocking, they also provide [instructions](https://developers.cloudflare.com/1.1.1.1/setup/windows/#windows-11) on how to implement this on a Windows 11 device. Still, there is one crucial addition that I would like to highlight — encryption.

Even the shortest and simplest instruction may not help without visual input, so let’s go through adding this setting with some images.

## Set up in Windows 11

> Based on Windows 11 (24H2)

1. Click on the **Start menu** and select **Settings**.

[![Windows 11 - Start menu - Settings](Windows_11_encrypted_DNS_123546.png)](Windows_11_encrypted_DNS_123546.png)

2. Go to **Network & internet**.

[![Windows 11 - Network & internet - Ethernet](Windows_11_encrypted_DNS_123621.png)](Windows_11_encrypted_DNS_123621.png)

3. Click the **Edit** button near the **DNS server assignment** section.

[![Windows 11 - DNS server assignment - Edit button](Windows_11_encrypted_DNS_123636.png)](Windows_11_encrypted_DNS_123636.png)

4. Change the **Automatic (DHCP)** option to **Manual**.

[![Windows 11 - Edit DNS Settings - Automatic (DHCP)](Windows_11_encrypted_DNS_123654.png)](Windows_11_encrypted_DNS_123654.png)

5. Switch the toggle **On** for **IPv4** and type the desired DNS server in **Preferred DNS** as well as **Alternative DNS**.

[![Windows 11 - Edit DNS Settings - Manual - Off](Windows_11_encrypted_DNS_123706.png)](Windows_11_encrypted_DNS_123706.png)

{{< details-summary "Use 1.1.1.1 resolver" >}}
```
1.1.1.1
1.0.0.1
```
{{< /details-summary >}}

{{< details-summary "Block malware with 1.1.1.1 for Families" >}}
```
1.1.1.2
1.0.0.2
```
{{< /details-summary >}}

{{< details-summary "Block malware and adult content with 1.1.1.1 for Families" >}}
```
1.1.1.3
1.0.0.3
```
{{< /details-summary >}}

[![Windows 11 - Edit DNS Settings - Manual - IPv4 On](Windows_11_encrypted_DNS_123733.png)](Windows_11_encrypted_DNS_123733.png)

6. Change the setting of **DNS over HTTPS** from **Off** to **On (automatic template)**.

As you will see, the template below will be filled with the relevant data for the Cloudflare service.

{{< details-summary "For 1.1.1.1 resolver" >}}
```
https://cloudflare-dns.com/dns-query
```
or
```
https://one.one.one.one/dns-query
```
{{< /details-summary >}}

{{< details-summary "For Block malware with 1.1.1.1 for Families" >}}
```
https://security.cloudflare-dns.com/dns-query
```
{{< /details-summary >}}

{{< details-summary "For Block malware and adult content with 1.1.1.1 for Families" >}}
```
https://family.cloudflare-dns.com/dns-query
```
{{< /details-summary >}}

[![Windows 11 - Edit DNS Settings - Manual - IPv4 On with DNS over HTTPS template](Windows_11_encrypted_DNS_123814.png)](Windows_11_encrypted_DNS_123814.png)

> If your network uses **IPv6**, follow the same steps for that protocol.

7. Switch the toggle **On** for **IPv6** and type the desired DNS server in **Preferred DNS** as well as **Alternative DNS**.

{{< details-summary "Use 1.1.1.1 resolver (IPv6)" >}}
```
2606:4700:4700::1111
2606:4700:4700::1001
```
{{< /details-summary >}}

{{< details-summary "Block malware with 1.1.1.1 for Families (IPv6)" >}}
```
2606:4700:4700::1112
2606:4700:4700::1002
```
{{< /details-summary >}}

{{< details-summary "Block malware and adult content with 1.1.1.1 for Families (IPv6)" >}}
```
2606:4700:4700::1113
2606:4700:4700::1003
```
{{< /details-summary >}}

> If you select **On (automatic template)** for the **IPv6** connection and the **template** is not automatically populated, it means your network connection may lack proper communication over IPv6, and you may not be able to set this. In that case, keep the IPv6 toggle turned **Off**.

Click **Save** to apply the changes.

If everything is done correctly, you will see that your DNS is set to use Cloudflare's service and, additionally, it’s encrypted, as shown below:

[![Windows 11 - IPv4 DNS Servers - Encrypted](Windows_11_encrypted_DNS_124414.png)](Windows_11_encrypted_DNS_124414.png)

---

If you selected just the **1.1.1.1** DNS servers, your requests will be encrypted and optimised.

If you choose the **Security** option with the **1.1.1.2** servers, your traffic will also be filtered for potential malware.

For the **Family** option **1.1.1.3**, in addition to filtering malware, you will implement a block for adult content.

---

And just like that, without installing any extra software, we’ve made changes to the entire system to make our traffic more secure.

In the above example, we implemented the change for our **Ethernet** network card (wired). For most users, this will be applied to **Wireless**, but it’s worth applying this to all interfaces available.

---

To verify that encrypted DNS is working, simply head to [one.one.one.one/help](http://one.one.one.one/help/), where after a short analysis, you should see a response of **Yes** under **Using DNS over HTTPS (DoH)**.


---
## Bluesky — Embracing Change and Domain as Your Handle
- **URL:** https://dariusz.wieckiewicz.org/en/bluesky-embracing-change-domain-as-your-handle/
- **Date:** 2024-11-17
- **Tags:** Bluesky, AT Protocol, ATProto, domain handle, custom username

### Content

When Jack Dorsey departed from Twitter, it was passed into the greasy hands of another billionaire who turned it into a cesspool.

I don’t have anything against billionaires. Let them have their money; just do good with it, not harm. This reminds me of the meme that rings true for every hard-working person:

> “Most people don’t want to be rich. They just want enough money to not worry anymore.”

<!--more-->

I [ended my experience with this platform in December 2022](/en/enough-is-enough-bye-twitter/) and stuck to places that do not contribute to anxiety or negatively impact my mental health.

A lot of people felt the same and moved to Mastodon instances or Facebook-owned (Meta) Threads.

Luckily, the Meta team still care about some kind of moderation of the rubbish people publish there. Hence, with the right type of followers, you may only see things you want to read or view.

> This may start to change in the near future, as Meta has already announced that they are planning to implement ads into the feeds. Consequently, things may become as unpleasant as they currently are on Facebook.

In my case, this excludes the Facebook platform itself, as their main platform pisses me off daily with its terrible recommendations, time-stealing reels, and ads in every other post.

There is so much rubbish happening on Facebook that I rarely see posts from my friends in my group. Because of that, I use it for specific things and try not to spend too much time there, as it can easily pull me into a rabbit hole. Before I realise it, I’ve lost an hour of my time in this world.

With our limited time here, I’ve started to care a bit more — especially since I [turned 40](/en/milestone-reached---40/) — about what is truly important in life.

Going back to the beginning.

Jack Dorsey, when he decided to start Bluesky, reminded me of another meme that recently crossed my path:

> “Don’t be afraid to start over. This time, you’re not starting from scratch; you’re starting from experience.”

I must admit, with all the chaos happening in America recently — and what will continue to unfold over the next four years — we’ve noticed another wave of well-meaning people ending their experience with “X” (formerly Twitter).

We saw the first exodus of users back when Starman took over, and now we’re seeing another wave as chaos reigns on the platform.

This time, people are joining Bluesky, and it’s not just lesser-known individuals. Companies like Australian Airlines are seizing the opportunity to leave toxic environments with a clever twist (“We took a moment to locate our nearest X-it”). Even major news organisations, such as *The Guardian*, have realised that the platform’s environment no longer aligns with their values.

Despite being on Threads as well, I decided to join Bluesky to see how Jack’s “experience” will serve the greater good and, hopefully, bring an end to the dead bird once and for all.

{{% ads-in-article %}}

When I created my account, I chose my username, which was attached to the domain **.bsky.social**, creating so-called “handles” like **@idarek.bsky.social**.

Shortly after, an article in my feed caught my eye about the possibility of using my domain as a handle (username). It’s a good way to be found on the platform and to verify oneself without paying for a ridiculous blue tick.

In less than two minutes, my handle — under which you can find me on the platform — changed from *@idarek.bsky.social* to **@dariusz.wieckiewicz.org**. This was all thanks to the implementation of the [AT Protocol](https://en.wikipedia.org/wiki/AT_Protocol) in Bluesky.

You can become recognised and validated on the Bluesky platform without creating your own server or instance (as in Mastodon).

For those who have decided to make Bluesky their new home and who own their domain, this should be the first step on their to-do list.

With a simple step of adding a TXT record to your domain’s DNS configuration, someone like Stephen King (**@stephenking.bsky.social**) could be found as *@stephenking.com*.

The entire process of changing your “handle” to use your domain is explained in [How to set your domain as your handle](https://bsky.social/about/blog/4-28-2023-domain-handle-tutorial).

If you scroll to the section **How do I set this custom domain as my handle?** You’ll see instructions for initiating a change of handle to your domain by adding a `_atproto` TXT record with a unique value (key).

After pressing the verification of DNS records button, most DNS providers will quickly allow an update, and you will be able to see yourself under the new handle on the platform.

[![Bluesky with custom domain handle](dariusz_wieckiewicz_org_bluesky.png)](dariusz_wieckiewicz_org_bluesky.png)

Of course, you’ll need access to edit the DNS records for your domain. I’ve been advocating for years that if you ask someone to create a website for you, you should always ensure that the domain is registered in your name. The path may diverge down the road, and controlling these essential assets will help you avoid significant hurdles when you decide to go in a different direction.

I must admit, this feature will likely boost the platform’s popularity. Hopefully, it will be the final nail in the coffin for the dead bird — the rotting corpse that should have been buried long ago.


---
## RCS on iPhone with iOS 18 - Lost Hopes
- **URL:** https://dariusz.wieckiewicz.org/en/rcs-on-iphone-with-ios-18-lost-hopes/
- **Date:** 2024-09-18
- **Tags:** RCS, Google Messages, iMessage, Apple, iOS 18

### Content

I have been waiting patiently for the release of a new version of iOS mainly because of one feature – RCS.

> _RCS stands for **Rich Communication Services**. It is an upgrade to traditional SMS messaging, designed to enhance the messaging experience with features like read receipts, typing indicators, high-resolution images, group chats, and sharing larger files. RCS aims to provide an experience similar to messaging apps like WhatsApp or iMessage but integrated into the default SMS app on smartphones._

The main reason I have been looking forward to RCS was the ability to send messages to Android users, other than SMS, but still from the default Messages app.

RCS brings reactions, the ability to send pictures (replacing the outdated MMS service), and shows read receipts. Everything is standard when communicating between iPhone users using the iMessage service.

With the high popularity of WhatsApp, which filled the void and struggle when communicating between Android and iPhone users, RCS was meant to regain the market for native messaging apps.

<!--more-->

I saw how RCS worked on my friend's Android devices but didn't realise at the time that it was only because of Google's implementation of RCS in their Google Messaging app (an app that is not available for iPhone users).

RCS can be implemented by the carrier, but if it is not, Google comes to the rescue for Android users.

Updating to iOS 18 gives the ability for RCS, but that doesn't mean anything for its users when carriers do not support it.

In the UK, almost none of the carriers support RCS. Even with iPhones running iOS 18, we still will not have the ability to use this technology.

> There is some feedback from users that RCS works on EE with iPhones running iOS 18, but it is difficult to find official confirmation of this.

In the UK, the implementation of new technologies in mobile networks always comes with big delays. No surprise that, in waiting for RCS, we will end up disappointed.

Google recently advised that they are [working on RCS encryption between Android and iPhone](https://9to5google.com/2024/09/17/rcs-encryption-android-iphone-work/).

The easiest solution would probably be to bring the Google Messages app to iPhone, but this would just be another app. Convincing users to switch from WhatsApp will not be so easy.

> Knowing how good Google is at killing their apps, they will probably remove it simply because the winner on the market is WhatsApp. Beating it in an iOS environment is not something Google will be interested in.

On Android, when we install Google Messages, the app is integrated into the system. It inherits the functionality of sending and receiving text messages (SMS), making it a single place for users to communicate on their phones.

Google bypasses the lack of native support for RCS by carrier operators by operating their own RCS server.

It's like Apple that is operating the iMessage service, where communication between iPhone users is done over Apple servers and has nothing to do with mobile operators.

> Apple has not implemented iMessage in the Android environment for years, so it's doubtful that Google would bother to bring Google Messages and RCS over their servers to iPhones.

The simplest solution would be for Apple to open their own RCS server or simply integrate RCS into the iMessage service for the convenience of their users.

This, however, will not happen anytime soon. No surprise that Apple didn't mention RCS as a big feature in their slides at the Apple Event but just pushed it as a "mention" on a board of iOS 18 features coming to iPhone.

The official website for [iOS 18](https://www.apple.com/uk/ios/ios-18/) prominently refers to adding support for RCS messaging.

> _RCS (Rich Communication Services) messages bring richer media and delivery and read receipts for those who don’t use iMessage._

This, however, is only available if mobile carrier operators support it.

This should have been implemented in iMessage in the first place, but with the above statement, Apple acknowledges that not all users choose to enable the iMessage service.

In the Google ecosystem, things are slightly different, and some functions are enabled "for us" whether we want them or not. Apple looks at privacy from a different perspective than Google, hence their different approach to this matter.

In summary, iOS 18 brings support for RCS, but in the UK, we can forget about it until someone (carrier operators, Apple directly, or even Google) spends the energy to make it work for everybody, not just a few.

P.S.

Some people, when asked [Is Apple going to end the ‘green bubble dread’?](https://www.govtech.com/question-of-the-day/is-apple-going-to-end-the-green-bubble-dread), answered loudly **Yes!**, but my answer to that is a simple **no**.


---
## How to Remotely Reboot Yealink VoIP Phones
- **URL:** https://dariusz.wieckiewicz.org/en/how-to-remotely-reboot-yealink-voip-phones/
- **Date:** 2024-08-03
- **Tags:** Yealink, Yealink VoIP, Remote Reboot, Remote Commands, Phone Reboot, Provision, Cron, Curl, Scheduler

### Content

Recently, I have been required to find a method of manually rebooting user phones on the company network. From time to time, once they are up and running, we discover that some features are causing problems. Sometimes we cannot transfer calls, or we do not hear the person we are talking with. The causes may be numerous, but most of the time, a simple reboot of the phone solves the issues.

The problem with rebooting user phones is that the computers they are using are connected to the internet using LAN cables (for stability). The network cable is connected directly to the phone socket and then goes from the phone to the user's computer. This saves the need for using two LAN cables; however, once the phone is restarted, the built-in switch is also restarted, hence the network connection is interrupted.

We have some apps that, when they lose network connections, will lock users and require additional action to unlock them. Hence, it is not ideal to restart the phones throughout the day.

As I checked the phones and settings, I struggled to find a simple scheduler to perform the task of restarting phones overnight, so I needed to find a different way.

<!--more-->

Before you start, you need to know the admin password for your phone web panel. The admin password is typically set by the provider and rarely shared. However, they can also set a user password that will allow us to execute some commands.

Luckily, I got access to the admin and user password and confirmed that the method described below works for both.

Each VoIP phone, when connected to the network, downloads provider settings. These settings are called provisions.

To allow remote reboot, you may set one option through the phone web panel. However, this simple setting has one drawback, which I will describe. Because of this, by working with your provider, you can ask your supplier to add three configuration lines to the provision, which will allow you to swiftly reboot phones without issues. I will describe that as well.

Let’s begin.

## Web Panel

> This step requires admin access; however, you may skip it and go to the [provision configuration](#provision-configuration) section.

Log in to your phone web panel at `https://yourPhoneIPAddress`. You can find your local phone IP address by pressing the `OK` button on the keypad.

By going to the **Features** section, you will find an option for **Remote Control**.

[![Yealink T42U - Web Panel - Features - Remote Control](Yealink_T42U_Features_Remote_Control.png)](Yealink_T42U_Features_Remote_Control.png)

In the field `Action URI Allow IP List`, you can specify the IP addresses that are allowed to send remote control commands, such as the reboot command. You can either specify `any` (to allow commands from any IP) or limit it to specified IP addresses in the local network, such as `192.168.0.*` (with the asterisk allowing commands from any IP within that range).

By pressing the blue `Confirm` button, we will apply this to the phone.

By adding this option, we are already able to send commands to our phone; however, this solution is not perfect.

The first time we send a remote command to the phone, a message will appear on the phone screen asking _"Allow remote control?"_ to permit the execution of remote commands.

We can choose to answer "Yes" or select "Block."

The problem is that if you have phones spread across the company, this means that, the first time you execute a remote command, you will need to physically click the approval button on each phone.

Once you confirm, any further remote commands will be executed without the need for additional confirmation.

This solution is not ideal; it would be better if we could perform this action without bothering our users or needing to physically access the phone.

Here is where your VoIP service provider can help: by adding three simple lines to the configuration (provision) that will be pushed to each phone.

## Provision Configuration

To allow remote execution of commands on user phones, we can ask our provider to add the following three lines to their provision file. This should not be a problem for them, as it does not affect their end at all.

```
features.action_uri.enable = 1
features.show_action_uri_option = 0
features.action_uri_limit_ip = 192.168.0.*
```

The `features.action_uri_limit_ip` setting, as explained in the [previous point](#web-panel), specifies the allowed IPs that can execute the command. In this case, it allows the entire network.

The `features.action_uri.enable` line is a generic setting that allows the execution of remote commands.

The `features.show_action_uri_option` setting removes the prompt/notification from the user's phone asking **"Allow remote control?"**.

With that in place, you can execute remote commands without needing physical access to the device. For this purpose, you can use the command in the following section.

## Reboot Script

To reboot the phone remotely, you need to execute the following command:

**As an admin user:**
```
https://admin:adminpassword@192.168.0.111/servlet?key=Reboot
```

**As a normal user**
```
https://user:userpassword@192.168.0.111/servlet?key=Reboot
```

> Where `192.168.0.111` is replaced with the phone's IP address.

There are a couple of ways to execute those commands.

You can simply paste it into a browser and visit it like any ordinary URL.

> You may be required to accept an untrusted local certificate the first time you visit the URL.

You can implement it into the scheduler on your network devices.

{{% ads-in-article %}}

For example, I use an OpenWrt router with cron functionality, which allows me to schedule commands to be executed at specific times throughout the day or night.

**Crontab**
```
00 6 * * 2-5 /bin/sh /root/voip_restart_phones
```

This command will run a script called `voip_restart_phones` at 6 AM from Monday to Friday.

**voip_restart_phones**
```
curl -l -s https://user:userpassword@192.168.0.111/servlet?key=Reboot
```

The file will contain a command for each phone that needs to be rebooted, with one command per line, specifying the IP address of each phone.

> You may need to set execution rights for the file using `chmod +x voip_restart_phones`.

---

> If you receive a **403 - User level forbidden** response during execution, it means that remote command execution is not enabled. Check the previous steps to ensure that you or your provider have configured everything correctly. Restart your phone to apply the latest provision and try again.

## Passwords with special characters

Sometimes passwords contain special characters. For example, `p@ssword`.

While it is not a problem to execute the command `https://user:userp@ssword@192.168.0.111/servlet?key=Reboot` in a web browser, you may encounter issues when trying to do this in the shell (bash).

In that case, you need to replace special characters with their [URL-encoded equivalents](https://www.w3schools.com/tags/ref_urlencode.ASP). For example, the symbol `@` becomes `%40`.

For example:
```
curl -l -s https://user:userp%40ssword@192.168.0.111/servlet?key=Reboot
```

This should work without any problems.

----

This way, by remotely rebooting phones, I resolved some network issues that occurred throughout the day.

Of course, to do this, you need to know the IP addresses of your phones. This is why it’s worth assigning static IPs to them based on their MAC addresses from the start.

Regards.


---
## When iPhone Battery Health is Lying to You, Help Yourself
- **URL:** https://dariusz.wieckiewicz.org/en/when-iphone-battery-health-is-lying-help-yourself/
- **Date:** 2024-07-10
- **Tags:** iphone, apple, battery health, battery stats, applecare, battery life, analytics data, cycle count

### Content

The phone I am using daily is an iPhone 13 Pro Max, which has been with me for almost 3 years. At the same time, when I got mine, I also got an iPhone 13 for my wife.

Straight after purchase, I opted for AppleCare+ with the monthly payment option. Thanks to the recurring payments, my device is still covered under AppleCare+.

I am considering an upgrade later this year, possibly in September 2024, but I am not rushing into it. My phone is performing well for its age and is still in pristine condition, which is important for potential resale value. The only thing that is showing signs of age is the battery.

After over 33 months of daily use, I started noticing that the battery is not as good as it used to be. With the built-in Battery Health feature, I can see that it's at 87% of design capacity. It's not bad for its age.

However, after the same period with her iPhone 13, my wife began to notice that her phone needed to be plugged in much more often.

Recently, we even noticed that the battery surprisingly jumped from 59% to 61%, only to return to 59% shortly after.

This made me start thinking, so I quickly checked her battery health. From `Settings > Battery > Battery Health & Charging`, we can see that her health is at 80%.

It's not a bad result after over 33 months, but also not great from the customer's point of view, especially when you got AppleCare+ purchased.

According to AppleCare+ terms regarding the battery, you are entitled to have your battery replaced free of charge when it falls below 80%.

Exactly, it states "below" 80%, which currently you may think is not met, as the battery health in settings shows exactly 80%.

**But what if that value is inaccurate?**

<!--more-->

I recently came across a podcast that I am not actively subscribed to. The podcast from Macworld was titled "[The mystery of iPhone battery life, solved!](https://www.macworld.com/article/2382769/macworld-podcast-the-mystery-of-iphone-battery-life-solved.html)" and it caught my eye. I decided to listen to it.

The podcast itself did not provide me with much new knowledge that I didn't already know, but it was worth listening to from one perspective. They mentioned a [Shortcut for Battery Stats](https://www.icloud.com/shortcuts/4948452c737d4b23887506294a03dfc9) that, when run, can read iPhone analytics data to provide precise information about battery health.

This shortcut is very useful for seeing how many charging cycles we have on our phones. The feature is visible for users of iPhones 15, but previous iPhone users cannot access it from a simple menu in Settings, which is a bit illogical.

I decided to give it a try and see what this handy shortcut can do, bearing in mind that Apple Support reads data about the battery condition in a similar manner, not solely relying on what is displayed in Settings.

Before I explore my findings, let's take a look at how to use this shortcut.

---

Once you add the shortcut to your Shortcuts (simply follow [this link](https://www.icloud.com/shortcuts/4948452c737d4b23887506294a03dfc9) and add it), you will need to go into your iPhone Settings to use it.

**You cannot run it as a standalone shortcut**, as it does not work that way. The shortcut requires input data to analyse and provide information in a human-readable form.

To use it, you go to `Settings > Privacy & Security` and scroll down to `Analytics & Improvements`. From there, you will find the option `Analytics Data` where you can proceed further.

[![List of analytics files in the Analytics Data menu on iPhone](Analytics_Data_list.png)](Analytics_Data_list.png)

This menu contains a collection of various analytics files, from which we will only focus on the most recent ones (sorted by date in the filename, not the order) that begin with the word Analytics. I observed that when plugging into the charger before bed, a new file is generated and is ready to be analysed the next morning.

> You may need to have "Share iPhone Analytics" turned on for some data to be collected.

By clicking into one of these files, you will be presented with data that few people will know how to interpret.

[![From Analytics Data, we need to select the Share button from the top right.](Analytics_Data_header.png)](Analytics_Data_header.png)

What we need to do is simply click the Share button in the top right corner to open the Share Sheet.

[![Accessing the Battery Stats shortcut from the Share Sheet on iPhone](Battery_Stats_accessed_from_Share_Sheet.png)](Battery_Stats_accessed_from_Share_Sheet.png)

In the Share Sheet menu, in the bottom list (after adding a shortcut), we will see the option Battery Stats.

> A little heads-up: Analytics data there may also be mixed with data from your other Apple devices, like the Apple Watch. The most recent file may be for watch data and not for the phone. Therefore, using a hit-and-miss approach, we need to try the one that will show us data representing our iPhone.

The shortcut will analyze your Analytics data and provide you with information about the **original maximum capacity**, **current maximum capacity**, **cycle count** (number of complete charge cycles), and your **battery health in %**, which is a relative value compared to when it was new.

[![Output from the Battery Stats shortcut on iPhone 13 Pro Max](iPhone_13_Pro_Max_Battery_Stats_D1.png)](iPhone_13_Pro_Max_Battery_Stats_D1.png)

> This calculation involves simple math. When the original capacity is 4489mAh and the current maximum is 3789mAh, dividing the lower value by the higher value gives us 0.8440. Multiplying by 100 gives us 84.40% (it shows 84.24% for some reason).

There will be a little shock. The values reported there will be lower than those officially reported by Battery Health in Settings.

Before we conclude, we need to remember that batteries supplied with new devices have a higher capacity than officially advised.

For example, the iPhone 13 Pro Max has an official battery capacity of 4352mAh, while the iPhone 13 has 3240mAh.

When we receive our phone, the designed capacity is likely around 110%, but Apple officially advises a lower value, as this is what they declare and guarantee for new devices.

They have multiple battery manufacturers, and this may vary, but all batteries must meet the minimum requirement. This is why they are most likely to have a higher original capacity than specified to ensure they meet that requirement.

The battery health most likely compares the current maximum capacity to the specified capacity (3789mAh/4352mAh), which will give us 87.06% and not 84.40%.

[![Battery Health displayed on iPhone 13 Pro Max](iPhone_13_Pro_Max_Battery_Health.png)](iPhone_13_Pro_Max_Battery_Health.png)

The 87% figure will match what is reported in settings and Battery Health.

---

[![Battery Health displayed on iPhone 13](iPhone_13_Battery_Health.png)](iPhone_13_Battery_Health.png)

Because my wife's Battery Health showed 80%, to my understanding, I am still not eligible to get it replaced for free as it needs to be below 80%.

However, the 80% can actually be 79.99%. You don't know that, as the value is rounded.

Thanks to the Battery Stats shortcut, I have been able to obtain data about my wife's phone.

[![Output from the Battery Stats shortcut on iPhone 13](iPhone_13_Battery_Stats.png)](iPhone_13_Battery_Stats.png)

It showed me an original capacity of 3348mAh, a current maximum of 2561mAh, and health calculated as **76.49%**.

> Additionally, it showed me a 1043 cycle count, which is extremely high. However, considering her need to connect much more often over recent months, this will explain a lot.

If you compare the current maximum value of 2561mAh to the official value of 3240mAh, you will get **79.04%**, which is not exactly 80% as reported by iPhone Battery Health.

Whichever method of calculation you use, both figures will allow me to get my wife's battery replaced free of charge.

> Because we are planning to give her phone as a gift to our kid, we thought about doing a battery replacement in September. This situation now allows us to get it replaced for free. Overall, we have been paying for that under our AppleCare+.

I opened my Apple Support app and quickly started chatting with the Apple Support representative.

Apple Support sent a request to run diagnostics on my wife's phone. Once that was finished, it was quickly confirmed that indeed the battery had degraded below an acceptable level. Now, as I have AppleCare+, it is eligible for a free battery replacement.

Quickly, through the same chat, we arranged an appointment at a nearby Apple Store to get this done. All is great.

That will resolve her issue now, and in September, it will save us some money when we want to get it replaced anyway.

{{% ads-in-article %}}

---

This makes me think about what my phone is reporting.

Through Settings, I received information about **87%** battery health, but upon analyzing some data from the past few days, I noticed some worrying signs.

On the 1st of July 2024, I observed a maximum capacity of 3789mAh, 616 cycle count, and a health percentage of 84.24% (compared to the original capacity of 4498mAh).

> That's 3789mAh compared to 4352mAh (the official figure), which is 87.06%.

[![Output from the Battery Stats shortcut on iPhone 13 Pro Max - Other day](iPhone_13_Pro_Max_Battery_Stats_D2.png)](iPhone_13_Pro_Max_Battery_Stats_D2.png)

On the 4th of July 2024, I observed a maximum capacity of 3792mAh, 617 cycle count, and a health percentage of 84.3%.

> The fluctuation in the maximum capacity is normal, as other factors can have an impact on it.

[![Output from the Battery Stats shortcut on iPhone 13 Pro Max - Day 6](iPhone_13_Pro_Max_Battery_Stats_D3.png)](iPhone_13_Pro_Max_Battery_Stats_D3.png)

However, on the 7th and 8th of July 2024, the analytics data showed 3576mAh, 619 cycle count, and a health percentage of only **79.5%**.

[![Output from the Battery Stats shortcut on iPhone 13 Pro Max - Day 7](iPhone_13_Pro_Max_Battery_Stats_D4.png)](iPhone_13_Pro_Max_Battery_Stats_D4.png)

Compared to 4352mAh, it is 82.17%.

> From what I've read, the data in Settings about battery health is refreshed periodically. This is why it's still displaying 87%. It **might** refresh in a few weeks, when the maximum capacity will be reported at a similar level over consecutive days.

I decided to monitor it for another day to see how it would change.

The mystery is why the data in Settings hasn't refreshed yet to show the current battery health, which is 82% (to specified capacity), rather than 87%.

This explains why my wife's battery health is reported as 80% in Settings, even though the actual capacity has likely been lower for some time.

Contacting Apple Support for diagnostics is a good way to get the most accurate battery health reading, which can help you decide whether a replacement is necessary.

> In the meantime, my wife headed to the Apple Store where it was confirmed that the battery did not pass the test and needed to be replaced. Before this issue was sorted out, they discovered some issues with cellular and wireless charging, which we were not even aware of. What started as a battery replacement ended up (whe parts arrive) requiring the replacement of the whole back of the phone. Fortunately, all of this was covered under Apple Care; otherwise, it would have cost us more than the phone is even worth (£357.50!).

While I understand that Apple compares the original battery capacity to the current maximum to determine health, raw data suggests a greater capacity loss. At 80% health, the battery has likely degraded by closer to 24% of its original capacity.

According to the Apple article on [iPhone battery and performance](https://support.apple.com/en-gb/101575), iPhone 14 and earlier batteries are designed to retain 80% of their original capacity at 500 complete charge cycles under ideal conditions.

> iPhone 15 models are designed to retain 80% of their original capacity at 1,000 cycles. 

My phone, and even my wife's phone, easily met these assumptions; hence, Apple delivered what it had promised.

Having, and using, AppleCare+ only to get the battery replaced for free is not a great investment, but we need to remember that this is insurance. You pay a fee to have peace of mind in case something happens. You could say that over the 3 years, if you haven't used your cover even once, you have just wasted money. However, in the case when you will need it most and you don't have it, you will see how expensive repairing Apple devices can be. Using third parties (unapproved) to repair your devices may be a cheap alternative, but I seriously discourage it, as they are most likely not using approved parts. Because of that, your phone may no longer work as you would expect, and its resale value will be significantly lower.

My friend not so long ago replaced the screen on an iPhone 13 with a local [iSmash](https://www.ismash.com/pages/ismash-leeds-trinity-phone-repairs) store located just opposite the Apple Store.

Sadly, the software immediately reported that non-genuine parts were used. As a result, reselling this phone will be very challenging, if not impossible. Just months after the replacement, the performance and responsiveness of the new screen degraded, leading us to the conclusion that we used their service for the first and last time.

To add context to the story, at the time, Apple would not replace the screen on my friend's phone at all, as the case was seriously bent backwards from impact. iSmash took the risk of straightening the case as much as they could (which was not great work) to allow them to fit the screen. In my opinion, they should have refused this service in the first place if the case could not be restored, but they chose a route where over time, the customer will be dissatisfied with their service.

When new phones are released in September, my wife's phone can give us a [trade-in value](https://www.apple.com/uk/shop/trade-in) of up to £305, whereas my friend's phone is currently worth absolutely nothing.

It’s partly my fault, as I knew that Apple would not help her with her phone. I recommended iSmash, thinking that this might turn out well (she did not have AppleCare+ at the time). To my disappointment, it turned out exactly like other shady third-party unauthorised repair shops. I shall believe in some critical reviews about them on the internet before taking a risk and not believe what they state on their website about using genuine replacement parts. Lesson learned.

Some people, especially in sales, need to remember one golden rule of the satisfied customer.

*One satisfied customer will generate one additional sale; however, one dissatisfied customer will take three customers away from you.*


---
## Combining Methods to Prevent Adblockers from Blocking Your Minimal Google Analytics 4 Snippet
- **URL:** https://dariusz.wieckiewicz.org/en/combining-methods-adblockers-google-analytics/
- **Date:** 2024-06-24
- **Tags:** Google Analytics, Redirect 200, minimal analytics, AdBlock Plus, DuckDuckGo, JavaScript

### Content

When I developed my [Minimal Google Analytics 4 snippet](/en/minimal-google-analytics-4-snippet/), I thought about preventing it from being blocked by various AdBlockers.

Along with AdBlock Plus, I am also using the DuckDuckGo Privacy Protection extension in Safari. I am using the DuckDuckGo browser on its own as well.

DuckDuckGo, along with restrictive ad blockers, tends to block requests heading to the `google-analytics.com` domain. This is done on purpose, and I fully understand that.

This is why I described mitigation techniques ([Minimal Analytics 4 - masking (hiding) requests](/en/minimal-google-analytics-4-snippet/#minimal-analytics-4---masking-hiding-requests)).

This technique allows you to utilize **Redirect 200** to mask requests to external domains under your domain.

By implementing a redirect as follows:

```
/g/collect https://www.google-analytics.com/g/collect 200
```

Instead of calling the address below in a script

```
https://www.google-analytics.com/g/collect
```

I am calling this

```
https://www.example.com/g/collect
```

Behind the scenes, thanks to **Redirect 200**, I am sending requests to Google Analytics that are not blocked by either AdBlock Plus or DuckDuckGo.

This solution, however, has **2 major flaws**.

<!--more-->

1. Only some people can use Redirect 200, especially for external domains.

Where I cannot do much about it, apart from advising utilizing Netlify for this, users are left with losing the actual analytics and not getting the true figures for website visits.

> You can set up Netlify independently of where your site is hosted and utilize it only for Redirect 200. Your website will be pointing in the script to the Netlify address and then from there back to Google Analytics.

2. Redirect 200 masks users' locations, from which the traffic is coming.

If you call `google-analytics.com` in your script directly (and it is not blocked), traffic details are sent to Google Analytics 4 together with information about where it is based on the user's IP address. This IP address allows for better geolocation and shows much more accurately where (which country, city) the user is coming from.

If you call your domain behind Redirect 200, the request is sent with the location of your server (from where the request originates), or if you are using a CDN, with the location of the CDN point (server).

For example, when using Netlify to perform Redirect 200, and you are surfing from the United Kingdom (or anywhere in Europe), your Google Analytics dashboard will show your users coming from **Frankfurt, Germany**.

[![Google Analytics map showing users originates from Frankfurt Germany](google_analytics_frankfurt_germany.png)](google_analytics_frankfurt_germany.png)

You can be in the UK, Poland, or Spain, and you will still be shown as traffic coming from Frankfurt, Germany. This is where the Europe CDN server for Netlify is located.

## Inspiration

I have in mind a solution that is available for JavaScript. When JavaScript is enabled, it can run code inside `<script>`. If JavaScript is not available, then it can return what's inside the `<noscript>` tag.

Like this:

```html
<script>
document.write("Hello World!")
</script>
<noscript>Your browser does not support JavaScript!</noscript>
```

I have been thinking if I can have a similar approach for JavaScript.

> Please keep in mind that I am not an expert in that field. I am learning along the way as I explore things.

I want to detect when a request for the `google-analytics.com` domain is blocked, and then serve the masked request (for users using AdBlocker), but when it is not blocked, serve an unmasked script (for users not blocking requests).

That’s in theory.

## Theory in practice

After doing my search, I found something like this:

```html
<script>

    let blocked = false;
  
    function success() {
      console.log("Success! A-script loaded. Website is likely reachable.");
      // Add your actual success logic here
      // minimal analytics tracking code goes here (https://www.google-analytics.com/g/collect)
    }
  
    function alternate() {
      console.log("Failed to load a-script. AdBlock might be blocking the request.");
      // Add your alternate functionality here
      // minimal analytics tracking code with implemented Redirect 200 goes here (https://www.example.com/g/collect)
    }
  
    const ascript = document.createElement('script');
    ascript.src = 'https://www.google-analytics.com/g/collect';  // Update URL to primary a-script
      
    ascript.onload = function() {
      blocked = false;
      success();
    }
  
    ascript.onerror = function() {
      blocked = true;
      alternate();
    }
  
    document.head.appendChild(ascript);
  
</script>
```

> Code from the [Minimal Google Analytics 4 Snippet](/en/minimal-google-analytics-4-snippet/), pasting the content from between the `<script>` tags **only** and removing both `console.log` lines from the script.

When you install the DuckDuckGo Privacy Protection in Safari, it will report straight as "Request Blocked from Loading" and in detail advise about blocked Google Analytics.

If you run Web Inspector, in the console you will see the response `Failed to load a-script. AdBlock might be blocking the request.`.

Just changing `google-analytics.com/g/collect` to just `example.com` will return `Success! A-script loaded. Website is likely reachable.`.

We are creating the script element, but we are not loading anything from it. It's just a dummy script that is used for identification if it is blocked or not.

If the script is blocked, then `function alternate()` will be fired. This is where we will paste our minimal analytics snippet with implemented Redirect 200.

If the block is not detected, then `function success()` will run. This will contain code for minimal analytics with a direct reference to the `google-analytics.com` domain.

{{% ads-in-article %}}

---

If you prefer (**recommended**), instead of pasting analytics code inside the same script, loading separate scripts, this approach will be:

```html
<script>

  let blocked = false;

  const ascript = document.createElement('script');
  ascript.src = 'https://www.google-analytics.com/g/collect';  // Update URL to primary a-script

  ascript.onload = function() {
    blocked = false;
    console.log("Success! A-script loaded. Website is likely reachable.");

    // Load success script
    const successScript = document.createElement('script');
    successScript.src = 'success.js';
    document.head.appendChild(successScript);
  }

  ascript.onerror = function() {
    blocked = true;
    console.log("Failed to load a-script. AdBlock might be blocking the request.");

    // Load alternate script
    const alternateScript = document.createElement('script');
    alternateScript.src = 'alternate.js';
    document.head.appendChild(alternateScript);
  }

  document.head.appendChild(ascript);

</script>
```

The `alternate.js` will contain code with Redirect 200 implemented (`https://www.example.com/g/collect`) and `success.js` without (`https://www.google-analytics.com/g/collect`).

> Code from the [Minimal Google Analytics 4 Snippet](/en/minimal-google-analytics-4-snippet/), pasting the content from between the `<script>` tags **only** and removing both `console.log` lines from the script.

---

While it's not possible to directly remove the initially created script element (`ascript`) after `onload` or `onerror` because the script execution continues, we can achieve a similar effect by conditionally loading the success or alternate scripts based on the loading outcome.

_P.S._ Loading the initial script (`ascript`) without parameters does not do anything; hence, you don't need to bother with it. The response for the script will be zero (see below - `204 No Content`).

```
% wget https://www.google-analytics.com/g/collect
https://www.google-analytics.com/g/collect
Resolving www.google-analytics.com (www.google-analytics.com)... 216.58.201.110
Connecting to www.google-analytics.com (www.google-analytics.com)|216.58.201.110|:443... connected.
HTTP request sent, awaiting response... 204 No Content
(0.00 B/s) - ‘collect’ saved [0]
```

## In Practice

Shortly after implementation, I didn't need to wait long to see users from other cities visiting my site, like Leeds in the United Kingdom (which is my visit).

[![Google Analytics map showing users originates from other locations in Europe](google_analytics_leeds_uk.png)](google_analytics_leeds_uk.png)

By inspecting the source code, I can see that `success.js` is loaded when I am browsing through the browser without any blocking extensions, and `alternate.js` when I am using ad blockers.

This small change should improve the reliability of location tracking through Google Analytics.

After just 24 hours, I noticed around 70% of traffic, on various sites, to be reported from a much more accurate location.


---
## Make Websites Readable Again
- **URL:** https://dariusz.wieckiewicz.org/en/make-websites-readable-again/
- **Date:** 2024-06-19
- **Tags:** Safari, Safari Reader, just read, auto reader, extension, accessibility, Chrome, Edge, Firefox

### Content

Have you ever tried to read an article on a website that is jam-packed with ads? Most of the time the overall experience will discourage you from it and you give up or will try to find similar information in a place, where you can access it more pleasantly.

I am using AdBlockers on all my browsers and hate when some websites tell me to turn it off just to read their content. They decided to block me from reading until I complied.

I understand that this is their source of income, however, browsing these websites without an adblocker enabled is a pain as hell.

The screens encouraging "support of independent writing" by displaying ads are nothing compared to the unpleasant and distracting experience of reading their website without adblocker enabled.

> This kind of website that prevents me from visiting at the start is, for example, [makeuseof.com](https://www.makeuseof.com).

This is crazy but true.

<!--more-->

Some other websites, that do not display ads, will block you from reading their content before you decide to support them through paid subscription.

If I cannot read it first, how can I know that I will ever return to your website? Supporting at the beginning is like giving a blank cheque. Let's be reasonable here.

Luckily there is a solution for that, but before we indulge ourselves in that, let's see the problem here.

## New York Times example

[![Article on New York Times website with a banner covering the view](nytimes_website_article_banner.png)](nytimes_website_article_banner.png)

Even if you disable an adblocker, you are still not allowed to go any further without creating an account, to allow them to track what you reading and further convince (force) you to subscribe.

[![Article on New York Times website with AdBlocker disabled](nytimes_website_article_without_adblock.png)](nytimes_website_article_without_adblock.png)

**It sucks!**

However, the same article can be readable again just like that:

[![Article on New York Times website through Safari Reader](nytimes_website_article_reader.png)](nytimes_website_article_reader.png)

This is thanks to the Reader option built into Safari Browser.

> **Safari is only available for Apple operating systems but keep reading, as I have options for Windows users as well.**

---

Reader in Safari can be turned on **automatically** for specific sites, like NYT. Thanks to that, from wherever you will be redirected to their article, the article will be loaded in a way that you can enjoy it in full.

On any website you are on, you just need to click the Reader icon from the address bar (on computer).

[![Reader icon in Safari displayed as an option for New York Times article](nytimes_reader_icon_address_bar.png)](nytimes_reader_icon_address_bar.png)

To enable the reader automatically on a specific site, just right-click on the reader button (on computer) and select option *Use Reader Automatically on ...*.

If you want to use the reader on mobile you need to click the `aA` icon on the address bar, from where you need to select Reader from the available options.

[![Enabling Safari Reader on the New York Times website on mobile](nytimes_reader_safari_mobile.png)](nytimes_reader_safari_mobile.png)

While you are in reader mode, by clicking the `aA` button again, from available options select *Website Settings* and enable the reader to *Use Reader Automatically* on a specific site as shown below.

{{% gallery %}}
[![Setting Safari Reader to start automatically on the New York Times website - aA menu](nytimes_reader_automatically_1.png)](nytimes_reader_automatically_1.png)
[![Setting Safari Reader to start automatically on the New York Times website - Website Settings menu](nytimes_reader_automatically_2.png)](nytimes_reader_automatically_2.png)
{{% /gallery %}}

---

**Going back to NYT...**

Blocking on their website is strictly based on JavaScript. The article is loaded in full but when JavaScript is served after, your view is restricted. Turning off JavaScript altogether will do the work as well.

This is how the reader in Safari makes it work. It's stripping the website from unnecessary nonsense leaving only the most important part.

> Not all websites (or even some articles on NYT) however are loading full articles and then blocking it with JavaScript. Some articles are placed behind a paywall and only allow you to read a portion of it. To read the rest, you need to log in and subscribe. In this instance, the reader will only load a portion of the article that is not behind a paywall. Sadly we cannot do anything about it but is worth trying what is available **for free**.

---

{{% ads-in-article %}}

## Some other websites

I am using automatic reader mode on a few websites. All these websites you can control from Safari settings.

On mobile, head to *Settings > Safari > Reader* to find them.

[![List of websites in my Safari where Reader is set to start automatically](safari_automatic_reader_websites.png)](safari_automatic_reader_websites.png)

I don't have a lot of them but got them few enough to make my daily reading experience manageable.

Through everyday browsing [AdBlocker](https://adblockplus.org/ad-blocker-safari) doing its job, in some extreme situations I need to enable Reader and this is saving me a lot of struggles.

## Chrome Unboxed website

One of the websites that I have recently explored is [Chrome Unboxed](https://chromeunboxed.com).

I understand that there are a few people venture that need to fight to stay afloat. They use advertising on their pages to such an extreme, that on every screen scroll (especially on mobile) you are presented with a large advertising box.

{{% gallery %}}
[![Chrome Unboxed website article on mobile - with banner on top](chrome_unboxed_1.png)](chrome_unboxed_1.png)
[![Chrome Unboxed website article on mobile - with blank space remaining after Ad was blocked](chrome_unboxed_2.png)](chrome_unboxed_2.png)
{{% /gallery %}}

Even if AdBlocker doing its job in blocking them from being displayed, the empty box is left unfilled making the reading experience a bit awkward.

[![Chrome Unboxed website article on mobile in Safari with empty space between paragraphs](chrome_unboxed_empty_space.png)](chrome_unboxed_empty_space.png)

There are some other empty spaces as well, that potentially shall be filled with ads.

Because of the empty blocks (which can be easily fixed as highlighted by Google [itself](https://support.google.com/adsense/answer/10762946?hl=en-GB)), you have a feeling that the article is very long. However, when you start reading you get to the bottom very quickly and you get this feeling of a lot of space and not enough content. Because of that, the amount of ads in such short text is way too much.

When you enable Reader on their website, this confirms it, but even Reader struggles with removing empty spaces where the ad was initially shown.

[![Chrome Unboxed website article on mobile in Safari Reader with remaining space from removed ads](chrome_unboxed_empty_space_reader.png)](chrome_unboxed_empty_space_reader.png)

---

Reader in Safari is not perfect but is a great tool enough to make websites readable again.

> Some websites may be poorly constructed so the option to enable reader will not be available.

## Other browsers

Other browsers also have their tools, which typically require them to be installed as an extension.

Suggested alternatives for Safari Reader in other browsers:
* [Just Read by justread.link](http://justread.link/#getJustRead) for Google Chrome and Microsoft Edge
* [Auto Reader View by Patrick Marchwiak](https://addons.mozilla.org/en-US/firefox/addon/auto-reader-view/) for Mozilla Firefox

---

Using Reader mode or the extensions mentioned above is a great way for publishers to see **how accessible their sites are**.

If browsing a website with a reader still returns a lot of crap, the owner of the website shall consider making changes.

Be aware that the reader mode is very often used by people with disabilities who rely on assistive technology like screen readers etc. If a person without any disabilities struggles imagine what struggle millions of people with disabilities will have.


---
## Implementing Google Adsense without affecting site performance
- **URL:** https://dariusz.wieckiewicz.org/en/implementing-google-adsense-performance/
- **Date:** 2024-06-17
- **Tags:** google adsense, hugo, javascript, javascript delay, script delay, ads, AdBlock, webperf, webdev, css

### Content

Recently, I have been in contact with several people who have been thanking me for posting articles that have helped them significantly with their technological struggles or in easing their issues.

Some of them have been so happy that they would like to know how to donate a bit to support the cause. While this gesture is appreciated, most of the activities on my site are non-profit.

I used to have ads displayed on my website when it was hosted on WordPress. However, after migrating to Hugo, I soon realized that despite the speed benefits, the web performance was being compromised due to ads served through Google AdSense.

I managed to significantly reduce the costs for my website, so I decided to take the step of removing ads altogether, and I have been happy with this decision.

<!--more-->

Nobody likes websites filled with ads that make them difficult to use, let alone read, due to all the clutter. This clutter refers to ads.

> Thank you for the Reader option in Safari that makes websites readable once more!

I prioritize my readers' experience over profit, which is why one of the options provided by Google AdSense, Auto Ads, was on my blacklist from the beginning.

However, if there is a way to display something non-intrusive within the article, without impacting the overall reading experience, why not give it a try?

I heard a question posed to an expert on one of the podcasts I listened to: "When should you start monetizing a website?" The expert's response was "as soon as possible."

I agree with that **if it is done correctly!**

I tried adding "buy me a coffee" banners, but it required some extra steps to finalize that **nobody wanted** to follow.

Ads served in intrusive ways are the very reason why AdBlockers exist in the first place. I use AdBlockers everywhere and do not recommend anyone to go online without them.

Adblockers are doing a great job in making the internet usable again.

If I decide to resume serving ads, they need to have as minimal an impact as possible.

When I say **minimal impact**, I mean not only for readers (to avoid distracting them) but also for the website itself in terms of web performance.

I recently re-analyzed the ad unit offered in Google AdSense, which allows me to insert **in-article ads**.

Simply pasting the code somewhere in the middle of the article significantly impacts the overall performance of that specific webpage.

**This wasn't for me.**

I decided to try a **different approach**.

I recall a recent discussion on the [Hugo Discourse forum](https://discourse.gohugo.io/t/adsense-lazy-load-with-auto-ads-on/39180/5?u=idarek) regarding lazy loading Adsense Ads, specifically Auto Ads.

I examined the code there and observed that the script is loaded after the page is rendered upon mouse movement.

This reminds me of a script delay approach that I discussed in my post [Implementing JavaScript Delay for Cookie Consent Banner](/en/implementing-js-delay-for-cookie-consent-banner/).

I decided to implement that in combination with *in-article ads* served through Google AdSense.

As tested initially, everything has been working as theoretically assumed.

Without impacting the performance on the initial load of the website, the script starts to execute after the specified event is detected:

```javascript
const eventList = ["keydown", "mousemove", "wheel", "touchmove", "touchstart", "touchend"];
```

I opted for *in-article ads* and positioned them much lower, below the initial view when the website (web page) loads. In general, I don't want to annoy my readers like other websites do by displaying ads every other paragraph or every time the screen is scrolled.

I am someone who dislikes ads, so I bear that in mind and utilize my code to show ads only once.

Naturally, incorporating ads required me to reinstate [my cookie consent banner](https://github.com/idarek/cookies-bar) (with a delay, of course), but I restricted its display to posts where ads might be shown, excluding pages where it is unnecessary.

---

The in-article ad code is composed of 3 elements.

The first element is a script (redacted) that loads the ads. This script causes the **biggest performance drop** when loaded **as is**.

```html
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-################"
     crossorigin="anonymous"></script>
```

The second part of the script (redacted) is a block where ads are displayed.

```html
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-################"
     data-ad-slot="##########"></ins>
```

And there is just a final, third part of it.

```html
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>
```

> I find it challenging to comprehend this, as I am not an expert in JavaScript, so I consulted [ChatGPT](https://chatgpt.com/share/4fc6c265-bbdc-4a3f-b1f4-e9633af0ad18) about it:
> 
> Shortly _"In JavaScript, `|| []).push({});` is a pattern used to ensure that a variable, typically an array, is defined before performing operations on it."_

---

I am using [Hugo](https://gohugo.io) to generate my website. Using Hugo shortcodes, I created one specifically for displaying ads on my website, which I named `ads-in-article.html`.

Within this file, I included all three parts of the Google Ads script with some modifications. But before we explore that, let's discuss how I insert my `shortcode` into my posts.

I intentionally used shortcodes instead of integrating them into the layout (theme), as this provides me with flexibility regarding when and where the ad will be displayed.

I review all my posts on my website, which are saved in Markdown files, and determine precisely where I want to insert my ad.

I insert my code simply by adding the following line:

```markdown
{{%/* ads-in-article */%}}
```

This solution is beneficial for one reason. Suppose you want to remove all the ads from your articles. In that case, I simply clear the content of the file `ads-in-article.html` and leave it blank. All blocks are rendered, but since they are empty, nothing is added or displayed.

Adding it was time-consuming considering the number of posts, but it allowed me to refine some of them and determine where the ads would be placed.

Intentionally, I ensured that the ads would be displayed below the fold of the website, whether in the desktop layout or on mobile.

Once I had this sorted out, I revisited my `ads-in-article.html` to make some modifications that enable me to manage the impact on the initial page load performance of the pages where ads are shown.

---

I had already implemented the script delay functionality for my [cookie banner](/en/implementing-js-delay-for-cookie-consent-banner/), but since you may not have done so yet, I will begin from the start.

In Hugo, I defined my script delayer in the file `script-delay.html` as a partial in my layout.

I referenced this file in my `article.html` (at the bottom of the file), which is a part of the layout responsible for displaying individual posts only.

```html
{{ partial "script-delay.html" . }}
```

> Of course, you can simply paste the content of `script-delay.html` into the footer of your website if you wish to make it available site-wide.

The `script-delay.html` file is as follows::

```html
<script>
const autoLoadDuration = 5; //In Seconds
const eventList = ["keydown", "mousemove", "wheel", "touchmove", "touchstart", "touchend"];
const autoLoadTimeout = setTimeout(runScripts, autoLoadDuration * 1000);

eventList.forEach(function(event) {
    window.addEventListener(event, triggerScripts, { passive: true })
});

function triggerScripts() {
    runScripts();
    clearTimeout(autoLoadTimeout);
    eventList.forEach(function(event) {
         window.removeEventListener(event, triggerScripts, { passive: true });
    });
}

function runScripts() {
    document.querySelectorAll("script[data-delay]").forEach(function(scriptTag) {
        const delaySrc = scriptTag.getAttribute("data-delay");
        if (delaySrc) {
            scriptTag.setAttribute("src", delaySrc);
            scriptTag.removeAttribute("data-delay");
            if (scriptTag.hasAttribute("async")) {
                scriptTag.setAttribute("async", ""); // Re-apply async if it was present
            } else if (scriptTag.hasAttribute("defer")) {
                scriptTag.setAttribute("defer", ""); // Re-apply defer if async was NOT present
            } else {
                // Default to defer if neither async nor defer were initially present
                scriptTag.setAttribute("defer", "");
            }
        }
    });
}
</script>
```

The script waits for user interaction or 5 seconds, before doing its action.

Its action is to change invalid code for loading JavaScript on the website into a valid one and running it.

For example, this is how the script will be loaded.

```html
<script src="script.js"></script>
```

To prevent it from loading, we break the script as follows:

```html
<script data-delay="script.js"></script>
```

> The `defer` attribute is added by default unless it is already specified in `<script>`. If `async` is present, `async` is retained.

This way, there is no `src` element (making it invalid), hence the script is not fired.

This is where the script delayer takes over by replacing `data-delay` with `src` and firing the script when conditions are met.

---

Going back to `ads-in-article.html`, the only thing that I changed was this part:

```html
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-################"
     crossorigin="anonymous"></script>
```

to that:

```html
<script async data-delay="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-################"
     crossorigin="anonymous">
```

Thanks to that, the ads are shown to those who are not blocking it with AdBlockers, and the performance is not affected.

Whoever wants to click on them will, and whoever wants to block them can do so with AdBlockers. **I don't mind.**

Google is suggesting anti-adblocker tactics, but I hate screens telling me to turn off adblocker to read articles. If that's annoying me enough to make me give up the site altogether, then I prefer not to use it at all and ensure that my readers enjoy what I have to share rather than profit from them.

---

There is one more thing that is not advertised well but strongly suggested by Google [itself](https://support.google.com/adsense/answer/10762946?hl=en-GB). It's a small addition to the CSS style to prevent displaying empty blocks where ads should be displayed.

```css
ins.adsbygoogle[data-ad-status="unfilled"] {
  display: none !important;
}
```

And that's all.

If you decide that you would like to serve some ads to get a small return from your investment in creating the content (time), do it the smart way and don't let your website suffer.

Here is an **example** of ads served the smart way (between the horizontal lines below). If you don't see them, don't worry, that's probably your browser or adblocker successfully blocking them. If you do see them, check out what they have to offer and support me if you think it's right.

---

_Inserted ad (if not blocked by your AdBlocker):_

{{% ads-in-article %}}

---

In the end, the content matters, but if the website is slow as well, you can have the best content available, but Google, which is the main driver of traffic to my website, will not like you.


---
## Don't spread the cost through Apple when buying a refurbished iPhone, buy a new one instead and save
- **URL:** https://dariusz.wieckiewicz.org/en/dont-spread-cost-through-apple-refurbished-iphone-buy-new-instead/
- **Date:** 2024-06-08
- **Tags:** Apple, Refurbished, iPhone, APR, Installments

### Content

Buying a refurbished Apple product is a great way to save money. I purchased my MacBook Air with an M1 chip through this route back in 2021, and the device is still working well.

The good news when buying refurbished items directly from Apple is that they are treated no differently than new devices in terms of support and service. You are eligible to purchase additional protection through AppleCare, just like with new devices.

The savings on refurbished items, compared to the same item new, can be significant. Of course, you can buy them even cheaper if you don't mind losing the ability to get extra care for them directly through AppleCare, but if you do mind (like me), then there is one more thing that you should think about before going this route.

<!--more-->

In 2021, I purchased my MacBook Air M1 by trading in my Intel-based MacBook Pro (2020) directly to Apple. I received a credit from Apple towards a different device, which I used to purchase my refurbished laptop and a few other things from them.

If I did not have this credit, I would consider buying it by paying in installments (monthly).

I always advise buying Apple devices this way, as in the UK, with Barclays, new devices are sold with 0% APR (used to be).

Over months, you pay the same amount as if you were to pay in full at the beginning. Because of that, it's not cost-effective to spend so much money at once; it's better to put this in a savings account and get something back from it while the device pays for itself without any extra cost.

I recently noticed that when new devices (iPhones) get a preferential 0% APR rate, in a refurbished store, it's highlighted that spreading the cost will burden you with a 14.9% APR.

Surprisingly, other new Apple products are also advertised with a 14.9% APR. I remember that this used to be 0% as well.

This means buying a refurbished product (in this case, an iPhone) and paying monthly is not a great saving, as in the end, you may be paying the exact amount you would spend on a new device.

Let's say that you want to buy a previous generation iPhone 14 128GB.

The new device, at £699, will cost you £29.12 per month for 24 months with 0% APR. The last installment will be a bit different, but it will work out to £699 in total.

> Zero cost.

However, the same device refurbished is sold for £589.

> A potential savings of £110 when buying refurbished.

Apple, by default, advertises 36 monthly installments at £20.12. **I strongly do not recommend that**, but if you go that route, it will look like you will pay around £724.32 in the end.

> Removing the initial saving of £110, you will be **worse off** by £25.32 compared to buying a new device.

If you go for 24 months, you will pay £28.27. This will cost you £678.48.

> Removing the initial saving of £110, you will be **better off** by just £20.52.

Is it worth buying refurbished? **In that case, I don't think so!**

The other option that you may consider is going into 12-month instalments for £52.88 per month. You will pay £634.56 in total.

> Removing the initial saving of £110, you will be £64.44 **better off**.

But is such a small difference worth it? In the end, when you want to sell the product, even after 12 months, you will not gain anything but lose even more.

{{% ads-in-article %}}

---

The same story is currently happening in the UK market with cars. New cars, even though they are more expensive, have much lower APR than when you buy an approved used car that is just 1 year old. In that situation, it is simply not worth looking into a used car unless you buy it and pay in full.

---

Of all the Apple products currently, it's only the new iPhone that is sold with 0% APR spread over 24 months in the UK.

This is a really good deal for the upcoming September 2024, when we are all looking forward to seeing what the iPhone 16 will offer.

---

Of course, there is also another option to purchase an iPhone through the iPhone Upgrade Programme. I explored that in [2020](/en/iphone-upgrade-programme-in-2020-is-it-worth-it/) but never found it compelling enough for me to go for it.

The program is good for people who:
1. always buy AppleCare with their product, and
2. always want to upgrade to the latest phone once the new one is announced.

Number 1 suits me, but I don't always feel the urge to upgrade each year to the latest one. I am past the stage where I always need to have the latest tech. I am too old for that.

Currently, I have an iPhone 13 Pro Max (256GB), and I intentionally assumed that I would use it for 3 years. This year, when the iPhone 16 is announced, it is most likely that I will go for it. I started noticing wear on the battery, and performance began to slowly decline with the newest games. Comparing the need for greater performance and an aging battery, I found myself sticking to a charger more often than a year ago.

---

Despite Apple still offering 0% APR, but only on iPhones, that doesn't mean you don't have any other options to save.

There are plenty of 0% Purchase Credit Cards available in the UK (if you are eligible), which can help you save in the long run, as long as you keep up with monthly repayments and pay your balance in full before the promotional 0% period ends.


---
## Apple TV - Retro Gaming Console
- **URL:** https://dariusz.wieckiewicz.org/en/apple-tv-retro-gaming-console/
- **Date:** 2024-05-17
- **Tags:** Apple TV, Apple TV 4K, gaming console, emulator, RetroArch, App Store, Apple

### Content

It took years for Apple to allow gaming emulators on their platforms.

After a failed start with a fake emulator, it was time for the first one that worked and was not preying on someone else's intellectual property. However, the creator quickly got scared and withdrew the application from the store. You can understand him to some extent, because in reality, David rarely beats Goliath.

Less than a week later, however, we were able to enjoy the Delta emulator, which remains to this day.

Delta has introduced support for many emulators in a very friendly graphic design. However, it is not Delta that I will be writing about.

Some time passed when the Gamma and PPSSPP emulator officially came to the store, however, what they, and Delta, lacked was support for another Apple platform, namely Apple TV.

And so one day it came to the Apple platform with support for Apple TV multi-emulator [**RetroArch**](https://apps.apple.com/uk/app/retroarch/id6499539433).

With a bluetooth controller connected (I personally use an Xbox controller), my Apple TV finally became the game console I had been waiting for.

While I previously used Raspberry Pi and RetroPi for this purpose, RetroArch on Apple TV is more convenient and allows you to easily add files via a web browser.

My Apple TV is always connected and in use, so I don't have to switch between devices.

If I want to play [Super Mario Bros](https://en.wikipedia.org/wiki/Super_Mario_Bros.) for 5 minutes and then watch a movie, I can do it from the couch without any fuss.

Before I could play, however, I had to turn off "overlay" in the application, because it looks strange to have on-screen buttons on a TV that does not have a touch screen.

The creators of RetroArch did not take into account the fact that overlay should be disabled by default for Apple TV :)

{{% ads-in-article %}}

In December 2022, after purchasing the latest Apple TV, I wrote that it was a [good game console with missed opportunities](/en/apple-tv-4k-2022-good-gaming-console-missed-opportunities/). While it was possible to play newer games from Apple Arcade, everyone was actually waiting for something simpler, such as Super Mario Bros.

A year and a half later, Apple users experienced a breakthrough that was nothing new for the Google platform, but we can finally play some "old" games.

RetroArch brings to our Apple TV not only the NES, SNES, MegaDrive consoles, but also Nintendo 64, Gameboy, Nintendo DS, as well as PlayStation 1, PSP and others.

It is PlayStation games that can encourage many of you to try something "old" but good.

Now I would like to see if it is possible to add support for [Light Gun](https://en.wikipedia.org/wiki/NES_Zapper), which users have enjoyed in the past while playing [Duck Hunt](https://en.wikipedia.org/wiki/Duck_Hunt)!

Well, that would be the icing on the cake :)

> As a matter of curiosity, RetroArch is also available on Apple Vision!


---
## Managing Microsoft Edge settings in a business environment with Microsoft 365
- **URL:** https://dariusz.wieckiewicz.org/en/managing-microsoft-edge-business-policy-microsoft-365/
- **Date:** 2024-04-13
- **Tags:** Microsoft 365, Microsoft 365 Business Basic, Microsoft Edge, Microsoft Edge Business, Policies for Microsoft Edge, Google, Google Search

### Content

While I'm cautious about purchasing expensive licenses, for some businesses, the cheapest option, Business Basic for £4.90 per user per month, is more than enough!

Every now and then, I discover new "hidden" features that I can use with just a basic license, and this time was no different.

Setting up computers in businesses, I always default to Google Search.  Frankly, Bing just hasn't kept pace, despite the recent AI hype.  For most users, Google's familiarity boosts productivity, which is key in any business environment.

What I hate is that Microsoft, with every other Microsoft Edge update, forces Bing back as the default search engine.

<!--more-->

This situation reminds me of this nonsense:

![Red hat with Make Bing Great Again text on it](make_bing_great_again.png)

**One day, this annoyed me so much that I wanted to find a way to make it stop.**

However, I'm concerned when users disable browser settings or extensions I've installed for their own and the company's safety. Ideally, I'd like the ability to prevent these changes.

Manually reverting user changes on every computer isn't feasible.  Therefore, I wanted to see if Microsoft 365 offered a way to enforce these settings without a license upgrade.

Within our organization, each user leverages their Microsoft account to log in to their operating system and Microsoft Edge. This seamless integration ensures company-wide synchronization and data accessibility.

The Microsoft [Admin Portal](https://admin.microsoft.com) offers a wealth of useful features. However, some add-ons may only be activated for a trial period and require an extended licence. Others, despite being very useful, are so hidden that you do not even know that they are there.

I recently found a new option related to [Microsoft Edge in the Microsoft 365 Admin Portal](https://admin.microsoft.com/Adminportal/Home#/Edge). It's unclear how long this feature has been available, as Microsoft doesn't always effectively communicate these valuable additions to its paying users.

[![Microsoft 365 Admin Portal - Settings - Microsoft Edge](Microsoft_365_Settings_Microsoft_Edge.png)](Microsoft_365_Settings_Microsoft_Edge.png)

This section is used to set **Policies for Microsoft Edge**.

[![Policies for Microsoft Edge - Initial Screen](Policies_for_Microsoft_Edge_initial_screen.png)](Policies_for_Microsoft_Edge_initial_screen.png)

This might seem familiar to users who have experience with Group Policies on user computers. However, unlike Group Policies, this approach doesn't require their deployment.

Through Policies for Microsoft Edge, you can configure a wide range of browser settings and even lock them to prevent user modifications. Additionally, you can deploy extensions centrally.

To ensure a consistent browsing experience across the business, I deploy [Adblock Plus](https://microsoftedge.microsoft.com/addons/detail/adblock-plus-free-ad-bl/gmgoamodcdcjnbaobigkjelfplakmdhh) as a default extension on all computers. While users might occasionally disable it, frequent tinkering can disrupt security measures.  Fortunately, Microsoft 365 policies allow me to enforce its activation and prevent unintended modifications.

However, the most crucial aspect for me was permanently establishing Google Search as the default engine across all computers. This ensures it remains unchanged even with future Microsoft updates.

**Here is how I did this.**

> **Important Note:** These policies are currently only effective for users with Windows 10 and 11. macOS is not supported at this time, but this may change in the future.

## Default Search Engine

Since there are no default policies configured yet, we'll need to create one.

[![Microsoft Edge - Configuration policies](Microsoft_Edge_Configuration_policies.png)](Microsoft_Edge_Configuration_policies.png)

Heading to **Configuration policies** we need to hit the button **Create policy**.

> Don't worry about accidentally impacting users while configuring the policy. You can create and define the settings without affecting anyone. The policy only becomes active once you assign it to specific users or groups in the [Assignment section](#assignment).

The initial settings list can be extensive and less user-friendly compared to the browser interface itself.

Recognizing this potential challenge, Microsoft has helpfully included the following introductory text...

> Search for a setting to configure and add to Microsoft Edge Policy. Browse the list of available policies here: [Microsoft Edge Browser Policy Documentation | Microsoft Learn](https://learn.microsoft.com/en-us/deployedge/microsoft-edge-policies)

**Warning here!**

While the Microsoft team deserves credit for the **extensive** documentation, its single, lengthy format presents a usability challenge.

The initial load can be quite heavy, potentially causing sluggish browser performance or even temporary resource strain on your computer.

Loading this page in a single tab pushed my computer's RAM usage to 2.6GB before it became unresponsive (possibly due to impatience on my end).

This comprehensive page requires some initial loading time. Please be patient and avoid refreshing or navigating back and forth. Doing so can significantly slow down the loading process.

> If you need to move between sections (headers), use the scroll bar to navigate back to where you were.

Once loaded, the page's memory usage drops to a few megabytes, functioning smoothly thereafter.

---

Choose a descriptive name for your policy before clicking **Create**.

Let's revisit the policy list. Click on the policy you just created to open the **Manage settings for this Configuration policy** section. This section will initially appear blank.

[![Manage settings for this Configuration policy](Manage_settings_for_this_Configuration_policy.png)](Manage_settings_for_this_Configuration_policy.png)

Clicking **Add setting** displays a list of configurable policy options for Microsoft Edge.

> As mentioned before, configuring Microsoft 365 policies for Microsoft Edge isn't as straightforward as using the browser settings. Setting the default search engine, for example, requires applying multiple settings instead of just making a single selection.

To configure Google Search as the default and only search engine (enforced), we'll need to apply the following settings:

- **DefaultSearchProviderEnabled**\
	Enable the default search provider
	
	Allow users to override: **No** (unticked)

- **DefaultSearchProviderName**\
	Default search provider name
	
	```
	Google
	```
	
	Allow users to override: **No** (unticked)

- **DefaultSearchProviderImageURL**\
	Specifies the search-by-image feature for the default search provider
	
	```
	{google:baseURL}searchbyimage/upload
	```
	
	Allow users to override: **No** (unticked)

- **DefaultSearchProviderImageURLPostParams**\
	Parameters for an image URL that uses POST
	
	```
	encoded_image={google:imageThumbnail},image_url={google:imageURL},sbisrc={google:imageSearchSource},original_width={google:imageOriginalWidth},original_height={google:imageOriginalHeight}
	```
	
	Allow users to override: **No** (unticked)
	
- **DefaultSearchProviderSearchURL**\
	Default search provider search URL

	```
	{google:baseURL}search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}ie={inputEncoding}
	```

	Allow users to override: **No** (unticked)

- **DefaultSearchProviderSuggestURL**\
	Default search provider URL for suggestions

	```
	{google:baseURL}complete/search?output=chrome&q={searchTerms}
	```

	Allow users to override: **No** (unticked)


For those who wish to enable Google's [SafeSearch](https://en.wikipedia.org/wiki/SafeSearch) feature additionally, you can configure the following setting:

- **ForceGoogleSafeSearch**\
	Enforce Google SafeSearch
	
	Allow users to override: **No** (unticked)

These settings cover the essentials. However, since Bing can also influence address bar searches, I've included an additional setting to address this.

- **NewTabPageSearchBox**\
	Configure the new tab page search box experience

	`Address bar`

	Allow users to override: **No** (unticked)

I additionally enabled the following settings:

 - **ShowHomeButton**\
	Show the Home button on the toolbar

	Allow users to override: **Yes** (ticked)

- **HomepageLocation**\
	Configure the home page URL

	```
	https://www.google.com
	```

	Allow users to override: **Yes** (ticked)

{{% ads-in-article %}}

## Extensions

Within each Edge policy, you'll find a dedicated **Extensions** section in addition to the Settings section.

This dedicated Extensions section allows you to deploy extensions to your users' computers. You can also control whether users are allowed to modify or disable these extensions.

[![Microsoft Edge - policy - Extensions - AdBlock Plus](Microsoft_Edge_policy_Extensions_Adblock_Plus.png)](Microsoft_Edge_policy_Extensions_Adblock_Plus.png)

Setting the **Installation setting** to **Force** ensures pre-installation of the extension on all user computers and prevents them from disabling it.

In addition to the above settings, I also recommend adding the following:

- **ExtensionSettings**\
	Configure extension management settings

	`Use the Extensions tab to manage this setting`

	Allow users to override: **No** (unticked)

## Organization branding

Accessing your Edge policy grants you control over various aspects. Look for the Customization Settings section, which includes the **Organization branding** option.

[![Microsoft Edge - Organization branding](Microsoft_Edge_Organization_branding.png)](Microsoft_Edge_Organization_branding.png)

This section allows you to incorporate your organization's custom branding elements, such as logos and color schemes.

While using custom branding is optional, I highly recommend at least modifying the **Accent color**. This simple change provides a visual cue, helping you quickly identify if a user's browser is adhering to the policy.

## Assignment

Once you've configured your policy settings, navigate to the **Assignment** section (accessible within your policy from **Policies for Microsoft Edge**) to deploy it to your users.

[![Microsoft Edge Policy - Assignment](Microsoft_Edge_Policy_Assignment.png)](Microsoft_Edge_Policy_Assignment.png)

While assigning security groups is beyond the scope of this guide, selecting **All Users** from the Select group dropdown will deploy this policy to everyone in your organization.

Adding this group triggers the policy rollout to your users' browsers. While not instantaneous, the policy will reach everyone within a reasonable timeframe.

## How do you know it is working?

Implementing a policy and assigning it to a group doesn't result in immediate application.

As with many Microsoft services, policy application might take some time to synchronize across all devices. In some cases, this could extend up to a day.

If you've enabled [**Organization branding**](#organization-branding), a customized **Accent color** will be the quickest way to confirm policy application. Look for this color change when you click the user icon in the top-left corner of your user's browser.

Accessing Microsoft Edge settings (via the three-dot menu) reveals the message **Managed by your organization** at the bottom.

[![Microsoft Edge - Settings menu (managed)](Microsoft_Edge_Settings_menu_managed.png)](Microsoft_Edge_Settings_menu_managed.png)

Upon entering the Settings section, a banner at the top clearly states: **Your browser is managed by your organization.**

[![Microsoft Edge - Settings banner (managed)](Microsoft_Edge_Settings_banner_managed.png)](Microsoft_Edge_Settings_banner_managed.png)

Clicking the link within the banner redirects you to the `edge://management` section, which provides some basic policy details.

[![Microsoft Edge - management](Microsoft_Edge_management.png)](Microsoft_Edge_management.png)

Proceeding further from the `edge://management section`, you can access `edge://policy` for a more detailed view. This section displays the currently applied settings and provides a **Reload Policies** option. This is useful if you've made changes to the policy and want them to take effect immediately on user browsers, bypassing the usual synchronization wait time.

[![Microsoft Edge - policies](Microsoft_Edge_policies.png)](Microsoft_Edge_policies.png)

## Other suggested

Microsoft Edge policies offer a wide range of customization options to cater to specific business needs. The examples provided here represent just a few settings I found useful.

Apart from that, there are also a few that I would suggest:

- **StartupBoostEnabled**\
	Enable startup boost

	Allow users to override: **No** (unticked)

- **BackgroundModeEnabled**\
	Continue running background apps after Microsoft Edge closes

	Allow users to override: **No** (unticked)

- **SleepingTabsEnabled**\
	Configure sleeping tabs

	Allow users to override: **No** (unticked)

- **SleepingTabsTimeout**\
	Set the background tab inactivity timeout for sleeping tabs

	`30 minutes of inactivity`

	Allow users to override: **Yes** (ticked)

- **PasswordManagerEnabled**\
	Enable saving passwords to the password manager

	Allow users to override: **No** (unticked)
	
---

By following these steps, you've successfully implemented custom Microsoft Edge settings across your organization's user computers through specific policies.


---
## ChromeOS, Sticky Keys and the issue with foreign characters invoked with the right Alt-key (AltGr)
- **URL:** https://dariusz.wieckiewicz.org/en/chromeos-accessibility-sticky-keys-altgr/
- **Date:** 2024-04-11
- **Tags:** Chromebook, ChromeOS, ChromeOS Flex, Accessibility, Sticky Keys, AltGr

### Content

> Starting from 29th May 2024, ChromeOS 125 began rolling out to stable channels for all supported Chromebooks. The issue described below should be resolved for everyone, particularly for those writing in foreign languages with Sticky Keys enabled.

I recently faced an interesting issue with a friend's new Chromebook.

My friend has a disability and uses a single finger to write on her blog [antybariera.pl](https://antybariera.pl). Because she wrote in Polish by default, to put special characters, like `ąśćżęł`, she would need to use key combinations. For that purpose, she would have to use two fingers, which is extremely difficult, if not **impossible**.

Chromebooks are equipped with useful accessibility features. I remember seeing something called a sticky key that, **in theory**, should work as follows.

To produce the character `ę` in Polish, press and hold the <kbd>Alt</kbd> key and then press the letter `e`.

Sticky Keys work in a way that allows you to single-press a key like <kbd>Alt</kbd>. This activates it and makes it behave as if held down with another finger. In the same way, you can double-press the Control key (like the <kbd>Alt</kbd> key) to make it act like it's always pressed, similar to how the Caps Lock key typically behaves. This will allow you to type more than one special character in one run. If you don't need to use the key any longer, you press it again (for the third time) to release it from serving the sticky key function.

**That's in theory.**

<!--more-->

This seemed like the perfect solution for my friend, but there's one problem: **it doesn't work!** At least, not as I expected.

I tested sticky keys on macOS (Sonoma) and Windows (11), and they worked as expected. However, on ChromeOS, sticky keys malfunctioned across various devices. I checked Chromebooks with both built-in and external keyboards, as well as ChromeOS Flex on PC.

I decided to investigate that matter.

After reading more about it, I realized that we, as users, had oversimplified a few things based on our experience.

It's common knowledge that pressing the left <kbd>Alt</kbd> key in combination with <kbd>F4</kbd> forcefully closes an application or window. Conversely, on a Polish keyboard layout, pressing the right <kbd>Alt</kbd> key with <kbd>e</kbd> produces the letter `ę`.

The key positioned on the left side of the spacebar is the regular <kbd>Alt</kbd> key.  The other key, on the right side, is typically called <kbd>Alt Gr</kbd> (or **Alt Graph**). This <kbd>Alt Gr</kbd> key is responsible for invoking special characters specific to different languages, especially useful for those who don't use an English keyboard layout.

When Sticky Keys are enabled on Chromebook (ChromeOS or ChromeOS Flex), it incorrectly recognizes both the left and right keys as ordinary <kbd>Alt</kbd> keys.

I suspected this might be an issue only with external keyboards, but I also checked a branded Chromebook's built-in keyboard. It also has the <kbd>AltGr</kbd> key on the right side of the spacebar.

When typing with regular key combinations or using multiple fingers, the right <kbd>Alt</kbd> key works correctly as the <kbd>AltGr</kbd> key. However, when Sticky Keys is enabled, it treats the right <kbd>Alt</kbd> as a regular <kbd>Alt</kbd> key, and in such a way it's highlighted.

This is confirmed by on-screen notifications that appear in the top-left part of the screen when Sticky Keys are on and the relevant key is pressed, as seen below.

[![Sticky Keys notification when pressed n ChromeOS Flex](sticky_keys_chromeos.png)](sticky_keys_chromeos.png)

Here's the confusing part: the screenshot shows an `altgr` option, even though Chromebook treats both single and double presses of the left or right <kbd>Alt</kbd> key as a standard <kbd>Alt</kbd> key when Sticky Keys are on. This contradicts what's displayed on the keyboard itself.

When I activated the on-screen keyboard, it correctly showed the <kbd>AltGr</kbd> key positioned to the right of the spacebar, just as a physical keyboard should have.

If Sticky Keys are supposed to work with **AltGr**, then how do we actually use them together?

In my research, I found a website [keyjs.dev](https://keyjs.dev/) that allows detecting what key has been pressed.

When I press the left <kbd>Alt</kbd> key, I get responses `e.key=Alt` and `e.code=AltLeft`. However, when I press the right <kbd>Alt</kbd> key (the <kbd>AltGr</kbd> key), I get `e.code=AltRight` but still `e.key=Alt`. This is likely where the confusion with Sticky Keys arises.

Following this up, I found a discussion on  [Reddit](https://www.reddit.com/r/chromeos/comments/lel1ju/custom_russian_colemak_phonetic_keyboard/) where someone wanted to create a custom Russian keyboard layout using <kbd>AltGr</kbd> for Cyrillic characters. This suggests that adding custom layouts to ChromeOS might be possible.

Part of his code looks like:
```
var AltGr = { PLAIN: "plain", ALTERNATE: "alternate" };
var Shift = { PLAIN: "plain", SHIFTED: "shifted" };

var lut = {
"KeyE": { "plain": {"plain": "ш", "shifted": "Ш"}, "alternate": {"plain": "щ", "shifted":"Щ"}, "code": "KeyE"},
};
```

This code defines the characters produced by different key combinations: pressing just the <kbd>e</kbd> key, pressing <kbd>e</kbd> with <kbd>AltGr</kbd>, and pressing <kbd>e</kbd> with <kbd>Shift</kbd>.

For my scenario, this will look this:

```
var lut = {
"KeyE": { "plain": {"plain": "e", "shifted": "E"}, "alternate": {"plain": "ę", "shifted":"Ę"}, "code": "KeyE"},
};
```

While creating a custom layout is a solution, it's important to remember that the keyboard itself recognizes <kbd>AltGr</kbd> correctly when producing the `ę` symbol. The problem lies with Sticky Keys treating <kbd>AltGr</kbd> as a regular <kbd>Alt</kbd> key when enabled.

After reaching out to the Google Accessibility Team for help, I decided to explore the issue further while I awaited their response.

Based on [another discussion on Reddit](https://www.reddit.com/r/chromeos/comments/e5qi4i/creating_custom_keyboard_layout_or_customizing/), it seems ChromeOS uses `e.code` to differentiate between the left and right <kbd>Alt</kbd> keys.  The question remains: why doesn't Sticky Keys recognize the right <kbd>Alt</kbd> (which is actually <kbd>AltGr</kbd>) and utilize it correctly?

Is there a way to modify `e.code=AltRight` so that Sticky Keys recognize it as <kbd>AltGr</kbd>?

I [searched](https://github.com/search?q=repo%3Agoogle%2Fextra-keyboards-for-chrome-os%20AltGr&type=code) the official Google GitHub repository for extra keyboards for ChromeOS. Looking for instances of <kbd>AltGr</kbd>, I found it included for some languages.

I found something interesting in the `bepo` keyboard layout, which is designed for optimized French typing:

```
function updateAltGrState(keyData) {
  altGrState = (keyData.code == "AltRight") ? ((keyData.type == "keydown") ? AltGr.ALTERNATE : AltGr.PLAIN)
                                              : altGrState;
```

I found similar references to <kbd>AltGr</kbd> usage in Esperanto and Dvorak (both left and right-handed layouts), as well as some extended functionalities within the UK Extended layout.

In the file `composekey/background.js` I noticed an entry:

```
// Default to keeping the modifier: otherwise, the default AltRight compose
// key conflicts with AltGr in international layouts.
keepModifier: true,
```

Based on that finding, I looked into the [Compose Key for Chrome OS](https://github.com/google/extra-keyboards-for-chrome-os/tree/1f644e9f056fae74078f0d35000e2e906ae9475f/composekey) to see what it does.

So, here's what I learned from the Compose Key info...

> _This extension turns the right Alt key (the trigger key is configurable) into a Compose key on a variety of different English keyboard layouts including US, Canadian, and UK._

This suggests a further step is needed to enable the **AltGr** functionality. Simply adding a layout, like English (UK) with Dvorak, doesn't address the issue of Sticky Keys not recognizing the right <kbd>Alt</kbd> key as <kbd>AltGr</kbd>.

I found the [Compose Key extension](https://chromewebstore.google.com/detail/composekey/iijdllfdmhbmlmnbcohgbfagfibpbgba) in the Chrome Web Store and decided to install it.

As we read:

> _This extension adds several keyboard layouts with a compose key to Chrome OS._

I was not optimistic when I read one of the comments left:

> _No longer works on Chrome OS & Chrome OS Flex version Version 99.0.4844.94_

**And the comment was right.**

The instructions on enabling the Compose Key input method point to settings that no longer exist in the same way.

[![ComposeKey Initial Setup](composekey_initial_setup.png)](composekey_initial_setup.png)

Fortunately, I was able to find the necessary input method within the settings menu.

[![Add input method ComposeKey](add_input_method_composekey.png)](add_input_method_composekey.png)

After logging out and logging back in as recommended, I hoped to see the on-screen notification for Sticky Keys finally recognize <kbd>AltGr</kbd> correctly. **Unfortunately, this wasn't the case.**

Since I haven't heard back from the Google Accessibility Team yet, I've decided to ask this question elsewhere.

I began my search on the [Chromium community forum](https://support.google.com/chromebook/thread/259227846/how-to-invoke-altgr-with-sticky-keys-turned-on). There, it became clear that this appears to be a bug within the system itself."

Following the recommendation, I've created a Tracked Bug ([#325633307](https://issuetracker.google.com/issues/325633307)) to see how this progresses. In the meantime, I've also updated the Google Accessibility Team via email about the opened case in case they'd like to be kept informed.

While waiting for a response, I decided to test Sticky Keys with different language input methods. I installed several and observed their behaviour. Unfortunately, none of them reported the activation of <kbd>AltGr</kbd> when pressing the right <kbd>Alt Gr</kbd> key on the keyboard.

**I'm at a dead end for now. Maybe a fresh start later will help.**

{{% ads-in-article %}}

Despite my tracked bug not making any progress, I received further communication from the Google Accessibility Team. They requested some additional information to help them troubleshoot the issue.

Meanwhile, my tracked bug gained traction within the Google team, and after a month, it was addressed.

The team clearly understands the issue and has begun working on a fix.

Their investigation identified the root cause of the problem. A potential fix has been implemented for testing purposes and integrated into the development version of ChromeOS 125.0.6380.0.

I can't test the fix just yet. While my laptop runs ChromeOS in the Dev Channel, it's on version 124.

Assuming the fix is successful, I wonder how long it will take for it to reach the stable version of ChromeOS. Currently, the stable version is 122, Beta is 123, and Dev is 124.

**It's time to wait.**

The day finally arrived! My device updated to the development version 125.0.6398.0. After restarting, I was eager to see if the **AltGr** recognition issue had finally been fixed.

**And it does!**

Success! With Sticky Keys enabled, pressing the right Alt key (<kbd>AltGr</kbd>) now shows `altgr` in the notification, as expected.

[![Fixes Sticky Keys in ChromeOS 125 with working AltGr](sticky_keys_chromeos_altgr.png)](sticky_keys_chromeos_altgr.png)

A quick test with some text composition confirms it: the fix is working perfectly!

Wow, I'm really impressed that they took my issue seriously and fixed it like that! I wasn't sure it would happen at first, but the Google team really came through.

I revisited the website [keyjs.dev](https://keyjs.dev/) to confirm the fix. Now, pressing the right Alt key (<kbd>AltGr</kbd>) returns `e.key=AltGraph` and `e.code=AltRight`. Previously, it only displayed `e.key=Alt` and `e.code=AltRight`.

While I'm happy to report the issue is resolved for me, my friend is unfortunately still facing the problem.

The fix is currently in version 125, while the stable ChromeOS version is 123 (two versions behind). I inquired with the team about the possibility of backporting this fix to the stable channel sooner, rather than waiting for version 125's official release.

While backporting might be unlikely, there's always a chance. In the meantime, we'll have to wait for the stable release.

**No worries! At least it's fixed, and that's going to be a big improvement for my friend's writing.**


---
## When things start to fail... adding Multipath Routing to Cloudflare Email Routing with Email Workers
- **URL:** https://dariusz.wieckiewicz.org/en/when-things-start-to-fail-cloudflare-email-routing/
- **Date:** 2024-03-29
- **Tags:** Cloudflare, Email Routing, Email Workers, Gmail, Outlook, Gmailify, Gomailify

### Content

Thanks to Cloudflare Email Routing, I can accept and send emails in my domain, but still manage them on my ordinary Gmail account. This all is set as I wrote down in my post titled [Email in your own domain with Cloudflare (and Gmail)](/en/cloudflare-email-in-your-own-domain/)

Over the last week, I faced an issue with emails not being delivered to my mailbox.

Firstly I thought that there was something wrong with Gmail service blocking forwarded messages. The same though had plenty of people using this service and writing their experiences all over the internet.

<!--more-->

There is a post on [Cloudflare Community website](https://community.cloudflare.com/t/transient-error-421-4-7-0-when-forwarding-emails-to-gmail/629941) where started complaining about it and the loss in emails specifically when using Email Routing from Cloudflare.

When the message was rejected on Cloudflare it was reported as **Delivery Fail** and thrown below error message:

```
transient error (451): 4.7.650 The mail server [104.30.8.112] has been temporarily rate limited due to IP reputation.
```

There is no possibility to preview the message on Cloudflare or do anything with it. Because of that, it's hard to diagnose the problem.

As much as I like Cloudflare, I, like other users were thinking about resigning from this solution with some more reliable options.

Going back to the error message, as I thought that this was a Gmail restriction that caused this, I quickly been able to change my routing rule to forward my emails to my Outlook email.

Typically, email servers that haven't been able to deliver messages to the destination will keep trying again and again before dropping it. Redirecting from Gmail to Outlook will change the route and on the next repeat delivery attempt mail shall flow in another direction (Outlook).

This worked! Through a few days, I got most of the emails that failed to be delivered to Gmail.

> Surprisingly, all of them have been delivered marked as Spam (Junk) by Outlook servers, hence there is something more here than just a grit between Cloudflare and Gmail.

However, another day came and I saw a similar issue reported by Microsoft servers:

```
upstream (outlook-com.olc.protection.outlook.com.) temporary error: Unknown error: transient error (451): 4.7.650 The mail server [104.30.8.115] has been temporarily rate limited due to IP reputation.
```

**That cannot be a coincidence and something must be wrong with Cloudflare.**

People start their complaints all over the place claiming that Cloudflare is not interested in fixing it. As easy as it sounds, fixing this kind of issue may not be as straightforward as can be imagined.

Because the service is supplied free of charge it is difficult to directly ask for help, but some users, who decided to subscribe to paid plans also complain about the lack of support received in that matter.

Days passed and the blocking situation on the Gmail end seemed to return to the previous rate where the email was blocked, and when re-tried after, typically, 20 minutes was accepted and forwarded.

However, the question remains about how serious consequences this unreliability can be for us and what we can do about it.

The ability to receive emails in my domain is quite critical. I have been using my email in my domain for years when I was with Google Workspace (Free version) and have been using it almost everywhere.

Independently if that causes any material loss or not, it's hard to afford to lose some crucial communication only because some IPs on the Cloudflare end have been classed as spam.

Mitigation (temporary redirects) has been put in place, but in the meantime, I have been looking for some alternative solution in case in future this will happen again.

> If you are just a single user in your domain, choosing another solution on the market (paid) may be straightforward. However, when you start building your users (family), paying extra for each user suddenly becomes very expensive unnecessarily. Choosing the right service needs to be considered at the beginning. 

Having in mind my budget, I looked into the paid solution to utilise email forwarding to Gmail called [Gomailify (Gomailify.com)](https://www.gomailify.com) (previously Gmailify.com). Gomailify charges $12/year for up to 2 linked Gmail accounts, then $6/year for each additional. The service, similar in name to Google's solution, but different in functionality, is created by Mercata Sagl based in Switzerland.

The author of this service creates it with Gmail in mind. The communication is only with Google servers and is done with IPv6 as a primary way, falling back to IPv4 when needed. It supports SPF, DMARC and DKIM under specified domains. Compared to Cloudflare Email Routing, where I can set SPF and DMARC, I haven't found a way to use DKIM with Gmail and this is probably where the main issue in this forwarding service stands.

**But is it?**

> Cloudflare signs each email, that lacks DKIM, with their key and in the report, it shows that the message originates from `email.cloudflare.com`. 

**Somebody in the discussion said something that made me think before rushing with my decision to switch the boat.**

> "I worry about reliability and security with both gomailify and forewardemail…
> 
> Both feel like 1 man shows that grew out of a hobby. Which is usually great for OSS projects, but for a fundamental and critical service like email for entire domains, I dunno… Who knows if their infrastructure could crumple under attack, or if it could be an attack vector for someone to snag email 2FA codes, etc… The indispensable man could go on vacation or die…"

[![Cloudflare Radar Malicious Emails](cloudflare-radar-email-malicious-xy-20240325-20240325.png)](cloudflare-radar-email-malicious-xy-20240325-20240325.png)

As a part of my utilisation of other Cloudflare services, I have been looking into their Cloudflare Radar and chart for [Email Security](https://radar.cloudflare.com/email-security). During the weekend when the issue was at its peak, it showed that 50% of emails worldwide had been classified as a potential threat. **Coincidence?**

It's easy to jump to conclusions and start saying bad words about the service that is provided free of charge. Of course, there is room for improvement, but if something bigger happening on the horizon that nobody understands why, mitigation practices and **patience** shall be the first line of defence.

A discussion that was carried out in the community became, by some of the people, a rant on Cloudflare (now deleted by that person). A rant full of demands for service, that is supplied as it is, without any charge and obligations. Some people forget about it.

## Cloudflare Email Routing with Email Workers - Approach 1

> Spoiler alert: Approach 3 is the one I personally use.

The discussion is great when there is a conclusion that helps everybody, and this one [arrived](https://community.cloudflare.com/t/transient-error-421-4-7-0-when-forwarding-emails-to-gmail/629941/).

One user reminded, through his [other post](https://community.cloudflare.com/t/my-email-worker-catchall-backup-routing-plus-addressing-and-subdomain-addressing/634156), that there is an option to supercharge Cloudflare Email Routing with Email Workers.

```js
export default {
  async email(message, env, ctx) {

  //alias lists using RegEx. Examples below will allow for plus-addressing and subdomain addressing.
  // (I have configured wildcard (*) DNS records to catch all sub-domains). 
    const user1_alias = [
      "user1+.*@mydomain.net",
      ".*@user1.mydomain.net",      
      ];

    const user2_alias = [
      "user2+.*@mydomain.net",
      ".*@user2.mydomain.net",      
      ];

  //primary emails
    const user1_primary = 'user1@gmail.com';  
    const user2_primary = 'user2@gmail.com';  
    const user3_primary = 'user3@gmail.com';  

  //backup emails (still going to primary email, but via improvmx instead of directly from Cloudflare).
  //you will need to create a subdomain (ex. 'imx') setup using improvmx, and improvmx aliases pointed to primary email
    const user1_backup = 'user1@imx.mydomain.net';  
    const user2_backup = 'user2@imx.mydomain.net';   
    const user3_backup = 'user3@imx.mydomain.net';  
  
  //final catchall if primary and backup fails
    const user3_outlook = 'user1@outlook.com';  

  //This tests alias against message "To:", showing the value of [true] if matching.
    const is_user1_alias = RegExp(user1_alias.join("|"), "i").test(message.to);
    const is_user2_alias = RegExp(user2_alias.join("|"), "i").test(message.to);
  
  //action to take 
    //inside Try is to route to backup (ImprovMX to Gmail) to get by Cloudflare to Gmail issues.
    //outside Try is to route to Outlook (final catchall) if both primary and backup fails.
    var gmail_error;
    try {
      switch (true){
        case (is_user1_alias):
          try {await message.forward(user1_primary);}
          catch(gmail_error) {await message.forward(user1_backup);}
          break;
        case (is_user2_alias):
          try {await message.forward(user2_primary);}
          catch(gmail_error) {await message.forward(user2_backup);}
          break;
        default:
          try {await message.forward(user3_primary);}
          catch(gmail_error) {await message.forward(user3_backup);}
          break;
      }
     }
    catch(improvmx_error){
      try {await message.forward(user3_outlook);}
      catch(outlook_error) {
        message.setReject(outlook_error.message);
        return message.setReject(outlook_error.message + '\n' + improvmx_error.message + '\n' + gmail_error.message);
        }
    }
  }
}
```

> Saving this, and the below codes for my references in case it will disappear from the community thread.

He has set email workers to route any emails that fail to be delivered through Cloudflare service to be delivered using another forwarding service, [ImprovMX](https://improvmx.com).

> He set a subdomain to his main domain as an email service on ImrovMX where the main domain was still managed by Cloudflare. 

Additionally, the Worker added the ability to catch and deliver emails to other subdomains, which is not possible directly through Cloudflare Email Routing, as well as introduced the ability to catch emails with `+` symbols in email addresses, which in the Gmail environment are used to categorise emails.

## Cloudflare Email Routing with Email Workers - Approach 2

Another user in [the same thread](https://community.cloudflare.com/t/my-email-worker-catchall-backup-routing-plus-addressing-and-subdomain-addressing/634156/13) created another single email worker to deal with emails by incorporating catch-all technique.

```js
export default {
    async email(message, env, ctx) {

        // defining all alias to user mappings we have
        const users = [{
            alias: [
                "first@firstdomain.de",
                "first@seconddomain.de",
            ],
            primary: "first@gmail.com",
            backup: "first@gmx.de",
        }, {
            alias: [
                "second@firstdomain.de",
            ],
            primary: "second@gmail.com",
            backup: "second@gmx.de",
        }, {
            alias: [
                "third_alias1@firstdomain.de",
                "third_alias2@firstdomain.de",
            ],
            primary: "third@gmail.com",
            backup: "third@gmx.de",
        }, {
            alias: [
                "fourth@firstdomain.de",
            ],
            primary: "fourth@gmail.com",
            backup: "fourth@gmx.de",
        }, ]

        // setting the target_user as our catch all user
        let target_user = {
            primary: "catchall@gmail.com",
            backup: "catchall@gmx.de",
        }

        // checking if we have a user matching and overwrite the target_user with it
        users.forEach(user => {
            if (RegExp(user.alias.join("|"), "i").test(message.to)) {
                target_user = user;
            }
        });

        // sending mail out, first to google and on error to gmx
        let reject_reason;
        try {
            await message.forward(target_user.primary);
        } catch (gmail_error) {
            reject_reason = gmail_error.message;
            try {
                await message.forward(target_user.backup);
            } catch (gmx_error) {
                reject_reason = gmx_error.message + "\n" + reject_reason;
                message.setReject(reject_reason);
            }
        }
    }
}
```

Both solutions are great as adding the ability to have a backup route if emails, for some reason, are rejected.

{{% ads-in-article %}}

## Cloudflare Email Routing with Email Workers - Approach 3

Going back to the main community thread [the other user](https://community.cloudflare.com/t/transient-error-421-4-7-0-when-forwarding-emails-to-gmail/629941/91) provided a very simplified code for email worker that utilising simple approach for a backup route.

```js
export default {
  async email(message, env, ctx) {
    await message.forward("your gmail address").catch((err) => {
      return message.forward("your alternative mailbox address");
    });
  }
}
```

I thought about going into a more complex approach (1 or 2) but ended up with a simplified one as it **simply works**.

## Simplified approach in practice

Through **Email** > **Email Routing** > **Destination Addresses** I have added (and verified) the Gmail addresses of all users I got there as well as their alternative email addresses (Outlook).

> You need to have added and verified all routes that you will specify in your Email Workers. If not the worker simply fails to deliver.

Following that, I created a few workers for each user and each scenario.

In **Routing rules** I changed each action for each custom address from **Send to an email** to **Send to a Worker** and specified worker.

In such a way, I utilised simple rules that stand as follows.

Anybody sending an email to my main address `dariusz@` (in my domain) will be routed to my `@gmail.com` address. If for some reason Cloudflare will report an error in forwarding, it will try to re-route to `@outlook.com`.

> With a little tinkering it is possible to set a 3-way approach, when the first two fail the third and last address is tried. This was initially considered in Approach 1. For most people, a single backup route shall do its job.

Successfully routed (through workers) emails will be marked in Cloudflare **Activity log** as _Dropped_. If both routes fail, it will show an error and will be marked as _Delivery Failed_.

[![Cloudflare Email Routing summary (March 2024)](Cloudflare_Email_Routing_summary_March_2024.png)](Cloudflare_Email_Routing_summary_March_2024.png)

Successfully forwarded emails, without workers, were marked as _Forwarded_ in the Activity Log and are as _Dropped_ with Email Workers. This may be a bit confusing, but, as one person on the community forum rightfully pointed out, it's just a naming thing by Cloudflare.  We just need to re-think the word _Dropped_ as _mail successfully dropped to mailbox_. **Happy with that interpretation :)**

> As noticed in November/December 2024, Cloudflare changed how emails are marked when delivered through Email Workers. Some are still marked as _Dropped_, but more of them are marked, as they should be in the first place, as _Forwarded_. A positive change that will not confuse its users.

## Managing main and backup route in one place - Google Gmailify

When you have a nicely set main address (in Gmail) along with your backup (in Outlook) it will be nice to have all email just in one place.

In the Outlook environment, we can easily set a forwarding rule, so any email landing in _Inbox_ will be forwarded, this time by Microsoft servers, back to our main Gmail address.

**I tested, and this is working well, but...**

There is one issue with _just_ enabling Forwarding in Outlook. 

Only emails successfully landed in Inbox are forwarded further. If any of our emails are forwarded through Cloudflare to our alternative email will land in the Junk folder, this will stay there (only for 10 days, as per Outlook retention policy).

I don't see myself going into Outlook from time to time just to check the Junk folder, hence I utilised Gmailify to help with that.

I mentioned Gomailify at the beginning (previously Gmailify.com), but this time I am referring to [Gmailify, a service offered by Google](https://blog.google/products/gmail/gmailify-best-of-gmail-without-gmail/). **I know, it's confusing!**

Because of the same name for two different services done by two different authors, this is why did the creator of [Gomailify.com](https://gomailify.com) put this on his website:

> **Not Your Google's Gmailify**
>
> Gmail has a feature named Gmailify. It serves a different purpose though, linking Outlook and Yahoo accounts with Gmail. We link Gmail with custom domains instead. The name conflict is coincidental.

**Gmailify from Google** allowing to add your Outlook account in such a unique way, that it will **not** just fetch messages from another email like it is when setting it through POP3 or IMAP protocol. Gmailify will **integrate** Outlook email into your Gmail environment.

> Google recently killed Gmailify a well as fetching emails from other mailboxes using POP3 protocol. You can read it on their official page: [Learn about upcoming changes to Gmailify & POP in Gmail](https://support.google.com/mail/answer/16604719?hl=en).

If something lands in your Junk folder on Outlook, once synced on the Gmail environment (it's not instant), you will see this message in your Junk folder in Gmail. **Great!**

If you remove the message from the Junk folder from Gmail end, it will be removed from Outlook as well.

**Thanks to forwarding set in Outlook for all incoming messages and Gmailify by Google, you can manage your main email and your backup email from a single point, Gmail.**

## Different approach

With the introduction of simple routing with Cloudflare Email Workers, I asked myself, is it possible to route to more than one email address?

In [another post in the community](https://community.cloudflare.com/t/routing-an-email-to-more-than-one-address-from-the-same-user/437169/3) I found out the straight and simple answer to how to achieve that.

```js
export default {
  async email(message, env, ctx) {
    const forwardList = ["email1@gmail.com", "email2@gmail.com"];
    for(const email of forwardList){
      await message.forward(email);
    }
  }
}
```

With a small tinkering, the worker can become an interesting method of serving a purpose asked by Cloudflare users for some time, which is routing an email to more than one address from the same user (custom address).

I am not an expert but the _rough_ idea will be:

```js
export default {
  async email(message, env, ctx) {
    const forwardList = ["email1@gmail.com", "email2@gmail.com"];
    for(const email of forwardList){
      await message.forward(email).catch((err) => {
      return message.forward("email@outlook.com");
    });
    }
  }
}
```

With multiple backups:

```js
export default {
  async email(message, env, ctx) {
    const forwardList = ["email1@gmail.com", "email2@gmail.com"];
    const backupList = ["email1@outlook.com", "email2@outlook.com"];
    for(const email of forwardList,backup of backupList){
      await message.forward(email).catch((err) => {
      return message.forward(backup);
    });
    }
  }
}
```

I cannot guarantee that it will work, as this may have some negative effects if one email fails and another does not. 

I am using a Cloudflare Email Route from my domain to a private Google Group email address from which I propagate messages to multiple users.

--- 

A last word to this post is the count for use of Cloudflare Workers.

We have a limit on free accounts of **100,000** workers' requests **per day**. Interesting is that, when I set my rules, after like 50 emails forwarded (*Dropped*), the number of requests goes close to 600. Unsure about how exactly workers' requests are counted, but I think I shall be well within the limit for my private use.

Regards.


---
## Filtered, Secure DNS with Cloudflare One, Zero Trust and OpenWrt
- **URL:** https://dariusz.wieckiewicz.org/en/filtered-secure-dns/
- **Date:** 2024-03-24
- **Tags:** OpenWrt, Secure DNS, Filtered DNS, DNS, DNS over HTTPS, DoH, HTTPS DNS Proxy, Cloudflare, Zero Trust, Firewall Policies, Cloudflare Radar

### Content

Cloudflare, let’s be honest, is an incredibly generous organization, offering a range of services that we rarely have to pay for. Individuals, families, small or medium-sized businesses can use their technology without having to spend money unless they need to.

Among the range of services, DNS servers (1.1.1.1) and DNS encryption service deserve recognition. In combination with their software available on a range of platforms, not only can we speed up our internet surfing, but we can also increase our security.

OpenWrt on the other hand is an incredible software designed to increase the security of our network device, which is the router, and also adds the ability to expand the capabilities of our hardware.

By combining Cloudflare with OpenWrt software and an additional software package, we can introduce [Secure DNS](/en/secure-dns/) to our network, which I wrote about some time ago.

Moreover, when we need to access our local network resources from anywhere in the world, we can use the Cloudflare Zero Trust service by creating a [secure tunnel](/en/adding-cloudflare-tunnel-to-openwrt-router/).

Zero Trust, offered as part of our Cloudflare account (and in the free version), is not just a "VPN" tunnel. Zero Trust also offers a number of other options. One of them is the ability to create "your own" secure DNS server.

<!--more-->

Just like 1.1.1.1 without much configuration, it can secure our DNS queries, it doesn't allow us to enter anything else.

On the DNS side, additional restrictions, security measures, or blockings can be introduced. This happens, not necessarily with our consent, when we use DNS servers provided by our Internet service provider.

What if we wanted to introduce these types of restrictions on our network, except that we would decide what is blocked and what is not?

We already have secure DNS using Cloudflare (1.1.1.1) and OpenWrt. If we have our Zero Trust tunnel set up, then we already have some of the infrastructure in place that will allow us to gain more control on our end.

Secure DNS from Cloudflare (1.1.1.1) by default will not block any sites that spread hate, share pornography, sell drugs or weapons to anyone. The Internet is a place where we can have a good time, but just like in real life, we can also encounter its dark side.

In the case of companies (but also within your household), we cannot afford for our employees to use the equipment entrusted to them for purposes that could expose us to serious legal consequences. Therefore, most companies have a so-called IT policy in place, informing their employees about the possibility of monitoring and blocking undesirable behavior.

While monitoring is not a problem, blocking may require additional procedures, hardware or specific software. What if I told you that the solution is within reach thanks to **Zero Trust**.

Well, as part of Zero Trust, we can set up our own secure DNS, which will be operated by Cloudflare, just like with the 1.1.1.1 service. As part of it, we will be able to add rules that allow us to block some of the Internet traffic, from the DNS level, that could expose us to serious consequences.

All of this is possible with the ability to manage in the Zero Trust (Cloudflare One) panel and track what's happening. Plus, all of this is available for free (at least for our basic needs).

If our employee has a gambling problem and instead of working, he spends time (wasting his own and the company's money) on betting, we can block it.

If another employee visits sites that could expose their device (that they use) or themselves to becoming a victim of phishing or other similar threats, we can also prevent this by introducing appropriate restrictions.

Of course, any restrictions are as good as the rules that are introduced to block them. The Internet evolves every day and they (the rules) have to be updated a little bit. It would be nice if we didn't have to worry about this, but we would leave it to professionals.

And that's where the fun is. Using available solutions, we will secure our network, specify what we want to block, and the rest will be taken care of by professionals - Cloudflare. Here's how we can do it.

---

Below I will describe a method to implement **filtered, secure DNS** on the side of our OpenWrt router, however, it does not mean that this is the only method.

If our router does not have the ability to enhance it with OpenWrt software, we can still use the possibilities offered by Cloudflare.

In the case of devices using different connections, outside our home network, we can also implement the offered solution through dedicated applications, modifying network settings or changing our browser settings.

While I will mainly focus on the OpenWrt router, I will touch on other available solutions at the end. Since I have described some of the steps in my other posts about [OpenWrt](/en/tag/openwrt/), I will not repeat myself too much, but I will refer to them in the appropriate step.

## Secure DNS Installation

First, we need to [install **DNS over HTTPS** support on our OpenWrt router](/en/secure-dns/#dns-over-https-openwrt) according to the guide.

At this stage, we should have **Secure DNS** set using Cloudflare (1.1.1.1) and Google (8.8.8.8).

If everything works as I described in the link above, we can continue the fun.

Go to [Cloudflare Zero Trust](http://one.dash.cloudflare.com).

## When we have a permanent (external) IP address (version 4)

If our router has a fixed IP address, we can use it to obtain additional IP addresses (version 4) for DNS servers, which we can set on our router interfaces. This is to protect DNS query leaks. When our encrypted DNS is not working, then by default our device will use the DNS addresses associated with the service, which will continue to filter queries.

First, go to the **Gateway** > **DNS Locations** tab.

[![Gateway DNS Locations Default Location](Gateway_DNS_Locations_Default_Location.png)](Gateway_DNS_Locations_Default_Location.png)

There we will already have the **Default Location** set, which we need to modify.

Click on the three dots on the right and select the option **Edit**.

[![Gateway DNS Locations Default Location Add IP](Gateway_DNS_Locations_Default_Location_Add_IP.png)](Gateway_DNS_Locations_Default_Location_Add_IP.png)

In the **Endpoint protection** tab, you can select **IPv4 endpoint filtering and location matching** by IP address. When we click on it, we should get our external IP address.

> This step is optional. Turning this on will resolve DNS queries only by the source IPv4 addresses added below. DNS queries will match the location with the most specific source IP network. If you have a dynamic IP or more than one connection on your router, skip that step.

---

To make sure that this address is correct, let's log into our router via SSH and execute the following command:

```bash
curl -s 'http://icanhazip.com'
```

> Sometimes it may happen that we have a secure DNS enabled, e.g. Cloudflare Warp, or we use Apple Private Relay and our original IP is filtered. DNS over HTTPS installed on our router can also affect this. During the setup it may be necessary to temporarily disable this service.

At this point we will save our configuration.

> If we do not have a static IP address, or we don't want to turn on IPv4 endpoint filtering and location matching, we also need to turn off **IPv4 DNS** in the **DNS endpoints** tab, which is a shared IP address. We will **lose** the option to use the below **Individual address for configuring Secure DNS** over IPv4 (unless you upgrade your Cloudflare Plan), but we will still have **DNS over HTTPS**, which can be more than enough.

## Individual address for configuring Secure DNS

Go to **Gateway** > **DNS Locations** and click on **Default Location**.

[![Gateway DNS Locations Default Location data](Gateway_DNS_Locations_Default_Location_data.png)](Gateway_DNS_Locations_Default_Location_data.png)

In the window that will appear on the right, we will see the addresses assigned to us.

If we have and have set our fixed IP address in the default location, as I described in the previous step, in the **IPv4** section we will see the addresses of our DNS, which we will need in the next step (typically `172.64.36.1` and `172.64.36.2`)

In the **IPv6** section we will get the IP address of the DNS version 6 server assigned to us (in the form `2a06:98c1:54::`)

In the **DNS over HTTPS** section we will receive a link to the configuration of a secure DNS server (in the form of `https://{unique_link}.cloudflare-gateway.com/dns-query`), which we will use on our router.

We will need all this in the next stage of configuration.

## OpenWrt Router Setup - HTTPS DNS Proxy

We log in to our router from a web browser and go to **Services** > **HTTPS DNS Proxy**.

[![OpenWrt Services HTTPS DNS Proxy](OpenWrt_Services_HTTPS_DNS_Proxy.png)](OpenWrt_Services_HTTPS_DNS_Proxy.png)

In the **HTTPS DNS Proxy — Instances** section, remove the default **Cloudflare (Standard)** and **Google** using the **Delete** button on the right.

Then click the "add" button (**Add**) and from the service provider (**Provider**) select the option at the very bottom of the list — custom (**Custom**).

[![OpenWrt Services HTTPS DNS Proxy Custom](OpenWrt_Services_HTTPS_DNS_Proxy_Custom.png)](OpenWrt_Services_HTTPS_DNS_Proxy_Custom.png)

In the parameter section (**Parameter**) we paste the address that we read earlier in the **DNS over HTTPS** section on the Cloudflare side.

```
https://{unique_link}.cloudflare-gateway.com/dns-query
```

We leave the listening address `127.0.0.1` and port `5053` as suggested.

> Personally, I prefer to specify (type) it there.

Then click the green **Save** button.

[![OpenWrt Services HTTPS DNS Proxy Custom set](OpenWrt_Services_HTTPS_DNS_Proxy_Custom_set.png)](OpenWrt_Services_HTTPS_DNS_Proxy_Custom_set.png)

On the next screen I click **Save & Apply**.

> If our ISP also provides us with an IPv6 address, then it's worth adding, similarly to the above setup, a DNS response over IPv6. Then, we add the same configuration, on the same listening port (`5053`), but enter `::1` in the listening address.

Finally, we make sure that our **HTTPS DNS Proxy** service is enabled (**Enabled**) in the **Service Control** section and started (**Start**).

This way, our personal secure DNS was enabled and we gained the ability to filter on the Cloudflare Zero Trust side, which I will discuss in a moment.

---

We can see that our DNS queries go through our personal secure DNS server in the **Analytics** > **Gateway** section on the [Cloudflare Zero Trust](http://one.dash.cloudflare.com) page.

[![Analytics Gateway analytics](Analytics_Gateway_analytics.png)](Analytics_Gateway_analytics.png)

## OpenWrt Router Setup - Network Interfaces

Our DNS queries work securely when our **HTTPS DNS Proxy** service is up and running. In case it goes down or stops working for some reason, it's a good idea to have a backup plan.

If we have a permanent external IP address, it is worth using the DNS addresses obtained in the IPv4 and IPv6 sections.

To do this, in the administration panel of our router, go to the **Network** > **Interfaces** tab.

First, we click on the "edit" button (**Edit**) on our **wan** internet connection.

In the **Use custom DNS servers** field (in the **Advanced Settings** tab) we enter our DNS servers obtained earlier (`172.64.36.1` and `172.64.36.2`).

> If you don't see the **Use custom DNS servers** box, you probably have the **Use DNS servers advertised by peer** box checked. After unchecking it, you'll see the option to enter addresses.

We finish by clicking the **Save** button.

Similarly, we change our **wan6** interface with the IPv6 DNS address obtained during configuration (optional).

Additionally, we enter the IPv4 and IPv6 addresses (both) in the **lan** interface configuration.

We finish the whole thing by clicking the **Save & Apply** button.

---

This way we have everything set up. There is no need to change anything on the side of our clients (users and their devices).

Before we go any further, I recommend enabling one more feature in our **HTTPS DNS Proxy** package, namely **DNS Hijacking**.

## DNS Hijacking in HTTPS DNS Proxy

Before I continued configuring filtering, I went back to the **HTTPS DNS Proxy** settings on my router and changed the **Force Router DNS** setting from **Let local devices use their own** to **Force Router DNS server to all** to ensure that all users (devices) were using the same secure DNS server.

{{% ads-in-article %}}

## Filtering

It's time to add DNS query filtering for our users and their devices. To do this, we go to the [Cloudflare Zero Trust](http://one.dash.cloudflare.com) panel.

In the **Gateway** section, we go to **Firewall Policies**. Here, in the DNS section, we will add our rules.

[![Gateway Firewall Policies](Gateway_Firewall_Policies.png)](Gateway_Firewall_Policies.png)

Cloudflare has different methods of filtering traffic (**Selectors**). Personally, I will focus on two.

1. **Security Categories**
2. **Content Categories**

Within the security category, we have the ability to block things like traffic classified as Spam, Spyware, Phishing, or Malware.

These are the things we should pay attention to first.

Creating a new rule is very simple. Click the button to add a new rule (**Add DNS Policy**).

[![Gateway Firewall Policies Add DNS Policy](Gateway_Firewall_Policies_Add_DNS_Policy.png)](Gateway_Firewall_Policies_Add_DNS_Policy.png)

In the first step (**Step 1**) we enter the name. In the second step (**Step 2**), and in the part responsible for network traffic (**Traffic**) we press the button to add a condition that must be met (**Add consition**).

Then from **Selector** we select **Security Categories**. As **operator** as **in** (contains), from the **Value** option we select the type of block, for example **Malware**.

In the third step (**Step 3**) we select what should happen when the condition is met. In my case I select "block" (**Block**).

We finish everything by pressing the button to create a rule **Create policy**.

In this way, our rule has been enabled and our network traffic is filtered from the DNS server level.

---

The **Content Categories** have a few more options, such as blocking pornography, hate, and gambling.

> You can read more about each category on the [**Domain categories**](https://developers.cloudflare.com/cloudflare-one/policies/gateway/domain-categories/) page.

While it is possible to enable more than one value (**Value**) in a single rule, I personally recommend creating each one separately for each value. Sometimes it may happen that we accidentally block something that should not be blocked and by splitting the rules we will be able to track which rule is causing the problem and disable it as needed.

> I personally created separate rules for each security category and enabled them in my network. As part of the blocked items analysis I would decide whether the rule worked or if it should be disabled.

## Block Analysis and Cloudflare Radar

As your network traffic is analyzed, you can see in real time what is allowed and what is blocked in **Analytics** > **Gateway**.

[![Analytics Gateway analytics 7 days](Analytics_Gateway_analytics_7_days.png)](Analytics_Gateway_analytics_7_days.png)

In the appropriate sections, you will be able to see the most frequent and allowed things, as well as the things that were blocked.

Easy-to-read graphs will allow you to analyze traffic in terms of different categories.

[![Analytics Gateway analytics Charts](Analytics_Gateway_analytics_Charts.png)](Analytics_Gateway_analytics_Charts.png)

In the **Logs** > **Gateway** section you will be able to analyze in detail the elements that were blocked.

[![Logs Gateway activity logs](Logs_Gateway_activity_logs.png)](Logs_Gateway_activity_logs.png)

By clicking on individual items (domains), you can learn more about the block and which rule was used for this purpose. This is highly useful for analyzing rules that block more than we assumed they would.

---

An interesting thing is the **View domain details in Radar** option.

[![Logs Gateway activity logs Preview](Logs_Gateway_activity_logs_Preview.png)](Logs_Gateway_activity_logs_Preview.png)

Cloudflare Radar lets you see what category a domain is classified into.

[![Cloudflare Radar example](Cloudflare_Radar_example.png)](Cloudflare_Radar_example.png)

For example, my domain where I host my website is categorized as **News & Media**, **Personal Blogs**, and **Technology**.

If you choose to block any of these categories using **Content Categories**, you will also block my page.

With Cloudflare Radar you can also analyze categories and send a report to Cloudflare via the **Categorization Feedback** link if a page is incorrectly categorized.

> However, don't expect much action from Cloudflare on your suggestions.

For example, `www.halfords.com` is tagged as **Ecommerce** and **Vehicles**. I can certainly agree with that, but lumping it into **Sports** is a bit misleading in my opinion.

[![Cloudflare Radar halfords](Cloudflare_Radar_halfords.png)](Cloudflare_Radar_halfords.png)

## Configure Filtered Secure DNS in your browser

If we do not have a router that we can configure for secure DNS with filtering, we can configure a web browser for these needs.

For example, Google Chrome (or Chromium-based Microsoft Edge) has an option to use secure DNS (**Use secure DNS**) in the Privacy and security section.

We can use the options available there or add a custom configuration (**Add custom DNS service provider**), where we can paste our address that we received at the beginning of our game:

```
https://{unique_link}.cloudflare-gateway.com/dns-query
```

In this way, queries to websites directed from our browser will be safe and filtered according to established rules.

## Setting Up Filtered Secure DNS in Windows 11

If we do not have the luxury of an OpenWrt router, and securing the traffic generated by the browser is insufficient, we can secure our DNS queries from Windows 11.

I'm not talking about the ability to add DNS addresses to network interfaces (cards), but about introducing the DNS over HTTPS option.

Changing the DNS addresses of network interfaces is something we should also do, but by going to the system settings (**Settings**), the "Network & internet" category (**Network & internet**), clicking on our network settings (**Network properties**), and then on the hardware settings (**Hardware properties**), we can introduce system-wide encryption of our DNS queries.

[![Windows 11 DNS Settings DNS over HTTPS](Windows_11_DNS_Settings_DNS_over_HTTPS.png)](Windows_11_DNS_Settings_DNS_over_HTTPS.png)

By clicking on the section responsible for the DNS server address (**DNS server assignment**), which by default are set to obtain this information automatically (from the router), we change them to setting it manually (**Manual**). Then we enable the settings for IPv4 and enter our DNS addresses, which we received from the Cloudflare website (`172.64.36.1` as primary, `172.64.36.2` as alternative).

In the **DNS over HTTPS** section we change from disabled (**Off**) to enabled with manual configuration (**On (manual template)**).

In the field that will be presented to us, paste the address received from Cloudflare similar to this one.

```
https://{unique_link}.cloudflare-gateway.com/dns-query
```

We do the same for IPv6 addresses.

---

In this way, not only do we have [Secure DNS](/en/secure-dns/) introduced, but we also have control over what is allowed on the network and what is not. This is convenient because we can easily limit the behavior of some users on our network.

---

Cloudflare Zero Trust is not just DNS servers. It is also the ability to create a secure tunnel (VPN), thanks to which we can connect to our local network from outside the home or company.

I wrote more about it in the entry: [**Adding Cloudflare Tunnel to OpenWrt Router (VPN Alternative)**](/en/adding-cloudflare-tunnel-to-openwrt-router/).

Regards.


---
## Apple discontinues MacBook Air with M1 Chip, but what does that mean for its users?
- **URL:** https://dariusz.wieckiewicz.org/en/apple-discontinues-macbook-air-with-m1-chip/
- **Date:** 2024-03-04
- **Tags:** MacBook Air, Apple Silicon, Apple M1, Apple Care, discontinued, vintage, obsolete

### Content

Just a few weeks ago I have been thinking about, what I am doing with my ageing MacBook Air with an M1 chip. 

The MacBook Air Air with M1 was introduced in November 2020 but I purchased mine in July 2021, officially from Apple, but from their refurbished store.

I saved a bit on a base model and thanks to that I have been able to take 3 years of Apple Care and still meet my budget.

Despite that nothing happens along the road, so I don't need to use this plan, I still wonder, if, after these 3 years, I will be able to buy, at least, a year more.

The device working well. I would like to have a bit more internal storage (currently got 256GB base), but apart from that everything working fine. The device is still fast and reliable. For my needs, I don't see a reason for change.

I have been thinking about a possible upgrade when the MacBook Air is introduced with the M3 chip and that is what happens today (4th March 2024) through [press release](https://www.apple.com/newsroom/2024/03/apple-unveils-the-new-13-and-15-inch-macbook-air-with-the-powerful-m3-chip/).

At the same time, Apple decided to discontinue MacBook Air with an M1 chip. Its place, in the same price range, has been offered to a 13-inch MacBook Air with an M2 chip, which is typical.

But what does that mean for users, who use MacBook Air with an M1 chip? Also, what does that mean for people, who just now decide to buy MacBook Air with an M1 chip?

<!--more-->

Apple is still selling MacBook Air with an M1 chip on its [Refurbished Store](https://www.apple.com/uk/shop/refurbished/mac) where a base model can be bought for £759 (compared to £849 when I purchased it in July 2021).

Let's remember, that Apple has various terms for their product depending on their circle of life.

These are **discontinued**, **vintage** and **obsolete**.

**Discontinued** means that **new items** are no longer for sale. Replacements and parts will still be available for quite some time and you can still buy these devices as refurbished.

Products are considered **vintage** when Apple stopped distributing them for sale (new items) more than 5 and less than 7 years ago. Counting from today that will be somewhere between March 2029 and November 2031.

Products are considered **obsolete** when Apple stopped distributing them for sale (new items) more than 7 years ago.  For Air with M1 chip that that will be past November 2031.

If all the calculations are right (Apple may change these terms) Apple will support MacBook Air with an M1 chip for over 8 years since launch. There will be still a possibility to purchase Apple Care, which will still be available till at least March 2029.

> Of course, you need to purchase your Apple Care plan up to 30 days from purchase or up to 30 days past the current Apple Care plan expiration (if not purchased with the goods).

As my Apple Care is due to expire in July 2024, if I extend this in Annual intervals, I will be able to use my device for longer with peace of mind, if nothing happens.

**But are this will be possible?**

{{% ads-in-article %}}

I am asking this question as the freshly updated [AppleCare Product](https://www.apple.com/uk/support/products/mac/) page for Mac does not include prices from M1 anymore.

Just over a week ago, I asked a question to Apple Support, will I be able to purchase Apple Care for my computer past 3 years of support?

The answer was yes, as long I will do that in 30 days after my Apple Care expires.

In light of the updated AppleCare Product page and the fact that the device has been discontinued, I decided to ask that question again.

Through a very friendly phone call, I confirmed that I will be able to purchase an extension of my Apple Care plan as long I do not pass the 30 days and that calling a product **discontinued** does not affect that.

**It's good to hear that.**

On one side I would like to upgrade to MacBook Air with M3, but on the other, there are other things that I would like to prioritise this year, hence if my device can serve me a bit longer and be covered, that will give me peace of mind.

I think I will go for that. Overall this shall not cost me more than £64.99 annually, which is the bottom plan for MacBook Air 13‑inch (M2).

**So, in the end, what does it mean for its users?**

**Not much.** If the device is under Apple Care, or even if it's not, there will be still a possibility to get the support needed. 

For people without active Apple Care, the cost of repairs may go up and repairs may will require sending the device away and will take some time to get it mended.

In that case, sometimes it will be more economically viable to buy a new (or refurbished) device rather than fixing the old one.

Overall Apple devices, when handled properly, serve its users way above the standard warranty and initial Apple Care period.

> Apple devices, in most cases, meet the [SAD FART rule](https://www.moneysavingexpert.com/reclaim/consumer-rights-refunds-exchange/) easily.

Apple Care may not be an economically viable option when you just spend X amount of money on a new Apple device, but in the long run, it "pays" for itself.


---
## ChromeOS, Linux environment and sudo password
- **URL:** https://dariusz.wieckiewicz.org/en/chromeos-linux-sudo-password/
- **Date:** 2024-02-23
- **Tags:** ChromeOS, Linux, Penguin, SUDO, password, passwd

### Content

The Linux environment has been a part of my computer workflow for years.

In my personal life, I use macOS, which allows me to leverage the terminal to extend my possibilities beyond the graphical user interface (GUI).

At work, I use Windows devices. Through the Windows Subsystem for Linux, I can also use Linux on these machines.

Recently, as part of my work with Chromebooks, I decided to leverage the power of the Linux terminal there as well.

<!--more-->

I've just installed the Linux environment through the Developer option on ChromeOS Flex and opted to install a package manager to facilitate adding necessary software.

On Windows 11, I use the Ubuntu environment, which is based on Debian. Since I've learned Debian over the years, I'm familiar with it.

ChromeOS also utilizes a Debian-based Linux environment, making them quite similar.

While working with Linux on macOS or Windows, I rely on [Homebrew](https://brew.sh), aptly named "The Missing Package Manager for macOS or Linux." It empowers me to install essential packages effortlessly.

Within the ChromeOS environment, I attempted installation as well, but encountered a minor hurdle when copying and pasting the installation command from the Homebrew website.

Initially, I encountered difficulty pasting the installation command using the paste keyboard shortcut (<kbd>Ctrl</kbd>+<kbd>V</kbd>).

I needed to head to the Terminal settings, where under Keyboard and mouse, I needed to tick the box for <kbd>Ctrl</kbd>+<kbd>V</kbd> paste behaviour. I have also enabled several others I typically use, like <kbd>Ctrl</kbd>+<kbd>C</kbd> copy behaviour.

{{% gallery %}}
[![ChromeOS Terminal Settings](chromeOS_Terminal_Settings.png)](chromeOS_Terminal_Settings.png)
[![ChromeOS Terminal Settings > Keyboard and Mouse](chromeOS_Terminal_Settings_keyboard_and_mouse.png)](chromeOS_Terminal_Settings_keyboard_and_mouse.png)
{{% /gallery %}}

Yet, pasting the Homebrew installation command in the penguin terminal presented another hurdle.

{{% ads-in-article %}}

Homebrew isn't recommended for installation under root privileges. Instead, it is installed as an ordinary user who belongs to the `sudoers` group. This grants the ability to run commands with administrator privileges using the `sudo` command.

[![ChromeOS Terminal with Linux environment](chromeOS_Terminal_Linux.png)](chromeOS_Terminal_Linux.png)

Despite being in the sudoers group by default, the installation process initially prompted me for my password.

Surprisingly, during the initial Linux environment setup, I only needed to set a username. There was no prompt for a password. I assumed my Google Account password would suffice, but I was mistaken.

Desperate for a solution, I quickly Googled "default password" and found a reference to `test0000`. Needless to say, it didn't work.

Aware of how to change the password, I promptly ran the `passwd` command. However, to my surprise, it prompted me for the _current password_, which I, of course, didn't know.

To my surprise, using `sudo su` in the terminal granted me elevated privileges without a password prompt.

Fortunately, gaining root privileges allowed me to change my user password using `passwd user` (where `user` is the username displayed before `@penguin`).

Exiting root privileges and running the Homebrew installation command again, the process completed smoothly after I entered the new password.

It may seem straightforward, but searching online often leads to irrelevant answers. This guide serves as a reminder for myself and others on how to successfully install Homebrew on ChromeOS.

Regards


---
## Following encouragement to use Microsoft Edge, I am moving some users back to Google Chrome
- **URL:** https://dariusz.wieckiewicz.org/en/from-microsoft-edge-back-to-google-chrome/
- **Date:** 2024-02-09
- **Tags:** Microsoft Edge, Google Chrome, Chromebook

### Content

Since Microsoft Edge transitioned to the Chromium engine (the same engine as Google Chrome), I encouraged Windows users to try the updated version. After all, both browsers offer similar functionality.

Microsoft Edge, when logged in with a Microsoft account, was nicely integrated within the Windows operating system, offering a seamless experience. However, I've noticed that for users who primarily use Android phones and rely heavily on Google Services (like Google Photos), this solution is no longer optimal.

<!--more-->

Both Google and Microsoft built their browsers around their respective services, as evidenced by Google Chrome's alignment with Android and Microsoft Edge's integration with Windows. However, Microsoft's abandonment of mobile devices and subsequent cancellation of Windows Phones left a gap in their ecosystem. While their solution to integrate Windows with Android phones through the Microsoft Launcher is commendable, it feels akin to adding an engine to a car that already functions perfectly.

Faced with Microsoft Edge's rising popularity, Google launched a targeted campaign urging users of its services to switch back to Google Chrome, particularly those accessing Google services through Edge.

However, this has not gone without widespread criticism directed at Google. Nevertheless, Microsoft has recently followed suit with similar tactics. 

In my new approach, I prioritize user needs and preferences over my own.

For businesses using Microsoft 365 solutions, **maintaining** Microsoft Edge might be a reasonable option due to its beneficial integration with the operating system and services they **pay for**.

For users primarily relying on Gmail and independent of paid Microsoft services, opting for Google Chrome as the default browser on Windows operating systems seems like a reasonable solution.

**Simple, end of story.**

You can install extensions designated for Google Chrome into Microsoft Edge with ease, and all with work in the same way.

The only consideration is where you store your passwords, bookmarks, and other preferences (either in your Microsoft or Google account).

For users who rely primarily on Google's search engine and services, Google Chrome may be the most convenient choice. Those invested in Microsoft's services likely find Microsoft Edge a better fit.

My situation is unique: I juggle between personal iPhone and Mac (with Google services) and at work with Windows devices (with Microsoft services).

I am torn between multiple options and software.

One area where Microsoft Edge falls short for many users is the default search engine.

Microsoft Edge's default search engine, Bing, may not be as suitable for some users who prefer Google's search results.

I set Google as the default search engine on all work computers, only to find it switched back to Bing after certain updates. That's frustrating!

Microsoft's recent updates have raised concerns about data privacy, following reports that the Edge browser may automatically import tabs from Chrome without explicit user consent, as detailed in The Verge article [Microsoft stole my Chrome tabs, and it wants yours, too](https://www.theverge.com/24054329/microsoft-edge-automatic-chrome-import-data-feature).

This seems like an overreach.

> According to [recent reports](https://www.theverge.com/2024/2/16/24074712/microsoft-edge-automatic-chrome-import-data-bug-fix), Microsoft has "fixed" a bug that allegedly copied Chrome tabs and data. While the company claims it was unintentional, many suspect it was a deliberate act. The feature's removal after public outcry has left a lingering sense of distrust.

There is clear competition between Google and Microsoft in the browser market. Windows comes pre-installed with Microsoft Edge, while Google Chrome requires a separate installation. Some users choose Chrome due to preference or familiarity, while others may have concerns about Edge. While both browsers share similar functionalities, they also have unique features and cater to different user needs.

_Naturally, many users unaware of this will default to downloading Chrome. However, there's more to the story than brand recognition._

{{% ads-in-article %}}

My approach has shifted, largely due to my experience promoting Chromebooks to users with limited technical expertise and accessibility requirements. Recognizing the needs of those nearing the end of Windows 10 support, I now suggest alternative solutions beyond purchasing a new Windows 11 PC.

For basic users who primarily utilize their computer for web browsing, consider a Chromebook as a potential alternative to a full-fledged Windows machine. Particularly for Android phone users, Chromebooks offer a familiar interface and seamless integration with other Google services.

Buying a Chromebook Plus now comes with guaranteed software support until June 2032, ensuring your device functions well even as hardware advances. In most cases, the hardware itself will likely last just as long, making a Chromebook Plus a potentially cost-effective choice for the coming years.

For users with devices no longer eligible for the official Windows 11 update, concerns around obsolescence and potential e-waste are understandable.

Devices incompatible with Windows 11 will technically remain functional. However, concerns have been raised regarding possible software limitations and compatibility challenges. 

While some devices might not receive the official Windows 11 update, alternative solutions like ChromeOS Flex may be available to transform PCs into Chromebook-like devices. However, it's important to note that ChromeOS Flex does not feature Android app support, meaning you won't be able to run Android apps from the Google Play Store.

Chromebooks offer access to the Android ecosystem alongside Google Chrome, allowing users to install mobile and tablet applications typically unavailable on traditional desktops.

If you have switched to Microsoft Edge and are not entirely satisfied, returning to Google Chrome is an option worth considering. On the other hand, if you've been using Chromium-based Edge and it meets your needs, there might not be a compelling reason to switch back to Chrome.


---
## Using a Computer for True Beginners: Browsing the Internet with ChromeOS Flex
- **URL:** https://dariusz.wieckiewicz.org/en/using-a-computer-for-true-beginners-browsing-the-internet/
- **Date:** 2023-12-30
- **Tags:** ChromeOS, ChromeOS Flex, accessibility, Google Chrome, AbilityNet

### Content

I recently got the privilege to assist an elderly member of the community in his first steps with the computer as a part of my volunteering through a UK charity called [AbilityNet](https://abilitynet.org.uk/).

> AbilityNet's mission is to make a digital world accessible to all. Through it, they offer support services for a wide range of users. From older or disabled people looking for help with their technology to digital professionals advocating for accessibility best practices within their organisation.

As a part of the adjustment for that person, I decided to introduce them to [ChromeOS Flex](https://chromeenterprise.google/intl/en_uk/os/chromeosflex/).

ChromeOS Flex is an operating system provided by Google, which is very similar to these on branded Chromebooks, but without access to the Google Play Store and not backed up by the Android engine. This system can be installed on a variety of devices making it more accessible for people who need stability and simplicity.

Windows and macOS can be overwhelming for people who never used computers, this is where Chromebooks fit perfectly. 

Google integrated a lot of accessibility features into this system allowing it to adjust them to the needs of users with its users in mind.

There is one problem, however.

How do you introduce somebody, who lived his life without a need to integrate into technology?

<!--more-->

These people, at some stage of their life been left behind. Technological progress skyrocketed and they don't have a chance to catch up without help. This is why I like to be involved in organisations like AbilityNet, where I and other volunteers can help to close the gap by offering our free time, from time to time, to do something good.

ChromeOS is an operating system, that is, in my opinion, a great option to start the journey with the computers for elderly people (unless they decide to go the route of tablets).

It can be fast, yet simple and secure. Security is the most important thing for everybody, especially vulnerable people.

Google is providing very nice, simple guides for Chromebooks as a part of their [Chromebook Simulator](https://simulator.webapps.google.com/chromebook). These guides can be either viewed on-screen or printed in an accessible way to read on paper (let's call them printables).

This simulator is great, but from the perspective of a new user, something more is needed - something much simpler. This is why I decided to try my approach to make some "printables", that will cover basics.

The installation of ChromeOS Flex on ordinary computers can be done in simple manners, as Google prepared for this [a guide](https://support.google.com/chromeosflex/answer/11552529). You will just need an internet connection, a Chrome browser and a USB drive with at least 8GB of capacity.

When that's done, it's time to start.

I have thanked for a while how to help this particular person on my next visit. I know, that I can show things, how to operate them. For me, it's simple, for them not necessarily. After my short visit, I doubt that this will encourage them to start on their own. If they have something that he can rely on, re-read the information provided, this may be something that will help and encourage that technology is not so scary.

This is why I decided to prepare this simple guide which I will use to go through the basics, and leave it in printed form, so they can be referred back when needed.

Let's start.

---

## Getting started

When you turn on your computer you will be greeted with a lock screen as seen below.

[![ChromeOS Flex - Lockscreen](/images/2023/12/chromeos_flex_lockscreen.jpg)](/images/2023/12/chromeos_flex_lockscreen.jpg)

In the centre, you will see your picture (if set on your account) or avatar, which is an icon, typically represented by the initials of your name and surname.

Under it is a field to type the password to your account.

> During the setup of your computer, you will be asked to set, apart from the account password, which is typically long and complicated, also a PIN, which will be a combination of six digits, much simpler than a strong and secure password.

When you turn on your computer for the first time, you must type in your password.

---

**Mouse and Touchpad**

Firstly, if the field is not highlighted and ready to accept the password, you need to move the mouse to operate a cursor on the screen. If you are using a touchpad, you need to put a finger on it and slightly press and hold it on to move the cursor around.

Once you hover the cursor over the password field, press the left mouse button. Mouses may have more than two buttons. Typically, you use the left button to confirm the action.

The touchpad is typically fitted with two buttons, which left us used for most of the actions. Sometimes, some touchpads have buttons built into them, where, when pressed left bottom corner, this will represent the left click button.

---

Depending on how fluent you are with the use of the keyboard, you will need to carefully type in your password.

---

**Keyboard**

Typically, computers called Chromebooks have a different layout of the keyboard to the PCs which were adopted for the use of the operating system ChromeOS.

This is what the Chromebook keyboard looks like.

[![Keyboard layout on Chromebooks](/images/2023/12/keyboard_chromebook.jpg)](/images/2023/12/keyboard_chromebook.jpg)

And this is how likely your keyboard will look on an adopted Windows computer that you will be using with ChromeOS.

[![Keyboard layout on Windows computers](/images/2023/12/keyboard_windows.jpg)](/images/2023/12/keyboard_windows.jpg)

The numbers and letters are mostly in the same places, the difference will be in the use of some special keys, like these for starting writing in capital letters.

---

Please remember to type the password as set. Where there are capital letters, they need to be typed as capital, when there are numbers, as numbers and where there are special symbols (if set), typed accordingly.

---

[![Windows keyboard with Shift highlighted](/images/2023/12/keyboard_windows_shift.jpg)](/images/2023/12/keyboard_windows_shift.jpg)

To type capital letters, you can press and hold the <kbd>Shift</kbd> button. Once you hold it, each letter you press will be typed as capital. When you release it, it will written in small.

---

[![Windows keyboard with Caps Lock highlighted](/images/2023/12/keyboard_windows_caps_lock.jpg)](/images/2023/12/keyboard_windows_caps_lock.jpg)

If you struggling with holding the <kbd>Shift</kbd> button and at the same time typing a letter, you can single press the <kbd>Caps Lock</kbd> button. When pressed, the LED button will lit either on the button itself or somewhere on the computer (it all depends on the make of the computer).

Once the button is activated, each letter will be typed as capital. To turn it off, just single press the <kbd>Caps Lock</kbd> button again.

---

[![Windows keyboard - number keys](/images/2023/12/keyboard_windows_number_keys.jpg)](/images/2023/12/keyboard_windows_number_keys.jpg)

Sometimes you may need to type special characters like the `@` symbol (called `at`). You may notice that this symbol is located on top of the number `2` on the keyboard.

When you press the number `2` it will type number `2`. To get the `@` symbol, you need to press and hold the <kbd>Shift</kbd> button and once holding it, you need to press the number `2` key. This will type the `@` symbol instead.

It's the same with any other symbols.

If buttons on the keyboard represent more than one thing, by default, when pressed, you will type whatever is on the bottom of the key. If you want to type what's on the top of the key, that's where the <kbd>Shift</kbd> button needs to be used.

---

Once you type your password, let's check if it's typed correctly before we press the `Enter` key and try to log in.

To preview our password typed into the password field we need to click on the `eye` symbol at the end of the password field. The `eye` symbol will change and will become crossed over and your typed password will be displayed in plain text, instead of the dots.

[![ChromeOS Flex - Lockscreen - Show Password](/images/2023/12/chromeos_flex_lockscreen_show_password.jpg)](/images/2023/12/chromeos_flex_lockscreen_show_password.jpg)

> The preview of the password will not stay for too long and will revert itself to a hidden form over a short time.

If you typed the password correctly, press `Enter` to log into your computer.

If you make a mistake, you can correct it by using the `Backspace` button to remove the entered text.

If you type the password incorrectly and press `Enter`, don't worry, the system will tell you that it may be wrong.

[![ChromeOS Flex - Lockscreen - Wrong Password](/images/2023/12/chromeos_flex_lockscreen_wrong_password.jpg)](/images/2023/12/chromeos_flex_lockscreen_wrong_password.jpg)

Try typing it again and use the `eye` icon to preview it before you confirm by pressing the `Enter` button or button with an arrow pointing right located on the side of the field when you enter the password.

> Take your time and try your best to type the password correctly. Nothing will happen if you make a mistake a couple of times.

If all is done correctly, you will log into your computer and you will be presented with the computer desktop and the bar with the icons on the bottom of your screen as shown below.

[![ChromeOS Flex - Desktop](/images/2023/12/chromeos_flex_dekstop.jpg)](/images/2023/12/chromeos_flex_dekstop.jpg)

Congratulations, you are ready to start using your computer.

---

**Before we go to the next step, let's mention one more thing.**

When you not using your computer, you can leave it running and do not turn it off. This may be much more convenient for you, as you will not need to type the secure password each time, which may be a bit of a challenge.

However, the computer, when not in use, **for security reasons** will lock itself.

The screen will turn off in eight minutes and your computer will go to sleep in 30 minutes.

You just need to press any key on a keyboard, or mouse, or in some instances just shortly press the computer power button to resume.

When that happens, you will not need to type your secure password again. You will be asked to type a six-digit PIN code set, and provided, for you, at the beginning.

[![ChromeOS Flex - Lockscreen PIN](/images/2023/12/chromeos_flex_lockscreen_pin.jpg)](/images/2023/12/chromeos_flex_lockscreen_pin.jpg)

Type your PIN and, once the last, sixth digit, is pressed correctly, you will be back on your computer desktop.

> Try typing your PIN correctly. If you make a mistake three times in a row, you will be asked to type your secure password, like it happens when you turn on your computer for the first time.

**Now you are ready to use your computer.**

Before we start exploring further, let's see how we can turn the computer off.

## Turning off the computer

There are two ways of turning off your computer.

In the bottom corner of your desktop, there is a clock displaying actual time. When you click on it, you will be presented with a new menu as shown below.

[![ChromeOS Flex - Clock Submenu](/images/2023/12/chromeos_flex_clock_submenu.jpg)](/images/2023/12/chromeos_flex_clock_submenu.jpg)

In the new menu, on the bottom left side of it, there is an icon with a commonly known power symbol and a small arrow (chevron) pointing down.

When you press on it, you will be presented with an additional menu. The power symbol will be highlighted and the small arrow (chevron) will be facing up.

[![ChromeOS Flex - Shutdown](/images/2023/12/chromeos_flex_shutdown.jpg)](/images/2023/12/chromeos_flex_shutdown.jpg)

From the available options, you need to select the `Shut down` option, which is also shown with a commonly known power symbol on the left side of that text.

Once the `Shut down` option is selected, you need to click on it.

**Your computer will shut down and turn off itself.**

---

There is another option to turn off your computer.

When you single press the physical power button on your computer, a very similar menu as seen before appears in a bit larger format and is placed in the centre of your screen.

By hovering your mouse over the `Shut down` button and pressing on it you can shut down and turn off your computer as well.

**The first method is a standard approach, but choose whichever is easier for you.**

In such a way, you know how to:
- Turn on your computer
- Log in to your computer using the password
- Log in to your computer using PIN
- Turn off your computer

The next step will be to familiarise yourself with what the computer has to offer.

## Internet Browser

When you are on your desktop, at the bottom of the screen you will see a few things.

[![ChromeOS Flex - Bottom Bar - Left](/images/2023/12/chromeos_flex_bottom_bar_left.jpg)](/images/2023/12/chromeos_flex_bottom_bar_left.jpg)

There is a button with a circle on the bottom left part of the screen.

[![ChromeOS Flex - Bottom Bar - Center](/images/2023/12/chromeos_flex_bottom_bar_center.jpg)](/images/2023/12/chromeos_flex_bottom_bar_center.jpg)

There are some colourful icons in the bottom middle of the screen.

[![ChromeOS Flex - Bottom Bar - Right](/images/2023/12/chromeos_flex_bottom_bar_right.jpg)](/images/2023/12/chromeos_flex_bottom_bar_right.jpg)

On the bottom right, you have other options displayed, like date and time. By pressing the time, you can open a menu, from which we can turn the computer off as we mentioned in the previous part.

---

We will start with the first icon, from the group of icons in the middle bottom of the screen.

[![ChromeOS Flex - Bottom Bar - Center](/images/2023/12/chromeos_flex_bottom_bar_center.jpg)](/images/2023/12/chromeos_flex_bottom_bar_center.jpg)

The icon represents the internet browser, which is an application, that is used, as the name suggests, to browse the internet. This icon represents an application called Google Chrome.

> Google Chrome is the internet browser that you will be using to go to the internet. Some people may ask you to turn on  "your internet browser" or will refer to it by its name "Google Chrome", which means very the same.
>
> There are other internet browsers available, not only Google Chrome, hence it's much easier to refer to it using a generic term, rather than a specific application name. This may sometimes confuse users on other operating systems and other computers if they using different applications for this purpose, like Microsoft Edge on Windows.

By pressing the icon you will load a new window on your screen, that will present a Google text or logo in the centre of the screen and a horizontal search bar under it, which is used to search the internet.

[![ChromeOS Flex - Google Chrome - Start](/images/2023/12/chromeos_flex_google_chrome_start.jpg)](/images/2023/12/chromeos_flex_google_chrome_start.jpg)

> The text or logo that represents Google may change depending on the day of the year. This is called Google Doodle and the change is mostly related to commemorating holidays, events, achievements, and notable historical figures. If the logo is not as presented above, do not worry.

**Now you know how to open an internet browser. It is now time to explore it further.**

## Getting to know Google Chrome

When you click on the Google Chrome icon the new window loads. I already mentioned what happens in the centre of the screen - the Google Logo and the horizontal search bar under it.

Before we go any further, we need to understand a couple of basics.

[![ChromeOS Flex - Chrome Search Bar](/images/2023/12/chromeos_flex_google_chrome_search_bar.jpg)](/images/2023/12/chromeos_flex_google_chrome_search_bar.jpg)

In the horizontal search bar, you be able to type a text that you would like to search over the internet. You need to click into the box to start typing in.

Apart from that, you can do the same, if you will type the text in the top horizontal bar of the open windows of Google Chrome.

[![ChromeOS Flex - Google Chrome Address Search Bar](/images/2023/12/chromeos_flex_google_chrome_address_search_bar.jpg)](/images/2023/12/chromeos_flex_google_chrome_address_search_bar.jpg)

This bar has the same purpose as the search bar mentioned before, to search the internet using a search engine, which by default will be Google Search.

> We will cover Google Search a bit further.

**This bar can be used also to do something else.**

In this bar you can also type the address of the website, to go to the website directly.

> Like the phone number in our phone book that will connect us to a specific person, in the same way, each website has its domain (like www.bbc.co.uk) that will point to the site placed on a machine located inside the internet. We don't need to know where it is located, the domain address, or simply the website address, will do this for us.

Now you know that:
- A horizontal bar placed in the centre of the screen when the internet browser (Google Chrome) is loaded is used to type a word or preferably a phrase that you want to search for on the internet.
- The top bar is used to search, as described above, but also to type the precise address of the specific website in the internet called domain.

---

The window of the internet browser (Google Chrome) has a couple more things that you need to familiarize yourself with before you start surfing through the internet.

If you want to close the internet browser, you need to press the  `X` button located in the top right corner of the window.

[![ChromeOS Flex - Google Chrome Top Close](/images/2023/12/chromeos_flex_google_chrome_top_close.png)](/images/2023/12/chromeos_flex_google_chrome_top_close.png)

> In a similar way you are closing any other application that you may use on your computer.

In the very top, slightly from the left, you will see tabs.

[![ChromeOS Flex - Google Chrome Top Tabs](/images/2023/12/chromeos_flex_google_chrome_top_tabs.png)](/images/2023/12/chromeos_flex_google_chrome_top_tabs.png)

By default, you have only one tab.

Each website you are browsing opens inside a tab. Sometimes you may have some opened in an additional tab. Thank you that you may search the internet on one tab, and read articles on the website on the other tab.

[![ChromeOS Flex - Top 2 Tabs](/images/2023/12/chromeos_flex_google_chrome_top_2_tabs.png)](/images/2023/12/chromeos_flex_google_chrome_top_2_tabs.png)

Each tab has its own `X` button used to close it.

When you click the close button on the last and only tab open, this will close the windows of the internet browser as well.

Depending on how websites are made (designed), some pages may open themselves in separate tabs. Keep an eye on the tabs on top. The active tab will always be highlighted and the others will be presented in the background.

You can move between them by clicking each of them. 

If you are confused by the number of tabs open, just click the `X` button near each of them until you close them all.

> If you have multiple tabs open and you will close the whole window of the internet browser (Google Chrome), when you open it again, you may see that all the tabs, that have been left open, will load again.
> 
> The same situation, if you have been on a website before and you close the internet browser window (intentionally or by accident), Based on how it's set on your computer, your last open website may be loaded instead of the default Google search page. To close it, just press the X button in the tab to close it and the window itself. When you open the window again, you will be presented with the window as described in the beginning.

In this way, we can go a little bit further and start searching the web (internet).

{{% ads-in-article %}}

## Searching the internet

By using a search bar type a few words or a phrase of what you would like to search on the internet and confirm with the Enter button.

As a response, you will be presented with the search results in a search engine called Google Search (simply "in Google").

> Google Search is like an index in a book. If you type a number, it will point you to a page that contains it or something that is close enough and you will be able to select it or move further (to the next page).

Let's try typing "_whats currently happen in leeds uk_".

> When you search the web, you don't need to be grammatically correct. The search engines are clever enough to figure out what we meant to type (say) as you see in this example.

[![ChromeOS Flex - Searching Google](/images/2023/12/chromeos_flex_searching_google.png)](/images/2023/12/chromeos_flex_searching_google.png)

The search results will be presented as a list. You don't necessarily need to click the first result available. Sometimes you may need to scroll down to see other results, other websites, that will contain the results much more relevant to what you are looking (searching) for.

> Sometimes the list will be filled with some images or movies on which you can click to move forward.

Let's click on the following result.

[![ChromeOS Flex - YEP Search Result](/images/2023/12/chromeos_flex_yep_search_result.png)](/images/2023/12/chromeos_flex_yep_search_result.png)

You will be directed to a website (Yorkshire Evening Post, or just YEP), like in this example where you can browse across, read the news, and click on other interesting things on the website.

[![ChromeOS Flex - YEP website](/images/2023/12/chromeos_flex_yep_website.jpg)](/images/2023/12/chromeos_flex_yep_website.jpg)

If you do not find what you have been looking for, you can always go back, by pressing the **back arrow** located in the top left part of the screen.

[![ChromeOS Flex - Google Chrome - Back](/images/2023/12/chromeos_flex_google_chrome_back.png)](/images/2023/12/chromeos_flex_google_chrome_back.png)

This will put you back to the search engine.

If you want to start again, press a **home button** symbol to go back to the default starting page.

[![ChromeOS Flex - Google Chrome - Home](/images/2023/12/chromeos_flex_google_chrome_home.png)](/images/2023/12/chromeos_flex_google_chrome_home.png)

---

Internet browsers have also arrows to **move forward** and **refresh** arrows.

[![ChromeOS Flex - Google Chrome - Forward Refresh](/images/2023/12/chromeos_flex_google_chrome_forward_refresh.png)](/images/2023/12/chromeos_flex_google_chrome_forward_refresh.png)

If you go back from the website, but you want to return to where you were, you can also press the forward arrow to do that, if available.

If you head to the website and it doesn't look good or doesn't load properly, you can try the refresh button to try to reload it.

---

You are also using the refresh button to refresh the website when you are on it.

If you are on the home page of the news website, refreshing it will check if there is no new content published, and if it is, this will be presented to you.

---

Through searching the internet (or shortly, searching the web) you can head to various places.

Like in real life, do not believe everything that you find over the internet to be 100% true, and always have a bit of scepticism about the information presented.

## Visiting a website

Apart from searching the internet through the search engine like Google, you can also go to the website directly if you know its address. This address is called a domain. Knowing the domain name is like knowing somebody's phone number, so you shall know where you heading (who you calling).

The domains for various websites may be built differently.

They typically contain a unique name and then the extension of the domain used in the country where is based or what it represents (typically separated with dots).

For example, the BBC domain address is bbc.co.uk.

The `bbc` is the name of the domain, whereas `.co.uk` is the extension popular for websites in the United Kingdom.

The domains have also separate sections in their names which are separated with `slash` symbol `/`.

For example, the address for BBC News will be bbc.co.uk/news.

[![ChromeOS Flex - Google Chrome - BBC News](/images/2023/12/chromeos_flex_google_chrome_bbc_news.png)](/images/2023/12/chromeos_flex_google_chrome_bbc_news.png)

The domain address is typed typically in the top part of the window.

If you would like to visit the website of AbilityNet, you need to type their domain name and extension, which in that case will be abilitynet.org.uk.

[![ChromeOS Flex - Google Chrome - AbilityNet](/images/2023/12/chromeos_flex_google_chrome_abilitynet.png)](/images/2023/12/chromeos_flex_google_chrome_abilitynet.png)

It is not possible to remember all the domain names. Some of them, that you may use daily, you will remember, but some of them need to be saved for us, either by writing them on a piece of paper or by using other available options on your computer, like **shortcuts** and **bookmarks** that will be covered next.

## Adding shortcuts to websites

When you open your internet browser (Google Chrome) you will notice, that straight under the horizontal search bar, located in the middle of the screen, there are some buttons, including one with a plus symbol and a text "Add shortcut".

[![ChromeOS Flex - Google Chrome - Add Shortcut button](/images/2023/12/chromeos_flex_google_chrome_add_shortcut_button.png)](/images/2023/12/chromeos_flex_google_chrome_add_shortcut_button.png)

In this place, the websites that you visit the most will appear as a suggested website to go, however, you can also utilise it to save a website that you want to have under a click of a button.

When we click on a button called `Add shortcut`, we will be able to add a website that we want, but that will require some knowledge from our end.

We will need to specify the name of the shortcut, which is a name that will be easier for us what the shortcut refers to.

In the URL field, we will need to specify the domain name of the website. We will need to know the full domain name to add this correctly.

For example, we will type abilitynet.org.uk.

[![ChromeOS Flex - Google Chrome - Add shortcut](/images/2023/12/chromeos_flex_google_chrome_add_shortcut.png)](/images/2023/12/chromeos_flex_google_chrome_add_shortcut.png)

> Don't worry if you typing domain names with small or capital letters, in such things (excluding passwords), most of the time the size of the letters doesn't matter.

Once we click the `Done` button, a shortcut will be added.

[![ChromeOS Flex - Google Chrome - Shortcut added](/images/2023/12/chromeos_flex_google_chrome_shortcut_added.png)](/images/2023/12/chromeos_flex_google_chrome_shortcut_added.png)

Don't worry if this is too much, there is an easier way to save websites that we visit frequently by adding them to "bookmarks" which will be covered next.

## Adding and using bookmarks

The Internet is like a book without an end. With hundreds of millions of pages, sometimes we would like to save some of them for later, so we don't need to search for them each time. For that purpose, the internet browser (Google Chrome) is equipped with bookmark functionality.

The bookmarks are presented with a star symbol in the top part of the internet browser.

[![ChromeOS Flex - Google Chrome - Bookmark Star](/images/2023/12/chromeos_flex_google_chrome_bookmark_star.png)](/images/2023/12/chromeos_flex_google_chrome_bookmark_star.png)

---

When you read a book, you use bookmarks on the pages to which you would like to come back. It is the same with the internet, however, on the internet, bookmarks are not to the same page, like with a book, but to the page (site) that may (or not) change over time.

If you make a bookmark to a home page of the news website, each time you go into it, you may be presented with different things (despite going to the same page), on purpose and as expected.

If you make a bookmark to a specific article over the internet, you may land on the same article again, if you visit the same bookmark later, unless it disappears from the internet (been removed) or has been changed.

---

When you are on a website that you would like to save for the future, you can do this by pressing a star button located in the top right part of the internet browser window.

When you press it, your bookmark will be added automatically. 

You will be presented with an additional window where you can change the name of the bookmark or where it is saved (which folder), but by default, if you just confirm with the `Done` button, that will be all that you will need.

> By default, you will save bookmarks into the `All Bookmarks` folder. For easier access, you may also save them in the `Bookmarks bar` folder. The difference between the two of them will be covered later.

[![ChromeOS Flex - Google Chrome - Bookmark Added](/images/2023/12/chromeos_flex_google_chrome_bookmark_added.png)](/images/2023/12/chromeos_flex_google_chrome_bookmark_added.png)

You will see, that website that is bookmarked will have a filled star symbol near it.

[![ChromeOS Flex - Google Chrome - Bookmarked](/images/2023/12/chromeos_flex_google_chrome_bookmarked.png)](/images/2023/12/chromeos_flex_google_chrome_bookmarked.png)

By pressing that start, you can also access a monit window, whereby by selecting the Remove button, you can remove the bookmark altogether.

### Side panel

When you start building your bookmarks, you may want to know how to easily access them.

The internet browser (Google Chrome) can open a side panel that will show you all the bookmarks that you have saved so far. You do it by pressing the side pannel button located in the top right part of the window.

[![ChromeOS Flex - Google Chrome - Side Panel](/images/2023/12/chromeos_flex_google_chrome_side_panel.png)](/images/2023/12/chromeos_flex_google_chrome_side_panel.png)

### All Bookmarks

Once you add your first bookmark to your Bookmark library, on the starting page (or when you press the home button), you will notice that an additional bar will appear. This is called the Bookmark bar.

When you add bookmarks to the All Bookmarks folder, you will have this folder displayed on the right side of the Home screen of the internet browser.

When you click on it, you can access your bookmarks there.

[![ChromeOS Flex - Google Chrome - All Bookmarks](/images/2023/12/chromeos_flex_google_chrome_all_bookmarks.png)](/images/2023/12/chromeos_flex_google_chrome_all_bookmarks.png)

The more bookmarks you add, the longer the list will be.

Once all the bookmarks are hidden in the **All Bookmarks folder**, sometimes you want them to be added for even easier access.

For this purpose, you utilise a **Bookmarks bar folder**.

### Bookmarks bar folder

When you are on the website that you want to add a bookmark to, you click on the star icon, but this time, before you click the Done button, we will change the Folder but pressing `All Bookmarks` and selecting from the list `Bookmarks bar`.

> In this example I will use The Guardian website (website address, domain theguardian.com),

[![ChromeOS Flex - Google Chrome - Bookmarks Bar](/images/2023/12/chromeos_flex_google_chrome_bookmarks_bar.png)](/images/2023/12/chromeos_flex_google_chrome_bookmarks_bar.png)

Once that's done, when you close the tab or click the home button to go to start, you will see the bookmarks bar containing not only the `All Bookmarks` button on the right side but also an icon and short test of the bookmark that we add to the `Bookmarks bar` folder.

[![ChromeOS Flex - Google Chrome - Bookmarks Bar home](/images/2023/12/chromeos_flex_google_chrome_bookmarks_bar_home.png)](/images/2023/12/chromeos_flex_google_chrome_bookmarks_bar_home.png)

This way you can organise your bookmarks in two folders.

- For easy, quick access, add the bookmark to the `Bookmarks bar` folder;
- For a collection of all bookmarks, keep adding them to the `All Bookmarks` folder.

Independently when you add them, you can always display them by pressing the side panel button as mentioned before.

This way you know that the star presented on the top side of the window will be used as a bookmark for a website that you like and you want to save for later, to return to them in future.

---

This way you know how to browse the internet by searching in the search engine or by going to a website by knowing its address.

---

From turning on the computer, logging into it, browsing the internet and turning off the machine, you start your journey with your computer.

Regards.


---
## Barclaycard - a playground for fraudsters
- **URL:** https://dariusz.wieckiewicz.org/en/barclaycard-playground-for-fraudsters/
- **Date:** 2023-12-11
- **Tags:** Barclaycard, Amazon Prime, Credit Card, Fraud, unauthorised transaction, claim

### Content

I am quite a tech-savvy person and I know how to spot fraud, and how to protect myself from losing money to fraudsters.

To my surprise, I recently discovered 3 unauthorised transactions on one of my credit cards which is issued by Barclaycard.

Because I am using this card to pay for my balance transfer and nothing else, I have been logging into the app only once a month to pay a part of it.

Just last month, when was time to pay it, I noticed that the outstanding balance was higher than what I calculated that I needed to repay. I have looked into a statement and noticed that for the last months, from September to November, each time on the 8th, I have been charged for Amazon Prime £8.99.

The funny thing is, that I already have Amazon Prime, for years, but I am paying it annually and not from Barclaycard. I don't have Barclaycard added to my Amazon account.

Because these transactions are not displayed on my Amazon account, I haven't been able to sort this out with Amazon itself and need to contact Barclaycard.

Before that, I raised claims about unauthorised transactions for all three transactions.

As a precaution, I cancelled my Barclaycard and requested a new one with a new number as I thought that with a new number, no more new transactions would happen. Below I will show how wrong I were in that assumption.

<!--more-->

Every other bank that I am with would cancel any payments when a card is reported as lost/stolen and a new card is ordered, but Barclaycard is different.

Some credit card companies offer an option to freeze cards so your account cannot be charged when you not using it, but once again, Barclaycard is different, as they not offering this option, despite offering it for Barclays accounts (which Barclaycard is a partner company).

In response to customer service for my claims for unauthorised transactions, I received by post a follow-up letter from Barclaycard **blaming me**, rather than thinking that this may be a sign of fraud.

They sent me a letter stating:

> "We would like to inform you that if you had opted for free delivery on an item recently purchased from Amazon, by doing this you have entered into the trial for 1 month_".

This was total nonsense as I am already an Amazon Prime member.

This is followed by:

> "_As you didn't cancel the agreement within the free trial period, the merchant has renewed the subscription automatically._".

**Nonsense!**

I have reached Barclaycard to speak with somebody about this.

I have been put to claims teams who advised me what I already did, which was changing my card. Following that, I want some explanation of how this happens in the first place. Nobody has access to my card, hence how somebody could start a subscription on me?

Because this all looks like a fraud, I have been put forward to the fraud team.

The first contact with the fraud team was unprofessional. They did not show any care about my issue and didn't want to do anything apart from passing be back to the claims team.

**What a joke!**

Again, contacting the claims team needed to explain everything, wasting more and more of my time, to be put to the fraud team, where finally their member of staff did something with it.

The fraud team advised me that they put this case forward, including reporting this to the Police. Fine!

Been advised, that this transaction has been put on stop on their system and I shall not be charged any further. Also, been informed that my money will be refunded to me as well, which was good news, despite I didn't expect that due to the length of time.

On 11th December 2023 I received a text message stating:

> "_We've now refunded 3 fraudulent transactions totalling £26.97, which will show on your next statement._"

I thought that this case was resolved, as the transaction was put on stop and I got a new card, so is not possible that anybody will charge me again without my authorisation.

**Here is how wrong I was.**

Over the weekend, when the next 8th passed (8th December), I noticed that I got a pending transaction from Amazon Prime for £8.99 on my credit card, **again!**

**What the hell!**

I couldn't contact Barclaycard, as the time over the weekend was past their customer service working hours so I moved to Monday to contact them again and waste more of my time.

From my call with customer service, I learned two things from Barclaycard.

First was that they put a hold only on Amazon Prime transactions that had been linked to the same reference number as previous payments. Any other transaction from Amazon Prime will still go through, even unauthorised.

Second, I learned that Barclaycard making a life of fraudsters much easier by informing, whoever used my card to purchase Amazon Prime, that my card changed.

Once my card changed, whoever requested recurring charges from my account, was informed about that by providing payment details to them, so they could update their end and still charge me without authorisation (as explained over the phone).

**What a nonsense again!**

I have checked on the Barclaycard account if there are any connections related to Open banking or other authorisation on my account, but there were none.

In that case, Barclaycard did a favour to fraudsters and let them know how they could still charge me after I changed my card number.

**It's a total joke!**

{{% ads-in-article %}}

The pending transaction on my account has been shown without a previous reference number hence it hasn't been blocked at the start.

Barclaycard is simply not doing any checks required for them by basic banking obligations and they allowing fraudsters and their businesses to thrive!

As the amount is still pending, I contacted them again and they told me, they will put a monitoring in place, so when the pending transaction clears on my account, which means when I will be charged, they will raise a dispute to the merchant.

But why this is after I am charged?

Why were they allowed to do this in the first place?

I have recalled a letter that they sent to me earlier where they stated the following:

> "_However, we'll do our best to stop any further charges that Amazon Prime tries to put through your account from now on._"

This letter was dated 28th November yet my card was still showing pending transactions from 8th December, how this is working?

Following:

> "_If, at a later date, you enter into another agreement with them, please let us know so that we make future charges go through._"

I haven't let them know anything but still, they let further charges go through, hence **what the hell happening here Barclaycard?**

Following a conversation with customer services, I asked them to explain to me how this can happen in the first place. How somebody can charge my card even when the card has been replaced?

Once again been advised, that if it is subscription-based, Barclaycard will update the merchant end with new payment details (like with direct debits, as been explained), however, **this shall not happen in the instance of potential fraud!**

I have been informed, that on my previous calls when transactions have been disputed, their employees shall put on hold any, and all, transactions that may take place without the need for extra verification, but they haven't done that. I requested this from them now.

I also asked what else can be done. I am furious with them right now. The only thing I want to do is to pay my outstanding balance and close this account as soon as it's done. 

I don't want to have anything to do with their incompetence again, but until that happens I don't want to waste any more time disputing transactions all the time.

I have been suggested, as I am not using the card at all, that they can close the card leaving an account open with an outstanding balance. I will not be able to put any more money through but still will be able to pay the balance as I am doing now. 

I asked them to go forward with it. 

They promised me that they would send a letter confirming what was happening and what was put in place.

I am still worried, that even though there is no card active, somehow somebody will still be able to charge me without my knowledge.

All is like in a bad joke movie.

They have all this technology to prevent frauds like this, but this still happening even though, as a customer, I am not at fault.

I can only recall, months back before the first disputed charge, that I purchased something on Amazon using this card, for a very small amount. At that time I noticed that I used the wrong card and I removed the card altogether, hence was no chance that this card could allow for any further charges.

Also, at the time I have been, and still am, an Amazon Prime member, as been for years now, hence is no chance that I will be getting charged double for Prime membership. Even if that could somehow happen, I would have some records and emails to follow but I haven't have any.

**There is also an Amazon fault here which happening for years now.**

If you order something on Amazon, as long you put your name on the card, address details and card number with an expiry date, Amazon will process the payment not asking you for any additional security, including 3 digits security from the back of the card. **Thats a total nonsense but yes, Amazon is doing that!**

Still, I am shocked, that in the first century, in an era when all is computerised, this kind of nonsense happens and big institutions like **Barclaycard not doing due diligence to prevent fraud!**

**That's crazy!**

I admit, that they will refund me, however, it is a post-treatment. How about fraud prevention first?

I am yet to see if I will get my money back from the one that is pending, hence the issue is far from being resolved.

Also looking into raising an official complaint based on what I wrote above to Barclaycard and, if that does not help, to the Financial Ombudsman to see if something can change, as I can bet that I am not the only customer who is charged like that.

This is also why I am making this post. If somebody else is facing the same nonsense from Barclaycard or any other company concerning unauthorised transactions, this will give them a glimpse of what happening on my end.

> To be continued when more information is available.


---
## Namesco is raising domain prices, so it's time to move to Cloudflare and save!
- **URL:** https://dariusz.wieckiewicz.org/en/namesco-raising-prices-move-to-clourdlare-and-save/
- **Date:** 2023-11-21
- **Tags:** Namesco, Cloudflare, registrar, domains, Domain Transfer, Change Nominet Tag, price increase

### Content

Prices of everything are still rising, and people and businesses are looking everywhere they can to save. Domain names used for emails and websites are not the type of service where you can save, however, any price rise is not pleasant to see.

For years, I have been tightening up some of my domains by registering them with Namesco ([names.co.uk](https://www.names.co.uk)).

Namesco is one of those companies that imposes an additional fee on every domain if you decide to transfer it away. They justify this by citing administrative costs, but I've observed this practice with them for years and no other provider does the same.

Over the years, the cost of transferring domains to different registrars has become almost the same as the annual renewal fee. Therefore, there has been no real incentive to pay Namesco an additional fee to transfer a domain.

Today (20th November), I received an email from Namesco informing me of their intention to implement another price increase, effective on 20th December 2023, with a minimum notice period of 30 days.

They proclaim their commitment to price transparency, so they provide a link to [view the updated pricing for affected domains](https://landingpage.names.co.uk/price-changes-domains).

I recall paying £13.99 for the registration and renewal of .co.uk and .uk domains not long ago (2014-2015).

To transfer the domain away, I would have to pay them a £10.00 administration fee plus VAT. For a price difference of £3.99, I couldn't find anyone at that time who could offer me a one-year domain registration for that price.

The price has been increased to £15.99, resulting in a price difference of £5.99. At this point, the cost of transferring the domain to another registrar was either comparable or even slightly lower. Considering the minimal difference, I decided to remain with Namesco for the time being.

Last year, the renewal prices were £16.99 plus VAT per domain. This year, my renewal fees will increase to £19.99 plus VAT per domain, and I have four domains registered with them.

This time, the transfer fee is only half the renewal price, making it worthwhile to compare prices and find a cheaper option.

Over this year, I have transferred some of my domains from other registrars to Cloudflare, primarily due to the discontinuation of Google Domains, another Google service.

As competition in the market diminished, Cloudflare emerged as a prominent provider.

[Cloudflare](https://www.cloudflare.com/en-gb/products/registrar/) as a registrar claim themselves as **Domain registrar with no-markup pricing**, and that **you pay what we pay — you won’t find better value.**

I swiftly determined that transferring my domains to Cloudflare would result in cost savings, even considering Namesco's high transfer fees. Anticipating further price increases from the national registrar (Nominet), these savings are likely to grow in subsequent years.

Registering a .co.uk or .uk domain with Cloudflare costs $4.71 per year, which is approximately equivalent to £3.76 [based on current exchange rates with Wise](https://wise.com/gb/currency-converter/usd-to-gbp-rate?amount=4.71).

By paying a £40 transfer (administration) fee before tax for each of my four domains and adding £15.04 (4 x £3.76) to renew them for another year, I will achieve a **total savings of £24.92**.

In the subsequent year, assuming nothing changes, I will realize a **total savings of £64.92!**

And these are just the domain prices alone.

I don't utilize any of the services offered by Namesco. Cloudflare has been managing my domains' DNS records for quite some time, and other services, such as websites and emails, are independent of Namesco. Consequently, there is no compelling reason for me to remain with their service.

> Since I have already added my domains to Cloudflare and configured their DNS records, I have one less step to complete.

I accessed my Namesco Control Panel and for each domain, I utilized the **Domain Transfer** option. Within this section, I initiated an order to **Change Nominet Tag** and added it to my cart.

{{% gallery %}}
[![Namesco Control Panel with arrow pointing to Domain Transfer option](/images/2023/11/namesco_domain_transfer.png)](/images/2023/11/namesco_domain_transfer.png)
[![Namesco Control Panel with arrow pointing to Change Nominet Tag option](/images/2023/11/namesco_change_nominet_tag.png)](/images/2023/11/namesco_change_nominet_tag.png)
{{% /gallery %}}

I navigated to the **Domain Registration** section within the Cloudflare control panel, where I selected the **Transfer Domains** option. Subsequently, I confirmed the domains I intended to transfer and initiated the transfer process. Finally, I was instructed to contact my current registrar and request a change of the domain tag to CLOUDFLARE. This action is essential for proceeding with the transfer request at the Nominet website.

I provided them with the domain tag and briefly explained my reason for transferring the domains away, which was due to a recent announcement of a price increase. After paying the transfer fee, I waited for them to proceed with the tag change, which is typically completed within one to two business days.

The process of changing the domain tag and registering the domains with Cloudflare was completed much faster than the anticipated one to two business days timeframe. Approximately an hour and thirty minutes later, Cloudflare notified me via email that the domains were successfully registered with their service.

This indicates that the domain tag has been successfully changed, and the domains have been transferred to Cloudflare's registry.

Upon accessing the Namesco Control Panel, I observed that the domains were no longer listed. Conversely, within the Cloudflare dashboard, all domains were displayed as successfully registered.

I'm pretty sure if this process didn't cost me an extra £40 plus VAT, it would've taken way longer. Still, though, I think the cost is excessive but won't dwell on it and will instead focus on the savings.

Before deciding to transfer your domains, carefully consider where you have registered your services and where the DNS records for each domain are currently managed.

I strongly recommend initiating the migration process by transitioning the DNS records of your domains to Cloudflare. To achieve this, you'll need to replace the current nameservers of your domains with the ones provided by Cloudflare during the domain addition process. 

Once everything is functioning properly, you can promptly proceed with the domain transfer process as outlined above.

By investing a fraction of your potential renewal fee, you can achieve significant savings, just like I did.

Regards.

{{% ads-in-article %}}


---
## Google Photos in the Apple ecosystem (on iPhone and iPad)
- **URL:** https://dariusz.wieckiewicz.org/en/google-photos-in-apple-ecosyste-iphone-ipad/
- **Date:** 2023-11-13
- **Tags:** Google Photos, iCloud Photos, iCloud, Storage Saver

### Content

If your daily digital life relies on Google Services, once you become an iPhone owner this may not change. I was a long-term Android user before I changed to the Apple ecosystem.

Even though Apple is offering their equivalent of what Google offers on Android, I never found a better alternative for storing pictures than Google Photos.

Google Photos for most of the typical users is unreplaceable due to the Storage Saver option. Thanks to that we can store all our photos and do not pay too much for the storage. At some point we will need to pay Google to store them, however as they are compressed, they consume less space than storing them in full resolution in, for example, Apple Photo Library.

The first thing that I do when setting up my iPhone is to download the Google Photos app from the App Store. This is what I recommend to my friends who switch from Android to iPhone, however, there is one thing that needs to be remembered.

<!--more-->

When you take pictures on an iPhone, they are stored in the stock Photos app.

Photos in this app, in most scenarios, are backed up into iCloud Photo Library. They are also included in iPhone Backup (Photo Library), which is done into the cloud typically overnight when the phone is charging.

Apple gives you only 5GB of free iCloud storage before you need to purchase more space.

Google gives you 15GB for use across services like Gmail and Google Photos.

When you start storing photos in the Apple ecosystem quickly you will need to invest in a higher iCloud storage plan.

With Google, the 15GB for heavy users will also not last for too long, however, when storing photos in Storage Saver rather than Original quality, the megabytes will disappear less quickly.

This is why I decided to store pictures only in one place, in Google Photos.

To do that, and don't impact unnecessarily my iCloud storage, I need to change two things first.

1. Disable iCloud Photos
2. Exclude Apple Photos from Backup

This sounds simple, but many people forget about it until their phone starts screaming that it cannot backup itself due to lack of iCloud storage.

Also, having turned on iCloud Photos and using Google Photos as well we duplicate the job by backing pictures in both places unnecessarily.

Here is what I typically do after installation of the Google Photos app.

> If you install the Google Photos app and migrate your photos into it from already stored pictures in iCloud Photos, there are other aspects that you need to consider. I will write about it at the end.

## Disable iCloud Photos

Let's make it simple.

Head to **Setting > Your Apple ID > iCloud > iCloud Photos** and make sure that all toggles are off.

[![iCloud Photos with Sync turned off](icloud_photos_sync_off_EN.png "iCloud Photos with Sync turned off")](icloud_photos_sync_off_EN.png)

## Exclude Apple Photos from Backup

Head to **Settings > Your Apple ID > iCloud > Manage Account Storage > Backups** then tap from the list onto your device backup (iPhone) and wait on the next screen until it fully loads the list of backup elements.

[![iCloud Backup with Photo Library turned off](icloud_backup_photo_library_EN.png "iCloud Backup with Photo Library turned off")](icloud_backup_photo_library_EN.png)

Make sure that toggle is turned off near the **Photo Library**.

## Migrating from Apple Photos to Google Photos

If you have your photos backed up into iCloud Photos there is a way to migrate to Google Photos but it takes time.

Firstly, you need to install the Google Photos app and turn on the backup of your photos.

In **Google Photos settings > Backup > Backup quality** make sure it's selected option **Storage saver (slightly reduced quality)**.

> You can read more about it in the post [Freeing up space on Google Photos](/en/freeing-up-space-on-google-photos/).

Keep the app running on the screen and wait until all photos that on the phone are backed up. You can check that by clicking on your user icon in the right top corner where in the section **Backup** it will state **Backup complete**.

Then, from that same menu, you need to choose option **Clear space** which will remove all pictures from your phone that are already backed up in Google Photos.

Due to restrictions in the Apple ecosystem, Google Photos cannot remove pictures permanently from your device so the removed photos will be placed into the **Recently deleted** folder in the Apple Photos app.

By heading to the Apple Photos app, section **Albums** and scrolling to the bottom to the **Recently Deleted** option, press the **Select** button, which will enable the dots menu on the bottom right corner from which you select **Delete All** and confirm removing them on next prompt.

> Don't worry, by using the Clear space option through the Google Photos app you will not lose anything. But remember, removing photos from Google Photos will be removing them from there and from our device. Luckily, Google Photos puts them also into a Bin, whereas the Apple Photos app places them into Recently deleted where they can be permanently deleted or restored in 30 days.

But that is not all.

{{% ads-in-article %}}

For users how been backing up plenty of photos over time, not all the original photos are kept on the phone. They are backed up in iCloud Photo and the phone is storing only high-quality preview to preserve space. They are only downloaded from iCloud when it's needed.

> When Google Photos app is doing a backup, it's only doing it for files that are stored on your device.

By heading once again to **Settings > Your Apple ID > iCloud > Photos** there is an option called **Optimise iPhone Storage**.

[![iCloud Photos with Sync turned on](icloud_photos_sync_on_EN.png "iCloud Photos with Sync turned on")](icloud_photos_sync_on_EN.png)

We will need to change it to **Download and Keep Originals** so that the photos will be downloaded onto our device and then Google Photos can back them up. Once that is done, through the **Cleanup** option and emptying the **Recently Deleted** folder we can get rid of them.

This may require some time and a decent internet connection (not only download speed but also upload speed) to finish, especially in a large photo library. Also, the backup through Google Photos, Cleanup and removal of Recently Deleted would need to be done a couple of times until all pictures disappear from the Apple Photo app and they will be only in Google Photos.

At the end, you will notice that your photos are not consuming your iCloud storage but using Google Storage.

> In storage saver they will use less storage than on iCloud.

You probably will finish with a need to buy more storage from Google but also reduce the storage package of your iCloud.

---

There is one downside of Google Photos on Apple devices.

When using Apple Photos, the photos are backed up when there is an internet connection. To "drop" photos into Google Photos, you need to remember to go into the app, leave it open on the screen and let it do a backup. It's more like backing up only when we decide to do it rather than in the background. 

This has its positive side. You don't back up photos into the cloud storage until you decide to do so. If you doing some photos that you don't want to save, you can remove them from your phone (through the Apple Photos app) before turning on the Google Photos app, and they will not be saved there.

> In subsequent updates to the Google Photos app, the **Background App Refresh** option has been added, which should fix this problem by allowing you to upload photos in the background. To check if we have this option enabled, we need to go to our phone's Settings > Applications > Google Photos.


---
## Travel to Poland with eSIM and Orange Flex
- **URL:** https://dariusz.wieckiewicz.org/en/travel-to-poland-with-esim-orange-flex/
- **Date:** 2023-11-05
- **Tags:** eSIM, Orange Flex, Poland, SIM card

### Content

After five years interspersed with the pandemic and market instability, I flew to Poland to visit my loved ones.

A lot has changed since my last visit. My children need to be connected to the world to a much greater extent than in the past. Personally, I have also become accustomed to having the Internet at hand, always where I need it.

While in England most people with Wi-Fi at home have it at quite reasonable speeds, in Poland it varies depending on where you go.

<!--more-->

Streaming services prevail, and here, with impatient, not so little "kids", buffering while driving around Poland can really heat up the atmosphere in the car.

Even before I went to Poland, I was looking through pre-paid internet offers to find something that would help me satisfy even the most demanding user.

The 5 GB package in the European Union offered by [GiffGaff](/en/giffgaff/) is really nothing. In my case, unlimited internet at full speed is something I would really need.

Since I recently tested [LycaMobile](/en/trying-lycamobile-on-ee-network-as-a-giffgaff-user/) in the UK, I decided to check if I can buy an eSIM card on the Polish side and choose a convenient package there.

Unfortunately, although in the UK I could set up an account with an eSIM card option, on the Polish website I was stuck with the need to already have an number (or at least their SIM with a number). From this I concluded that the eSIM card is not available. I could be wrong, but it's their loss.

I decided to look further and came across the Orange Flex offer, which, being already in Poland, I cannot praise enough.

Orange Flex offers a flexible package in the so-called subscription (not on a prepaid basis, not on a contract basis, but on a subscription). You buy for as long as you want and end when you need it.

Orange Flex supports eSIM cards and full-speed 5G internet, which in my tests was around 100 Mbps (in several places in Poland where I stayed), which was absolutely amazing.

The service offers various tariff plans. Switching the price to the number of available gigabytes, I decided to start with the highest package of 150 GB per month.

This package cost me 80 PLN, which in pounds was just over £15.

When I created the account, I didn't expect that I would actually receive much more from Orange than I expected. Partly due to the simple fact that I did not read the offer, did not fully understand it, or believed it. I was more skeptical about it, which turned out to be unnecessary, but more on that in a moment.

I started by downloading the Orange Flex application available for [iPhone](https://apps.apple.com/app/orange-flex/id1441116618) (as well as [Android phones](https://play.google.com/store/apps/details?id=com.orange.rn.dop)).

When creating an account, I had to confirm my identity. Here I thought the stairs would start for me, but no.

As my Polish documents have expired and I haven't renewed them yet, I used my British passport.

With the UK no longer being a member of the European Union, I expected some problems, but no. Identity verification went without any problems and I was ready for the next step.

After selecting my plan (150 GB for 80 PLN), I proceeded to payment, where I entered my British card (for this purpose I recommend Wise, Monzo bank or any card connected to Curve to get the best currency exchange rate) and paid for the service.

In no time at all, my virtual eSIM was ready to be added to my phone.

As I was still in the UK at the time of purchase, I also expected stairs here. Despite this, my eSIM card was added to my phone and activated, connecting to EE network transmitters without any problem.

This way, I already had two cards in my phone, one from GiffGaff, which I use in the UK, and another one, which I will start actively using when I land in Poland.

For this purpose, in the iPhone settings when I landed, I left GiffGaff as the default calling network, and I set the Orange Flex one as the main data card.

Everything worked as planned and the holiday could begin.

But that's not all.

I thought that 150 GB might not be enough, so I checked in the application how much it would cost me to buy additional gigabytes. There, next to additional data packages, I saw the option of turning on an unlimited package (UNLMTD).

After clicking on it, I saw (which I hadn't read before) that as part of the highest package I bought, I could join it for ZERO PLN.

Without hesitation, I turned it on.

> Without it enabled, connections to social networking sites (Social Media) are not included in the Internet package by default (theoretically), and calls, SMS and MMS within the country and within the European Union are unlimited.

[![Orange Flex - My 150 GB plan with active UNLMTD package](orange_flex_150GB_UNLMTD_EN.png)](orange_flex_150GB_UNLMTD_EN.png)

Now I was really ready to enjoy my holiday without having to control how I use my devices.

Initially, I thought about purchasing an eSIM card for myself and sharing the Internet via a mobile access point (Personal Hotspot) for my family members.

However, here again there was a positive disappointment caused by my failure to read (yet again) what else Orange Flex offers at no additional cost.

Well, as part of the highest package for 80 PLN, I already received a working service with unlimited Internet.

As part of it, I could add 3 additional eSIM cards to the same package.

I decided to generate a QR code and add a card for my wife's phone as well as my daughter's phone, and surprisingly, everything went without any problems.

If I had an Apple Watch or iPad with cellular support, I could also equip this device with an Internet package.

The activation of additional cards, which I performed while still in the UK, officially failed (but only in theory).

> By going to the **SIM cads** tab in the Orange Flex application and clicking on the **Your number** option in the Main number section, a menu for adding additional SIM cards will be available. Not to be confused with adding new numbers to your account.

After more than 10 minutes, while in the activation stage, the phone added the card, but returned information that the activation had failed.

When I tested LycaMobile in the UK some time ago, I also had the same problem. Switching to airplane mode and back previously solved the problem, but not with the Orange Flex.

Cards added on additional devices were displayed as activated, but they did not have a signal (they did not connect to the network in the UK).

I quickly jumped into the chat with Orange Flex technical support in the application and received information that the additional cards in the package only work in Poland, which is why they cannot be connected when roaming abroad.

This wasn't a problem for me as I wasn't planning to use them in the UK anyway, but I wanted to be sure that they would have coverage after landing and would work without any problems.

And so it happened. Each card received the signal without any problems immediately after landing and turning off the airplane mode, and each user could use the Internet independently.

Additionally, each card received its own telephone number, which could be used to call and receive calls within the country.

In my case, however, when I added additional cards, I chose the option that I would use them only for data transmission, because after landing, GiffGaff sent me information that I could call in Poland, to Polish (and English) numbers, just as I would in UK. All calls will be deducted from the available minutes (unlimited in my case), and not from the available balance. This made communication in the country much easier because I didn't have to give anyone my Orange number and cause confusion.

Any devices that did not have cellular communication used a mobile access point (Personal Hotspot), which was a significant convenience.

> A little note here. Some services offering Internet abroad, such as Holafly, although they offer the ability to use any network, do not allow the use of the purchased Internet package beyond the basic device (no tethering, no personal hotspot).

{{% ads-in-article %}}

Here, my next failure to read cost me an additional 79 PLN, because I could have had the first month's package for only 1 PLN using the FLEX discount code.

However, there is nothing to complain about, as my holiday in Poland lasted only a week, so the package would not be renewed for the next period anyway.

The holiday flew by, the whole family used the Internet as much as they wanted (just like at home) and we didn't worry about any restrictions.

We used a lot of data throughout the period and speeds remained high.

Even from our final destination, when traveling to the airport, we used it while in transit and didn't hear any complaints.

Here I was surprised that even when entering the forest, the phone showed 5G network coverage, which I cannot experience in some locations in the UK, although in Poland I encountered black holes.

The holiday has passed and it's time to turn off Orange Flex and not pay for another month unnecessarily.

[![Orange Flex - Information about my current plan](orange_flex_moj_plan_EN.png)](orange_flex_moj_plan_EN.png)

To do this, I went to **My profile** and then to **My Plan** and then selected the **Cancel your Plan** option.

[![Orange Flex - termination of the plan within 14 days](orange_flex_zakoncz_plan_EN.png)](orange_flex_zakoncz_plan_EN.png)

Interestingly, since I purchased my plan a few days before departure and my vacation lasted less than a week, when I wanted to cancel it, I was informed that I could get a refund for the plan. All because I made it within 14 days of purchase.

I didn't really care about the refund, because the plan fulfilled its purpose during the trip, but if they insist, why not.

Therefore, I confirmed the resignation and loss of the number.

On the home screen, I received confirmation that my request was being processed. After a while, the plan was canceled and my eSIM card lost coverage. I could then remove it from my phone and any additional ones from the other devices I added them to.

My app account remains active and I can choose a future plan whenever I need to.

This way, I have a proven solution for unlimited internet for the whole family and all devices at a very reasonable price, even for free (which will probably change in the future, because I don't see how it can be profitable for them).

Regards.


---
## Upgrade Windows 11 Home to Pro
- **URL:** https://dariusz.wieckiewicz.org/en/upgrade-windows-11-home-to-pro/
- **Date:** 2023-10-18
- **Tags:** Windows, Windows 11 Home, Windows 11 Pro, Windows 11 Enterprise, upgrade

### Content

Recently, I had to put into use a computer that was delivered with Windows 11 Home version by default. Since I need the professional version in the environment where I need to use it, I decided to upgrade it.

Once you have purchased the product key, the easiest method is to go to **Settings** > **System** > **Activation** and enter the Pro version key in the `Change product key` section.

Unfortunately, although I have used this method before on other computers, this time I received information that the product key provided cannot be used to upgrade the currently installed system.

I decided to check whether I would be able to upgrade Windows 11 from Home to Pro using [the method of updating Windows 10 Home to Pro I described earlier](/en/upgrade-windows-10-home-to-pro/).

<!--more-->

I already had a downloaded Windows 11 ISO image loaded onto a pendrive using the [Rufus program](https://rufus.ie). If you do not have an ISO image of Windows 11, please refer to my post [How to download a Windows 10 image (ISO)](/en/image-iso-windows-11/).

---

Similar to the Windows 10 method, I started by changing the system registry.

To launch the system registry, simply click the 'Windows Logo + R' keyboard shortcut, then enter 'regedit' in the newly opened Run... window and confirm with the <kbd>Enter</kbd> button.

> Alternatively, click on the 'Start' button and type the word 'regedit' and you should get the 'Registry Editor' suggestion.

Go to the basic folder `HKEY_LOCAL_MACHINE > SOFTWARE`.

1. Then to `Microsoft\Windows NT\Current Version`

Here, in the right part of the window, we change the values of `EditionID` to `Professional` and `ProductName` to `Windows 10 Pro`.

[![Windows 11 Registry Editor](Registry_Editor_Windows_11.png)](Registry_Editor_Windows_11.png)

> Yes, we enter Windows 10, even though we are updating Windows 11. As you can see, Windows 11 is just a souped-up Windows 10.

2. Return to the basic folder and go to `WOW6432Node\Microsoft\Windows NT\Current Version` and make the same change as above.

[![Windows 11 WOW6432Node Registry Editor](Registry_Editor_Windows_11_WOW6432Node.png)](Registry_Editor_Windows_11_WOW6432Node.png)

3. Run `setup.exe` from the Windows 11 installer.

> If you downloaded the ISO image, you can unpack it using [7Zip](https://www.7-zip.org).

{{% ads-in-article %}}

To speed up the entire process, I recommend disconnecting your computer from the Internet, as the installer may want to perform system updates first before starting the installation, which may significantly extend the entire process.

[![Windows 11 installer ready to upgrade to Windows 11 Pro](Windows_11_Pro_ready_to_install.png)](Windows_11_Pro_ready_to_install.png)

If you have done everything correctly, after a shorter (or longer) analysis, the installer will ask you whether you want to install `Windows 11 Pro' with `Keep Files and Applications`.

> If the installer still informs us about `Windows 11 Home`, then we close it and check our system registry again, in particular `Microsoft\Windows NT\Current Version`.

Now just wait and enjoy the effect.

---

After restarting the computer, our system should be upgraded to Windows 11 Enterprise.

> Yes, not Windows 11 Pro as we intended.

We can reconnect our computer to the Internet.

By going from the Start menu to **Settings** > **System** > **Activation**, we need to make a change, enter our Windows 11 Pro key and activate it.

The upgrade should go without any problem, and the system version will change from Windows 11 Enterprise to Windows 11 Pro.

---

The last step will be to go to Windows Updates and check if there are any new ones available to install. As a rule, this operation will include new ones that **must be** installed first before we start using our system.

And that would be it.

Regards.


---
## Trying LycaMobile on EE Network (as a GiffGaff user)
- **URL:** https://dariusz.wieckiewicz.org/en/trying-lycamobile-on-ee-network-as-a-giffgaff-user/
- **Date:** 2023-10-06
- **Tags:** LycaMobile, EE Network, GiffGaff, eSIM, SpeedTest

### Content

I am a long-term GiffGaff user. I don't remember for how long now, it was something around mid-2012. For years I constantly recommended GiffGaff due to great prices per monthly bundle (goody bags) and prices for calling abroad. Nothing has changed. I still recommend this to everybody who wants a bit of saving and great value for money, but I am always looking if there is something better.

<!--more-->

[GiffGaff](/en/giffgaff/) relies on the O2 network and this is why I have stuck with them for so long. I have been on O2 for long. Shortly I explored Three UK but quickly moved away, as it was, and still is, rubbish for daily use in different locations.

Recently I read about **[a mess that happened on Lyca Mobile](https://www.moneysavingexpert.com/news/2023/06/lyca-mobile-has-started-switching-customers-from-o2-to-ee---here/)** when they decided to migrate from O2 infrastructure to EE without properly informing their customers (or seeing how this affect them). This doesn't look great, but not looking back, I want to try to see how the EE network works in places where O2 is struggling. Lyca Mobile on EE become a much more compelling choice.

Currently, I am paying £10 per month for 20GB Golden GoodyBag (with an extra 1GB on them if I run low) to get unlimited calls and text in the UK. All chargeable numbers and international calling are charged from a separate balance that I need to keep topped up.

> The good news is, if I purchase Goodybag and I run out of data before 30 days, I can purchase a new one earlier. I don't need to wait till the end of the period to do that. In Lyca Mobile this however is not the case. Once purchased a plan, even if you run out of data, you cannot purchase another one before the end of the 30 days.

The Lyca plan that I am looking for (end of August 2023), which is competitive with GiffGaff is also 20GB (for new customers), with Unlimited calls and Text for the same price, which is £10 per month, but for new customers, it is discounted to **£5 for first 6 months** if you keep auto-renewing your plan.

Additionally, I am getting 100 international minutes to 40+ destinations, including Poland where I am calling most of the time (however less over the mobile network but more over various communicators).

**100 international minutes for free is a good deal for a start.**

As I am mostly calling mobile numbers in Poland, in GiffGaff, this will cost me 5p per minute, hence these 100 minutes are worth £5. That's not a bad deal. Above that it's 6p per minute on [Standard International Rates](https://www.lycamobile.co.uk/en/rates/).

The only aspect that I consider is, are EE network coverage better than O2. [All the signs say that EE works better](https://www.moneysupermarket.com/mobile-phones/networks/reviews/ee-vs-o2/).

I know what to expect from O2, but also know where O2 is lacking. My friends who are living in other parts of Leeds, UK have significant issues with phone calls inside their home (1 bar and 4G there is the maximum or no signal at all). I have an experience where it is not possible to use any data with your phone showing 3G, but sometimes, in weak 4G, it's not working as well and nothing has changed for years.

> This is not a specific GiffGaff issue but an O2 network overall.

In some rural areas that I have been to recently, there was no reception at all, despite [the coverage map of Ofgem](https://checker.ofcom.org.uk/en-gb/mobile-coverage) showing differently. When I finally got 1 bar of 4G the internet was still not working.

This made me think and I decided to give Lyca Mobile a try. In the worst case, after a month, or so, I will come back to GiffGaff, as migration between operators, when you are not tightened to a lengthy contract is right now straightforward.

> Read: [How to Switch Mobile Network in the United Kingdom](/en/how-to-switch-mobile-network-in-the-united-kingdom/)

With Lyca, I would like to try eSim in the first place (GiffGagg still hasn't figured it out, or rather O2 didn't allow them to go into this route). While still using GiffGaff I can go dual sim on my iPhone before deciding to migrate (or not).

Having a physical GiffGaff card on my phone I decided to activate eSIM from Lyca to try, and, on the other day migrate from one network to another.

![Activating eSIM on LycaMobile](LycaMobile_Activate_eSIM.png)

Despite that purchase experience was straightforward and I received my QR code to activate my eSIM, this didn't go according to plan.

![Unable to activate eSIM on LycaMobile](LycaMobile_Unable_to_Activte_eSIM.png)

When trying to activate my eSIM I received a message **"Unable to Activate eSIM. You can try again or contact the network provider for assistance"**.

**Not a great start!**

Just wonder if that was something with the fact that I purchased eSIM on the August Bank Holiday in the UK, and because of that the network may not have activated it yet.

Decided to wait an hour or two before trying again, and if unsuccessful again, I will decide to give Lyca a call.

> In opposition to GiffGaff, you can call Lyca and speak with a human, so that's a plus.

In the meantime, I searched the internet and haven’t found any information about this issue, especially not related to Lyca. Heading to the EE community forum some people recommend taking out the physical sim and then trying to activate eSim. Decided to give it a go.

Tried, but the result was the same.

Decided to give them a call on **0207 132 0322**.

The difference between GiffGaff and Lyca is the thing that you can dial their customer service number and speak with a human and not rely only on dropping a message to an agent and waiting patiently until they respond.

Without long waiting times, I have been able to speak with somebody. They opened a case on their end, through which they will generate me new QR code with my eSIM card, as most likely there is a fault with my current code. Sadly, this will take more likely 24-48 hours.

Goods that I am not in a rush for my new card and I can wait for a new QR code, in another case, this is not a great start, but let's understand that this is just a technology that is not false proof.

I am meantime I want to check my theory, that the eSIM are not always ready from the first minute after purchase, especially those from virtual operators like Lyca and I got right.

Six hours later I decided to re-try adding my eSIM to my phone by scanning the QR code from my email.

![Another try activating eSIM on LycaMobile](LycaMobile_Activate_eSIM_Activating.png)

This time there was no error message and **"Activating..."** stayed on screen a bit longer.

![Connecting to network during activation of eSIM on Lyca Mobile](LycaMobile_Activate_eSIM_Connecting_to_network.png)

Shortly after a while it changed into **"Connecting to network..."**.

![Activation of eSIM on LycaMobile been completed](LycaMobile_Activate_eSIM_Continue.png)

Roughly a minute later it showed the **"Continue"** button with a message that I could use my iPhone while they activate my eSIM.

In the next steps, I followed setting the primary SIM card, which is used for Data and secondary for other stuff. **Nice.**

![Dual SIM displaying GiffGaff and EE (LycaMobile) on iPhone](GiffGaff_SIM_and_LyceMobile_EE_eSIM.png)

Once my phone showed GiffGaff and EE network on my Gmail landed an email from Lyca Mobile with information about the activation of my eSIM and my Lyca number.

> Despite that I have been promised a new QR code for my eSim Lyca never came back to me. This is not a great approach, despite being able to speak with humans, they do not tend to do what they telling you.

I quickly turned on Airplane mode then once again I received text messages from Lyca Mobile that **Bundle Activation been Successful** and then another text message with my phone number.

This was followed by a link to register my phone number at [LycaMobile.co.uk/en/registration](https://www.LycaMobile.co.uk/en/registration), which I do.

With this number, I could finally start exploring Lyca starting with downloading the mobile app (for [iPhone](https://apps.apple.com/gb/app/lyca-mobile-uk/id1670808515) or [Android](https://play.google.com/store/apps/details?id=com.lycadigital.lyca_mobile_uk)).

> After a few days my phone displayed EE as a network provider and changed to be displayed as LycaMobile. This is probably because network settings on a phone need to be updated. That same case is with GiffGaff which is displaying O2 first and then updating itself to display the right name.

---

When I purchased eSIM for use by my friends, during the week, the activation took approximately 5-10 minutes without any errors. My experience probably has something to do with non-working days.

---

Once that was done I decided to compare speed in my location.

I turned off my Wi-Fi and ran [fast.com speed test](https://fast.com) on my Primary sim card.

![SpeedTest carried out using fast.com for GiffGaff in O2 Network](SpeedTest_fast_com_GiffGaff_O2.png)

The peak download speed was around 110Mbps and the download 25Mbps with an average of 90/17 on O2. 

When I switched from Primary card for data use to Lyca, to my surprise I received information that I am using LTE, not 5G.

This was the first time that I saw an LTE connection in the UK for a while, as typically it's 4G or 5G (than 3G). In Poland, where I used to live, the LTE (or LTE+) was a very common name years back.

![SpeedTest carried out using fast.com for LycaMobile in EE Network](SpeedTest_fast_com_LycaMobile_EE.png)

Despite that LTE in theory shall be slower than 5G, during the test it peaked at 270Mbps and stabilised at around 100Mbps with download and 22Mbps peak upload.

This LTE made me think so I headed to Settings > Mobile Data and checked the default setting on the Voice & Data option.

{{% gallery %}}
![GiffGaff Voice & Data options on iPhone](Voice_Data_options_GiffGaff.png "GiffGaff Voice & Data options on iPhone")
![LycaMobile Voice & Data options on iPhone](Voice_Data_options_LycaMobile.png "LycaMobile Voice & Data options on iPhone")
{{% /gallery %}}

> There were more options available there on Lyca than on GiffGaff.

There it was LTE set by default and not 5G Auto. I switched to 5G Auto and tried again.

> Once I first ran a speed test on LTE, and shortly after received a text message from Lyca, that I could enjoy 5G data.

![Dual SIM displaying EE (LycaMobile) and GiffGaff on iPhone](LyceMobile_EE_eSIM_and_GiffGaff_SIM.png)

This time I noticed 5G in the network bar and not LTE.

![SpeedTest carried out using fast.com for LycaMobile in EE Network and 5G signal](SpeedTest_fast_com_LycaMobile_EE_5G.png)

Not surprised however that LTE was set by default, as speeds on 5G were worse than on LTE peaking at 80Mbps on download but upload peak at 30Mbps to finish at an average of 72/14.

---

Then I remembered that my iPhone had Apple's Private Relay turned on by default. This may have an impact on internet speeds. I decided to remove that and repeat the tests.

- GiffGaff (O2) finished at 120Mbps download and 16Mbps upload average on 5G.
- Lyca (EE) finished 83Mbps on download and 21Mbps upload on LTE.
- Lyca (EE) finished at 54Mbps on download and 18Mbps upload on 5G.

What interested me was Latency on EE on 5G and LTE, which is way worse than on O2. Better latency will work great for people playing on their mobiles.

O2 showed Latency at 49ms when Unloaded, but when loaded peaked at 503ms. You can interpret this as a lag in a game of 0.5 seconds.

EE latency was 61ms when Unloaded and 1s (that's 1000ms) when Loaded on LTE, and 1.8s (1800ms) on 5G. **That's bad!**

> To compare, my home internet on Virgin Media 250Mbps connection has a latency of around 80ms (on my OpenWrt router).

---

A big test would be **however** to check this in destinations where I always struggle to get internet, like my friend's house. The map of coverage from Ofgem looks way better for EE than for O2 with them.

Also, at my place of work, I rarely have 5G service indoors and wonder if I will manage to get it with Lyca Mobile. Looking at an Ofgem map, the indoor coverage is patchy.

The speeds were very similar however latency on EE, once again, was poor!

{{% gallery %}}
![GiffGaff Speed Test 5G (at location 2)](SpeedTest_fast_com_GiffGaff_O2_location_2.png "GiffGaff Speed Test (at location 2)")
![LycaMobile Speed Test 5G (at location 2)](SpeedTest_fast_com_LycaMobile_EE_5G_location_2.png  "LycaMobile Speed Test (at location 2)")
{{% /gallery %}}

My test at my friend's house went smoothly but the results weren't as impressive as I would expect.

Overall signal strength was better. The advantage of having LTE among 3G, 4G and 5G maintain the connection in weak spots.

During the test call, the call was fine (not great, but fine), however, I haven't lost the recipient. When disconnected, noticed that GiffGaff (O2) showed No Service info where Lyca Mobile (EE) had still been operational.

Where O2 shows barely one bar of 4G and constantly switches between 3G and 4G, the EE shows one bar in 5G.

The speeds oscillate from 1Mbps on download on O2 to 8-9Mbps on EE, so that's an improvement. The strength of EE has been comparable to what the Ofgem map showed for my friend's location, however, there was one spot where EE showed me No Service and GiffGaff still hung on a single bar. This however was (EE) way better than what my friends experience every single day, where they miss precious calls because their phone shows them No Signal or a weak signal didn't allow them to go through.

This proves the point, that, at least for them, trying different networks may be a good option for their problems.

> My friend has been using LycaMobile for a couple of weeks and noticed that sometimes the phone is losing signal as well (less than GiffGaff), however when it does it's more aggressively trying to connect back, probably trying different frequencies. This results in a huge battery drain. On one day when I checked, 25% of the loss of battery on her iPhone was due to No Service rather than the use of other apps. Thats bad.

Despite complaints, O2 didn't do anything for years to improve their signal in some areas, hence EE will grab these customers who need a bit more reliability.

{{% ads-in-article %}}

**Let's not think that everything is better.**

![GiffGaff on O2 with 4G when LycaMobile on EE displaying No Service](GiffGaff_O2_4G_LycaMobile_EE_No_Service.png)

I went to my normal place where I training Karate to find out, inside the place (Church), there was **No Signal** from EE at all when O2 still managed to have full signal on 4G.

This makes me think, is this solution good for me? Maybe it will be better for my friend, but not necessarily for me.

I kept looking for other things before I made a decision.

---

Another difference between Lyca Mobile to GiffGaff, despite that the GiffGaff website is much more user-friendly (accessible), you can see your Billing History on the website (if it's working).

This may sound crazy, but sometimes, when you wonder where you have been charged from your balance or where your data goes, you can see it there.

---

One surprise for me with Lyca was the lack of Two-Step Authentication to access your profile. You can do a SIM swap straight from your account, the lack of additional authentication is a bit risky in current times.

---

If you travelling to the EU, it will be very important for you to be able to use your phone as you tend to use it. Due to recent changes, most of the operators implemented Data Cap when used in the EU. In GiffGaff, through O2, imposed a 5GB data cap independently if you got a Goodybag with 20GB or a lot more.

With Lyca Mobile is a bit different. The cap depends on the package that you purchased.

For example, in my current package of 20GB, my EU Roaming Data Cap is set at 12 GB.

If you opt-in to the Unlimited plan (speed capped after 300GB uses), you will get 35GB for roaming.

**In both instances, that's way better than just 5GB.**

---

From time to time, when my internet goes down, I need to regain access to my laptop and for this purpose, I am using Tethering.

In GiffGaff there was no issue with that. You using the plan that you purchased and your allowance. 

I was a bit surprised that Lyca Mobile in their terms and conditions forbids Tethering and advises that data can be used in the mobile phone only. **Seriously!?**

That's a bit of nonsense. In current times, if you paying for something you shall be able to do with it what is possible.

Here is a bit of a mess on the Lyca Mobile end. When you try to go through their website, you will find conflicting information, and tethering is also the same. The only article I found there was from 2019, which is 4 years old, saying that you cannot tether, however, the UK popular site uSwitch, when describing Lyca Mobile stated that it is allowed, hence they need to have, possibly right, information.

> They recently updated their website and their [FAQ](https://www.lycamobile.co.uk/en/help/faq) section where they answered the question as **Yes** and removed reference to old inaccurate articles.

Here the power of the GiffGaff community wins keeping their website fresh and updated, and any old inaccurate information is removed. On Lyca, what has been published, which is not necessarily still the case, is still there. Possibly a different employee added this, and since then when he left, nobody has reviewed that. That is not a good thing, especially since you would like to base all your information using the source - their official website.

---

After the pros and cons, I decided to give it a try, **but I have not fully resigned from GiffGaff**.

I kept my number with GiffGaff but switched data use for Lyca Mobile (EE) to see in real life how it works. I turned off recurring Goodybag for a month and selected my main internet to be used through the EE network.

When I decide, I can [transfer my number to Lyca Mobile](https://www.lycamobile.co.uk/en/transferyournumber) using their form, or cancel Goodybag and use it for a bit longer as PAYG, as most of my friends are with GiffGaff and I got typically 3 months of free GiffGaff to GiffGaff calls and texts since last top-up (purchased Goodybag).

Will see how it will go.

> For now it's like me and my bank - Monzo. I know that other banks give bribes to join them, some of them even £200, however, the flexibility and useability of Monzo, and the lack of unnecessary bureaucracy do not compensate for taking steps back with something that is part of my financial life.

---

I port a couple of people over to GiffGaff and this was always straightforward, but with Lyca Mobile I feel like a novice user.

Whoever comes up with the idea of Porting Form shall be fired.

![LycaMobile porting form](LycaMobile_porting_form.png)

Name, Surname, email, **number you want to keep** then PAC code look very similar, but next we need to put New number (?).

What is a New number if we **keep the number provided earlier?**.

The Lyca Mobile SIM number is the temporary mobile number attached to our eSIM that will be replaced with our ported number.

Then we got another mobile SIM number, **which is?**

Finishing with porting date and the acceptance of Terms and Conditions before moving forward.

I was seriously stuck in that form and decided to use the robot icon available in the right bottom corner and do this through it. It was much more intuitive and 2 days later my friend was moved and she was able to start testing Lyca Mobile in a field.

> The good news with GiffGaff is, that even when you move away, your account, login details and password will still work. Simply you will not have any SIM attached to it. If you decide that Lyca Mobile is not for you you can easily move back to how it used to be.

The initial test for my friends went so well that they decided to move their other number (partner's number) to Lyca Mobile as well.

> Since I tried to port a number Lyca website has been updated along with the porting form. However, I haven't been able to see how it looks as their new website constantly has problems and apart from rought information you cannot even access your account.

---

On that day, when we decided to migrate my friend my Golden Goodybag from GiffGaff expired and I started testing the internet over the EE network as well to give me an overview of how good, or not, this would be for me before I decide, or not, to move my number across. I am not rushing into that and if needed, I will keep testing until my statutory GiffGaff to GiffGaff free calls will be due to expire, which is 11th November 2023.

{{% ads-in-article %}}

---

There is another reason why I am not rushing into moving across from GiffGaff is the fact that I [recommend people](https://giffgaff.com/orders/affiliate/itdarek) and I am collecting incentives from that, which is accumulated over periods of months. Currently, I have a small amount for payback for the period finishing in November 2023 and don't want to risk losing it. But that will give me plenty of time to test Lyca Mobile in a field.

---

Time has passed and I haven't found any difference in my use between GiffGaff (O2) and Lyca Mobile (EE).

I know that in some areas it will be better (my friends proved to me that when they got to the sea area, none of their friends on O2 got a signal when she got it all working well), but mostly, in these rural places I am occasionally, typically on school holidays. Having the option to attach eSim in a short period will add options when I need them.

I keep thinking about what to do and the recent events with Lyca mobile just assured me that, when Lyca is working for my friends well, I will not be staying with them.

Some things that I experienced in the testing period just assured me that this was right for me.

---

At the end of September and the beginning of October 2023, Lyca updated their website worldwide and they messed up with it so badly, that people haven't been able to do anything with their accounts.

![LycaMobile website down](LycaMobile_website_down.png)

In 2023 they refer people to go back by 10 years when to top up the phone you been forced to go to a physical shop, buy a voucher, dial a number and type the code from the card.

I cannot believe what I saw.

At this time I have been ready to turn off auto-renewal of my plan but I haven't been able to do so either.

Luckily for me, I still got like 3 weeks before its end and a few days later I was able to log into my account and turn it off.

![LycaMobile App down](LycaMobile_App_down.png)

Good that I did this, as at the time of finishing this article, logging into the account on their new website is down again. The mobile app also throws out an error message and nothing you can do about that.

I still have less than 3 weeks with Lyca before my plan terminates and I reactivate my Golden Goodybag at GiffGaff, but even that I cannot do anything on my account without going into the methods used ages ago by dialling special codes to check my balance.

---

The problems with the website, mobile apps and logging onto the account were just a final confirmation of the decision that I already made, to leave Lyca and stuck with GiffGaff as a main provider.

There were other things that I didn't like.

---

From day one, when I was attached to an eSim and a new Lyca number I started getting spam calls on that new number.

The number that nobody knew, in theory, suddenly been known by telemarketers. The surprise was that they knew my name, so they got this information from somewhere. 

It looks like Lyca is doing some shady business selling their customer details. If I just get random spam calls, I would think that they reused some number from the past, but the callers knew the details that they should not. **Worrying!**

---

The other aspect was when it came to the time when your plan was meant to be renewed.

GiffGaff is sending you all the information about when the plan is ending, what the next plan and, more important, how much it will cost and when they will charge you.

Lyca is less transparent. 

You get information that your plan is extending but you don't know how much you will get charged.

I initially signed into a deal, so as long my Auto-renewal is on, for the first months I am supposed to be charged only £5 for a plan that normally costs £10, but how am I supposed to know how much they will charge me.

There was nowhere information so see what my charge will be. Also, when (finally) logging into my account I couldn't find information on how much I am currently paying or will be paying. 

This is a bit shady.

> Maybe with their new website this is meant to change, however, with current problematic access through it, I will not hold too much hope.

Every single text message and email reminding me about the renewal of my plan has been also not clear, without any cost etc.

I cannot stand this like that if I don't know clearly how much I am paying.

If they somehow change their prices and I do not notice, I will be facing an ugly surprise that I cannot do anything about it until the next plan starts.

---

When I thought that things could not go any worse LycaMobile sent me the following text message:

> "Lyca Mobile is responding to a data security incident. As a precaution, please read our customer guidance at lycamobile.co.uk/en/update"

There you can read:

> "Lyca Mobile UK Limited has been the victim of a systems cyber attack."

> "Lyca Mobile first became aware of this on 30 September and took immediate action to contain the incident, which included isolating and shutting down systems where appropriate."

As I mentioned in the beginning, the fact that accounts with LycaMobile are not protected by a factor authenticator was one of the things that stopped me from migrating my main number to them and I keep exploring in a dual sim environment.

I bet that they will handle this and learn from the past but for me, it was an interesting experience GiffGaff will remain my main choice.

---

As I mentioned, there are some pluses and minuses of joining Lyca Mobile.

Ignoring the costs, which Lyca is trying to go absurdly low to gain customers if your main issue is the signal and speed of your mobile internet, then LycaMobile is a good way to try EE network.

In any other instances I still strongly recommend joining GiffGaff where I am heading back really soon.

> **ps. If you read this in full, I officially never left.**

If you are interested in joining GiffGaff, you can always do that by ordering a free SIM card with delivery to your home, and  additionally by getting at least **£5 balance on it for free** when purchasing your free plan but using the below referral code:

[https://giffgaff.com/orders/affiliate/itdarek](https://giffgaff.com/orders/affiliate/itdarek)

---

Throughout 2024, there was a lot of talk about Lycamobile, and most of it was not good. Due to their below-cost tactics to gain customers, they are currently a loss-making company that additionally owes millions to the UK tax office (HMRC). If you decide to stick with them, calculate the pros and cons, and the risk that may arise if they go bust.


---
## Virgin Media joining the gang and will start increasing prices in mid-contract
- **URL:** https://dariusz.wieckiewicz.org/en/virgin-media-joining-the-gang-increase-prices-mid-contract/
- **Date:** 2023-09-15
- **Tags:** Virgin Media, price increase, mid-contract, Retail Price Index, RPI, Consumer Price Index, CPI

### Content

As a Virgin Media customer for many years, I have always appreciated the fixed price guarantee that I get when I sign a contract. There are no hidden fees or price increases, and I can be confident that my monthly bill will stay the same for the entire contract term. In the month before my contract ends, I will be able to negotiate a new contract or switch to a different provider if I find a better deal.

Unfortunately, Virgin Media has decided to join the trend of other companies and raise their prices. They have notified their customers that their pricing terms will be changing.

> As explained by them, price increases are being attributed to rising inflation, which is currently at a 40-year high in the UK.

<!--more-->

In the past, if Virgin Media decided to change prices mid-contract, they were required to inform their customers and give them the option to terminate the contract without penalty if they did not agree to the price increase.

The email received is your final opportunity to end your contract with Virgin Media without incurring an early termination fee.

If you are on a new contract with Virgin Media, or if your contract is halfway, you will need to decide **by the end of October 2023** whether to accept the new terms or to terminate your contract without penalty.

> If you do not accept the new terms, you must give Virgin Media 30 days' notice in writing of your intention to terminate your contract. **If you do nothing, your new terms will be accepted automatically.**

If you accept the new terms, Virgin Media will increase the price of your contract by the Retail Price Index (RPI) rate of inflation plus an additional 3.9% each April. Based on the current RPI figures, this would be an increase of 13.8% each April.

> Virgin Media uses RPI+3.9% for their price increases, while other providers typically use CPI (Consumer Price Index). RPI is generally higher than CPI, so Virgin Media's price increases will be more expensive for customers.

Virgin Media contracts are typically for 18 months, so your price will go up at least once during the contract. If you sign your contract between October and March, your price may go up twice during the contract.

If you pay £27 for 250Mbps broadband, like me, and that's a good deal with them, then your price would rise to £30.78 in April 2024, based on the current RPI rate of inflation.

My contract is due to expire in mid-January 2024. This means that I will be facing a double price hike if I do not negotiate a better deal.

In that case, I will need to negotiate the price carefully.

If I am able to negotiate the same price of £27 per month, my monthly bill will increase to £30.78 in April 2024 and to £34.20 in April 2025.

Currently, on the market, only Hyperoptic has not opted into mid-contract price increases. However, their service availability is limited, and they will need to invest in infrastructure to make it available to more customers. This will cost them money, so I will not be surprised if they eventually opt into the same rules as other players on the market.

A price increase announcement is never welcome, but don't make any rash decisions. Do some research first and compare what other providers are offering. If you find a good deal, assume that the price you are quoted now will increase (twice) by 14% each time. Do your calculations quickly to see if it would be better to stick with what you have now.

Remember to use good comparison sites like Uswitch or MoneySuperMarket to see what's available to you. You may also want to consider Vodafone, which recently teamed up with CityFibre and can offer you a synchronous connection (like 100 Mbps download and 100 Mbps upload), which is not offered by most other providers.

If you have recently started a contract with Virgin Media or will still be in contract through April 2024 and will be affected by a price hike, it is always worth calling them before you decide to leave to ask if they will waive the price increase or offer you some sort of discount. However, remember that they are under no obligation to do this, so be polite and respectful when you communicate with them, as they are giving you an option and not forcing you to stay.

Remember that you have **until the end of October 2023** to let Virgin Media know if you want to accept the new terms or terminate your contract. If your contract expires before April 2024, like mine, you do not need to do anything. However, keep in mind that prices will increase in April 2024, so make sure to get a good price (discount) when you sign a new contract to compensate for future price hikes.

{{% ads-in-article %}}


---
## Anyone Can Create an Apple ID with Your Email Address without Your Permission
- **URL:** https://dariusz.wieckiewicz.org/en/anybody-can-create-apple-id-with-your-email-address/
- **Date:** 2023-09-14
- **Tags:** apple, apple id, email, apple support

### Content

Imagine waking up one day to 11 unread emails from Apple asking you to verify your Apple ID. **Someone has just created an Apple ID with your email address on their new iPhone!**

<!--more-->

The first thing you might think is that someone has gained access to your email. You would then take steps to secure your account, such as changing your password, enabling two-factor authentication, and reviewing your activity logs.

You think that's enough, but then you find dozens of other emails from someone trying to verify their Apple ID with your email address.

**Isn't it a bit annoying and concerning?**

Following your intuition, you carefully read the email and follow the instructions. The instructions state that if you did not create the Apple ID, you can reset your password at [iforgot.apple.com](https://iforgot.apple.com/).

You might think that this will be straightforward and you can resolve this issue quickly. **But you may be wrong about that assumption.**

The website will greet you with a **Reset Password** button, followed by a short form where you can enter your Apple ID and type a text-based security code presented in graphic form.

After clicking the **Continue** button, you will be stuck on the next screen, where you are asked to confirm your phone number.

To your surprise, the phone number will be displayed in a hidden form, with only the last two digits visible.

To your annoyance, the phone number displayed is not yours, but the person who created the Apple ID with your email address.

Without knowing the phone number to enter at this stage, you will be stuck and unable to do anything else.

Try typing whatever you want, but you will end up with the following message.

> _This phone number is incorrect. Please enter a phone number that you use to receive verification codes for two-factor authentication._

At this stage, you realize that you are stuck and there is **nothing you can do about it**.

The initial thought would be to contact Apple for help. This should be straightforward, and they should be able to help you in no time.

**Here is how wrong this assumption is!**

Let's contact Apple via chat.

You will be informed by chat support that this issue cannot be resolved through chat and needs to be escalated to a phone agent.

You may think that this is even better. You will have a human interaction with someone who can listen to your issues and concerns, and help you resolve them.

You may even describe how worried you are that someone is using your email and Apple ID to commit fraud, only to be surprised that your concerns are not taken seriously enough to be acted upon.

After spending some time on call, I learned that help with such an issue is very limited, or even **not possible**.

The only advice you will get is that you will not be able to create an Apple ID with your email address in the future, and you will need to use a different one.

But what if you don't want to create a new email address right now? What if you don't want to go through the hassle of opening another email account just to get your Apple ID working?

**The simple answer is that you cannot do anything about it**. This is what you will get from an Apple Support representative during a call.

According to Apple Support, it is possible that someone added your email address to their Apple ID by mistake because your email addresses are very similar. They may not realize that they have made a mistake, and they will continue to try to verify their email address without receiving any emails.

Apple Support will likely claim that they cannot do anything about this issue, as there is a chance that the person who used the wrong email address will eventually contact their support to get it sorted out. However, I believe that it is more likely that the person will simply give up and create a new Apple ID, leaving your email address locked in the Apple system and unusable.

This is quite absurd. As a long-term Apple user, I am quite annoyed by the lack of options and willingness to help with this issue.

In that case, anyone could do that and consequently lock you out of using your email address for Apple ID purposes, and you would just have to accept it.

> Please note that your email address may be a simple method to use for iMessage without having to provide your phone number. Therefore, the inability to connect an e-mail address limits the possibility of using iMessage as you want.

I am surprised that Apple security features do not prevent this from happening, or that there is no grace period for email verification after which unverified emails (accounts) will be locked or removed, forcing the other person to take some action.

> Apple theoretically removes unused Apple IDs from their system after 2 years. However, how do you know that this Apple ID is unused? Just because the other person can log in to their account, even if the email address is not verified, doesn't mean that they cannot use it. This is nonsense!

The issue can become even more complicated if you create an Apple ID with a different email address. At some point, you might accidentally verify the Apple ID on an email address that was added by another person by mistake.

Assuming that this is not a fraud but a genuine mistake, the best-case scenario is that nothing will happen. However, we live in a dangerous world, and if someone can create an Apple ID with your email address and you cannot do anything about it, and Apple will not be able to help you, then there is something seriously wrong with the system.

I am usually a problem solver, but this experience has really disappointed me, Apple.

## An update - 10 days later

This whole situation annoys me. The approach from Apple Support was very disappointing and I couldn't believe that's it, that nothing could be done.

Days passed and my friend who was affected by this nonsense kept telling me that he still receives plenty of emails every single day from Apple asking him to verify his email address.

These emails originate from the other person's end, who is continuously, every single day, trying to verify his email address not noticing that is probably the wrong one (mistyped or misspelt).

If you are flooded with hundreds of emails from a company that puts privacy on top of the list, you will say enough and will try to sort out this issue.

Armed with an argument that Apple was spamming my friend's emails, we contacted Apple Support once again. This time the conversation was very different. It was still polite but with a piece of blame onto Apple so they would understand the irritation that this whole situation was causing.

From Apple Support chat we have been transferred to Phone Support where, going once again through things we tried to get this sorted once and for all.

> During the first contact with Apple we received a case number and we stuck with this case number till the end. Thanks to that we have a whole history.

As much as the person on the other end of the line tried to do whatever the other person days before tried as well, he hadn't seen an option for what else could be done, but there was one difference. He fully understands the situation of being spammed by Apple email asking to verify email addresses. He knew that if this happened to him, he would be annoyed same as my friend was.

Thanks to that he decided to go a step further in the hierarchy of Apple Support and reach his supervisor (or the person with more knowledge and power).

This was a brave move showing that there is a chance to get this thing sorted, **and it was.**

{{% ads-in-article %}}

After going through some details the other support person suggested that one method to get this sorted, which on initial call was never considered.

> Going through details we advised on which device the person created Apple ID, from which country it originated (as some Apple emails have been sent in a foreign language before changing to English), and the whole timescale when exactly happens. Good that my friend didn't remove all these emails.

Apple Support at the higher end got the power to verify the ownership of the email attached to the Apple ID.

By invoking this action, Apple will request from us a verification code that will be sent to our email.

The email with the subject "Email Ownership Verification Code" will state:

> "Dear Customer, Provide the following verification code to your AppleCare advisor."

Thanks to that Apple initiated the removal of the email address originally connected to the Apple ID created by another person.

They don't have the power to remove Apple ID altogether, and I would not persist in doing this, as the other person may be genuine. 

Once email is removed from Apple ID, the other person still is able to log into their Apple ID using their phone number. At the time when they do, they will likely be asked to put their new email address. Alternatively, they will be pushed towards contacting Apple Support to discuss this matter.

Deattachment of the email address does not happen straight away. As advised this may take a couple of days and it did.

From the end of the call, my friend hasn't been bothered by Apple emails anymore and 2 days later, when checked on [iforgot.apple.com](https://iforgot.apple.com), his email was no longer recognised as an Apple ID.

Here is a success to the whole story.

I am happy that this issue has been sorted. This restores my optimism in Apple Support which was initially put into doubt.


---
## The Rapid Security Response update for macOS broke compatibility with OpenCore Legacy Patcher
- **URL:** https://dariusz.wieckiewicz.org/en/macos-rapid-security-response-update-opencode-legacy-patcher/
- **Date:** 2023-07-16
- **Tags:** MacBook Air, MacBook, A1465, OpenCore Legacy Patcher, macOS Ventura, macOS, Apple, Rapid Security Response

### Content

Recently, I wrote about giving my friend's [MacBook Air from Mid-2013 (A1465) a new life by installing macOS Ventura (13.4.1)](/en/second-life-macbook-air-opencore-legacy-patcher/) on it.

Although this laptop was still working well, it was not compatible with the latest macOS from Apple. However, the OpenCore Legacy Patcher gave it a new lease on life by allowing it to run the latest macOS.

After installing any OS updates on unsupported hardware, you should be prompted to install post-install volume patches (also known as root patches) on your first boot.

By installing Rapid Security Response Update 13.4.1 (c), the system froze at the Apple logo and progress bar at approximately 35% of the loading process during the first reboot.

Thankfully, the solution was not too complicated.

<!--more-->

I turned off the laptop by pressing and holding the power button, then turned it back on while holding the <kbd>Shift</kbd> key.

I held down the Shift key until the system booted into Safe Mode and the user login screen appeared.

After logging into my user account, I was shown a crash report that indicated the kernel panicked due to graphics card drivers.

Once in Safe Mode I open the OpenCore Legacy Patcher app from the Applications folder and selected **Post-Install Root Path**. From **Post-Install Menu** selected **Start Root Patching** and confirmed relaunching the app as admin to continue.

Once in Safe Mode, I opened the OpenCore Legacy Patcher app from the Applications folder and selected the **Post-Install Root Path** menu item. From the **Post-Install Menu**, I selected the **Start Root Patching** option and confirmed that I wanted to relaunch the app as an administrator to continue.

{{% gallery %}}
[![OpenCore Legacy Patcher app - Main Window - Selecting Post-Install Root Patch](/images/2023/07/OpenCore_Legacy_Patcher_Post-Install_Root_Patch.png)](/images/2023/07/OpenCore_Legacy_Patcher_Post-Install_Root_Patch.png)
[![OpenCore Legacy Patcher app - Post-Install Menu - Selecting Start Root Patch](/images/2023/07/OpenCore_Legacy_Patcher_app_Post-Install_Menu_Start_Root_Patch.png)](/images/2023/07/OpenCore_Legacy_Patcher_app_Post-Install_Menu_Start_Root_Patch.png)
[![OpenCore Legacy Patcher app - Confirming Relaunch as root](/images/2023/07/OpenCore_Legacy_Patcher_app_Relaunch_as_root.png)](/images/2023/07/OpenCore_Legacy_Patcher_app_Relaunch_as_root.png)
{{% /gallery %}}

After a minute or two, the patching was complete. I shut down the computer and started it up normally. This time, the computer booted into macOS without any problems.

It seems that sometimes when our computer refuses to boot into the system after the first reboot following an OS update, this is the way to fix it.

{{% ads-in-article %}}

---

**Note to Myself.** 

1. **Boot into Safe Mode** by holding down the **Shift** key while turning on your Mac.
2. Open the **OpenCore Legacy Patcher app** from the **Applications** folder.
3. Click **Post-Install Root Patch**.
4. Click **Start Root Patch**.
5. Confirm that you want to **Relaunch as root?** and wait.
6. **Reboot** your Mac.


---
## Second life for MacBook Air from Mid-2013
- **URL:** https://dariusz.wieckiewicz.org/en/second-life-macbook-air-opencore-legacy-patcher/
- **Date:** 2023-07-02
- **Tags:** MacBook Air, MacBook, A1465, OpenCore Legacy Patcher, macOS Ventura, macOS, Apple

### Content

Probably some of us have friends who have MacBook computers. Some of them purchased them some time ago and, despite still working, have been made obsolete and stopped from further support from Apple. 

When the device is out of support life, it does not receive any further software updates. This is putting their users at risk of unpatched variabilities but also causing problems using outdated software like Internet Browser.

I got friends who purchased MacBook Air 11th-inch Mid-2013 (A1465) at a very similar time when I purchased my first MacBook Pro. Since then I updated and I am currently on my 3rd with an M1 processor.

I mentioned to them some time ago (years back) about the end of software updates for their computer, but because they do not use it very often, they do not think of spending a minimum of £1,000 to get a new one. I fully understand and agree with that.

Analysing the way how they use their technology, where phones took most of the time, the laptop is used rarely, but still used. For them, upgrading to the latest hardware is a waste of money.

Recently I listened to a podcast where the host mentioned that he is still able to receive the latest software for his old MacBook thanks to [OpenCore Legacy Patcher](https://dortania.github.io/OpenCore-Legacy-Patcher/).

I decided to have a look at that and noticed that there is a bunch of hardware that has been forgotten by Apple for some time, but thanks to this solution it can still receive recent OS updates.

> Remember that Apple forgets their hardware (stops supporting) after much more years from release on the market than any other computer manufacturer, **any!**

Looking at the [supportd models](https://dortania.github.io/OpenCore-Legacy-Patcher/MODELS.html) I found their MacBook Air with a comment that **‌Everything is supported**.

**Wow!**

[![OpenCore Legacy Patcher MacBook Air Supported Hardware](/images/2023/07/OpenCore_Legacy_Patcher_MacBook_Air.png)](/images/2023/07/OpenCore_Legacy_Patcher_MacBook_Air.png)

I decided to give it a go and convinced (just acknowledge, to be right) them to resurrect their laptop, so it can be used for longer.

Their laptop got an Intel i5 processor 1.6GHz, 4GB of RAM and 256GB SSD drive. Despite that SSD read speed is 250MB/s in write speed, it's not bad for casual use. Way faster than some mechanical hard drives that are still fitted into some latest cheap laptops on the market.

Apart from getting a bit hot and the fact that the battery not holding as it used to ([coconutBattery](https://www.coconut-flavour.com/coconutbattery/) still showing 75% of design capacity), it's not bad hardware.

The screen is in standard resolution and just 11 inches, but for what they need to use it and how often they use it, the ability to get recent software will put good use in the old hardware.

I started by downloading the OpenCore Legacy Patcher app and follow with the preparation of a USB drive to proceed with the installation after. 

In the meantime, I made a backup using Time Machine, which take w while. Downloading the recent OS, which was Ventura 13.4.1 also takes some time followed by installation into a USB drive and then into the main hard drive.

> Before installing I used Disk Utility to Erase the hard drive so I will end up like a freshly purchased device rather than updating with all the outdated software there.

Hours later the installation finished. I followed up with [steps to make sure the device does not require USB to boot](https://dortania.github.io/OpenCore-Legacy-Patcher/POST-INSTALL.html), or holding Option (Alt) button at the start.

> Throigh the whole installation, before you finish everything keep your installation drive connected.

The OpenCore Legacy Patcher installs a custom boot loader that displays OS selection at the start of the computer, which I easily disabled through the app and built the bootloader into an internal hard drive. At this stage, I didn't need a USB drive connected any more and the device booted as every other Mac.

If I would give you this Mac, you will not know that there was some "magic" done with it. Off course, you will be surprised that this "old" hardware got recent software on it.

After finished installation, the Patcher is following us by applying post-install volume patches then everything is ready for use. **Magic!**

The great thing about this solution is the fact that you will be receiving any software updates released by Apple, so you are not limited to just sticking to what you installed.

> "**Native OTA updates**. Install updates the moment they come out, with native System Preferences support, just like a supported Mac."

Off course, any future updates will remove some applied "magic" stuff by the app, but the app will get that and after you update it will check if any patches are required and follow up with it by prompting us to do so. Very user-friendly approach!

Also, this solution does not change anything in your hardware and it can be easily reverted if needed.

> "**Zero firmware patching**. Using the capabilities of the OpenCore boot manager, our protocol upgrades are done in memory and are never permanent."

{{% ads-in-article %}}

I worked on this aged hardware for a while and I can say that despite it not being as fast as M1 Mac, it's useable enough. Instead of throwing out it, let's maximise its lifespan. Personally, it would be too slow for me, as I am used to the responsiveness of my M1 Mac, but for light users like my friends, this is perfect.

I understand Apple wants to remove outdated hardware from the market. They doing this for a reason. Sadly, other manufacturers are much more cruel to that and a computer purchased just a year or two years ago is in most cases called obsolete by them. With Apple, we using it for longer, but in reality, we can do this even longer than planned.

[Marcel Bischoff](https://mastodon.social/@herrbischoff/110089188214540419) in a response from the 26th of March published on Mastodon said something very interesting.

> "Recently used #OpenCoreLegacyPatcher to update a full creative agency’s worth of iMacs to Ventura. If ~3 guys can successfully run a non-commercial hobby project keeping Macs running smoothly, Apple’s deprecation strategy is clearly about shareholder value, nothing else. Throwing away working hardware because software refuses to support it is not sustainable. That’s capitalism and its incentives for you."

This software opens an option for people who want to start their journey into the Apple ecosystem without investing a lot of money but by working with its latest software.

I you want to try, head to eBay or another marketplace and look for [supported hardware](https://dortania.github.io/OpenCore-Legacy-Patcher/MODELS.html) that is still fully working and states in comments that **‌Everything is supported**.

**Great bargaining solution.**

For just £139.99 if not less you can get a MacBook Air 13.3" Mid-2013 with 8GB of RAM and 256GB of SDD and move it to its next life with Open Core Legacy Patcher and macOS Ventura.


---
## Adding Cloudflare Tunnel to OpenWrt Router (VPN Alternative)
- **URL:** https://dariusz.wieckiewicz.org/en/adding-cloudflare-tunnel-to-openwrt-router/
- **Date:** 2023-07-02
- **Tags:** OpenWrt, WireGuard, VPN, Cloudflare, Cloudflare Tunnel, Zero Trust, Zero Trust Network Access, CG-NAT, cloudflared, Cloudflare WARP, WARP

### Content

If you follow my website and posts related to [OpenWrt](/en/tag/openwrt) you have probably come across my post about [installing a VPN server on an OpenWrt router using WireGuard](/en/installing-vpn-server-on-router-openwrt-wireguard/).

**WireGuard** is one of the fastest protocols available for creating a VPN connection. Thanks to it, from the Internet, we can easily connect to our network and use it, either for local purposes (access to a printer or network drive) or to limit regional restrictions. Being outside the country, I can connect to my router at any time and my device will appear on the Internet as if it were where the router is, i.e. in the UK.

This super fast solution, however, requires configuration, which can sometimes be complex and cause various errors (although it is usually much easier than other VPNs).

WireGuard also has a limitation. To connect to our router, we need an external (static or dynamic, it doesn't matter) IP address.

<!--more-->

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

> In case of a variable (dynamic) IP address, we can set the domain according to the entry [Domain setting for variable IP address (OpenWrt and DDNS)](/en/setting-domain-for-dynamic-ip-address-openwrt-ddns/)

If our internet connection does not have an external IP address, as in the case described in my post [Adding a second internet connection to an OpenWrt router](/en/adding-second-internet-connection-router-openwrt/), then we have a problem.

Most mobile connections (4G/5G) do not have an external IP address, and each user is also placed behind a so-called [CG-NAT](https://en.wikipedia.org/wiki/Carrier-grade_NAT).

> Personally, I would describe CG-NAT as a network of users inside another network belonging to a shared external IP address. Our router (our network) is placed on another network, which contains a router that has an external IP address that we have no control over.

At work I have a router with OpenWrt configured in such a way that when the main connection goes down, the mobile connection is activated. Users on the local network can still work, but those connecting via WireGuard have a problem.

I decided to try using a method to create a tunnel that, regardless of whether we have an external IP address, whether we are behind CG-NAT, or whether we do not want to bother with configuring WireGuard or port forwarding on the router, will allow us to access local network resources from the Internet.

Here I came across [Hector Molina's solution using Cloudflare Tunnel](https://hmolina.dev/p/cloudflared-tunnel-in-openwrt/) and [Zero Trust Network Access](https://www.cloudflare.com/products/zero-trust/zero-trust-network-access/).

The author of the original post highlighted the lack of the *cloudflared* package in the OpenWrt repositories, which would allow for easy installation and configuration of the tunnel.

Here the situation has changed recently, as the package is available from the repository, as far as OpenWrt 22.03 is concerned. However, as I have found out, this package is not updated regularly and does not work at all. It is not without reason that this package is missing from the repositories of the latest OpenWrt 23.05 version.

Therefore, I will describe here how to create a Cloudflare tunnel using the package for our router provided directly by the Cloudflare team. Additionally, we do not have to worry about its updates, because it will update automatically as soon as a new version is published.

---

In addition to the entire tunnel, CouldFlare has its own app 1.1.1.1 (Cloudflare WARP) that allows you to configure it to connect to your tunnel. This saves you from having to mess around with configuring profiles for each user.

> For macOS, the Cloudflare WARP app and Cloudflare ONE are available. Cloudflare One allows you to configure your tunnel independently of the WARP app, so you can use both WARP and the configured tunnel without having to log in every time.

While WireGuard is my default approach when it comes to connecting remotely to my home network, it's good to have an alternative available that, under changing conditions, can solve problems like CG-NAT.

Additionally, the tunnel does not require us to open any ports on our router to connect, as is the case with Wireguard. It also allows us to bypass any network restrictions.

It can be described by comparing the tunnel to the way you connect using the TeamViewer application. It doesn't matter if you have an external IP address, are behind CG-NAT or not, as long as the internet connection works, it is possible to create a tunnel to access your network.

## Install the official cloudflared package

In OpenWrt software version 22.03 it is possible to install the `cloudflared` package from repository, however I do not recommend it because this package is defective, or more precisely the file initializing our tunnel does not work.

After updating to the latest version of OpenWrt 23.05 we will not see the `cloudflared` package in the repository, which will make things easier as we will get rid of the problems associated with it.

Previously this post was based on a package from the repository, but I modified it to use the same solution regardless of whether we are using OpenWrt 22.03 or 23.05.

In OpenWrt 24.10, as well in 25.12, the `cloudflared` package is back in the repository. However, I prefer to focus on having our system work with a package that is provided and updated by Cloudflare, which is actually done in the background, without our intervention and the need for manual updates.

---

> Before we start, a small note. The *cloudflared* package requires almost 32 MB of free space on our device. Make sure that your router, or more precisely the `/overlay` partition, has at least twice the space needed for this package.

[Cloudflare provides a package for several platforms](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/#linux). For OpenWrt routers, we need the ARM platform package for Linux.

To do this, execute the following command:

```bash
wget --no-check-certificate -O /usr/bin/cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm
```

If your system is arm64, the command shall be:

```bash
wget --no-check-certificate -O /usr/bin/cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64
```

We grant rights to execute (run):

```bash
chmod +x /usr/bin/cloudflared
```

> A little note here. If you use my method to [update OpenWrt firmware without losing installed packages](/en/firmware-update-openwrt/), be sure to run the above two commands after restoring the packages, but before restoring the backup. Otherwise, the system will have the incorrect `cloudflared` package.

And we run it, checking if our file works:

```bash
cloudflared version
```

We should see something like this:

```
cloudflared version 2023.10.0 (built 2023-10-31-1235 UTC)
```

At this stage, we go to the [Cloudflare Zero Trust](https://one.dash.cloudflare.com/) page where we select a user, and then set the name of our "team" assigned in the `cloudflareaccess.com` domain

[![Cloudflare Zero Trust Team](cloudflare_zero_trust_team.png)](cloudflare_zero_trust_team.png)

> Remember the team name, as you will need it to configure users on their devices. If you forget, you can find (and change) it in **Settings** > **Custom pages**.

Next, we need to choose a price plan. Of course, we start with the Free plan.

> Under the free plan, we can have up to 50 users of the service, which is very generous.

This is how we started the fun.

At this stage we need to create our tunnel. We do this fun on our router side.

```bash
cloudflared tunnel login
```

By executing this command, we will receive a link that we need to paste into our web browser to log in to Cloudflare.

In the next step we will select the domain for which we authorize our tunnel.

If everything went correctly, we will receive information that Cloudflare has created a certificate enabling the creation of the tunnel.

[![Cloudflared tunnel login success](cloudflared_success.png)](cloudflared_success.png)

Our terminal will display:

```bash
root@OpenWrt:~# cloudflared tunnel login
Please open the following URL and log in with your Cloudflare account:

https://dash.cloudflare.com/argotunnel?...

Leave cloudflared running to download the cert automatically.
You have successfully logged in.
If you wish to copy your credentials to a server, they have been saved to:
/root/.cloudflared/cert.pem
```

The `cert.pem` file must be copied (moved) to the `/etc/cloudflared/` folder

```bash
mkdir /etc/cloudflared
mv /root/.cloudflared/cert.pem /etc/cloudflared/
```

Next we will create our tunnel:

```bash
cloudflared tunnel create Tunnel-Name
```

Our terminal will display information about where the credentials and our tunnel ID are saved.

```bash
Tunnel credentials written to /etc/cloudflared/b26bb351-46ca-4fc1-a157-0ecdc1560658.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.

Created tunnel Tunnel-Name with id b26bb351-46ca-4fc1-a157-0ecdc1560658
```

> My ID in this example is `b26bb351-46ca-4fc1-a157-0ecdc1560658`, yours will be different.

We need to fill this information in our configuration file `vim /etc/cloudflared/config.yml`

```bash
tunnel: b26bb351-46ca-4fc1-a157-0ecdc1560658
credentials-file: /etc/cloudflared/b26bb351-46ca-4fc1-a157-0ecdc1560658.json
warp-routing: 
 enabled: true
```

If you have already created your tunnel, find its name and ID by running the `cloudflared tunnel list` command. Then, create the credential file using the following command:

```bash
cloudflared tunnel token --cred-file /etc/cloudflared/b26bb351-46ca-4fc1-a157-0ecdc1560658.json Tunnel-Name
```

Next, use the details to populate `/etc/cloudflared/config.yml` as described above.

> **Remember!** My ID in this example is `b26bb351-46ca-4fc1-a157-0ecdc1560658`, yours will be different.

All that's left is to launch our tunnel and check if everything works.

### Several corrective treatments (required)

Before we do that, however, there is an additional step that we must perform on the side of our router in order to correct several errors that are displayed when starting the tunnel.

1. We create the file `touch /etc/sysctl.d/99-fix-buffer-and-ping.conf`
2. We add the following lines to the file via `vim /etc/sysctl.d/99-fix-buffer-and-ping.conf`

```bash
net.core.rmem_max=2500000
net.ipv4.ping_group_range=0 2147483647
```

3. We run the following command `sysctl -p /etc/sysctl.d/99-fix-buffer-and-ping.conf`.

This prevents a problem at startup:

```bash
WRN The user running cloudflared process has a GID (group ID) that is not within ping_group_range. You might need to add that user to a group within that range, or instead update the range to encompass a group the user is already in by modifying /proc/sys/net/ipv4/ping_group_range. Otherwise cloudflared will not be able to ping this network error="Group ID 0 is not between ping group 1 to 0"
WRN ICMP proxy feature is disabled error="cannot create ICMPv4 proxy: Group ID 0 is not between ping group 1 to 0 nor ICMPv6 proxy: socket: permission denied"
```

Now we can launch our tunnel.

```bash
cloudflared tunnel run Tunnel-Name
```

After going to the [Cloudflare Zero Trust](https://one.dash.cloudflare.com/) > **Network** > **Tunnels** (was **Access** > **Tunnels**) panel we will see if our tunnel is working.

[![Cloudflare Zeru Trust Your Tunnels](cloudflare_zero_trust_your_tunnels.png)](cloudflare_zero_trust_your_tunnels.png)

This way we know that the tunnel is working. We can end the above command (<kbd>Ctrl</kbd>+<kbd>C</kbd> for Windows, or <kbd>Cmd</kbd>+<kbd>C</kbd> for macOS).

### Tunnel Migration

We run our tunnel again manually and go to our tunnel on the [Cloudflare Zero Trust](https://one.dash.cloudflare.com/) website and select the **configure** option (or simply click on the tunnel name) in the **Network** > **Tunnels** section (it was **Access** > **Tunnels** ).

Here we will get the option to migrate the tunnel which they had to perform.

[![Cloudflare Zero Trust Migrate Tunnel](cloudflare_zero_trust_migrate_tunnel.png)](cloudflare_zero_trust_migrate_tunnel.png)

We click the **Start migration** button, confirm each question (without entering any data) with the **Confirm** button, ending with **Migrate tunnel**.

### Adding our local network addresses

We click our tunnel again and the **Configure** button.

In the **Private Network** tab we add our local addresses that we use in our network.

Since I use the 10.0.0.(1-254) pool for Wireguard and the 192.168.0.(1-254) network, I added them as follows.

```
10.0.0.0/24
192.168.1.0/24
```

### Local network access - Split Tunnel

Additionally, we need to split the tunnel (**Split Tunnel**) to be able to access the local network.

To do this, go to **Settings** > **WARP Client** and in the **Device settings** section click on our default profile (Default).

Go to the **Split Tunnels** section, which by default is set to **Exclude IPs and domains** and click the **Manage** button.

There, on the exclusion list, we find the network addresses that correspond to our local network, in this case 10.0.0.0/8, 192.168.0.0/16, 192.0.0.0/24, and delete them.

At this point we can finish with our tunnel.

### Added support for UTP and ICMP (ping) packets

In addition, go to **Settings** > **Network**, in the **Firewall** section we enable **Proxy** and select, in addition to the default TCP packets, also UTP and ICMP.

Thanks to this, we will expand the functionality of our tunnel and additionally gain the ability to execute the **ping** command to our devices in the local network, which is very useful for analyzing whether our tunnel is working or not.

We are also enabling the **WARP to WARP** service.

[![Cloudflare Zero Trust Firewall Proxy TCP UDP ICMP](cloudflare_zero_trust_firewall_proxy_tcp_udp_icmp.png)](cloudflare_zero_trust_firewall_proxy_tcp_udp_icmp.png)

### Tunnel Launch

When installing the `cloudflared` package from the OpenWrt 22.03 repository, a startup file is provided along with it and installed in `/etc/init.d/cloudflared`. However, this file is buggy and does not work, so we do not use it.

In the case of the official package, we do not have this type of file by default, which will partially simplify the entire procedure.

To create it, we execute the following command:

```bash
cloudflared service install
```

> Thanks to this we will get a file saved in `/etc/init.d/cloudflared`, which unfortunately does not work entirely, but there is a solution described below.

The startup file is not adapted to work with OpenWrt. The packages available on the router, such as `ps` are not the same (do not have the same options) as in other Linux systems.

Our tunnel will start with the `/etc/init.d/cloudflared start` command without a problem, but stopping with the `stop` command does not work and even though the `status` shows that the tunnel is not running, we still see it when we execute the `ps | grep cloudflared` command.

The startup file generated by cloudflared is intended for Redhat Linux (as you can see by executing the command `head -2 /etc/init.d/cloudflared`).

#### Fixing new startup file /etc/init.d/cloudflared

In the file for RedHat, almost at the very beginning, we have the following command:

```bash
is_running() {
    [ -f "$pid_file" ] && ps $(get_pid) > /dev/null 2>&1
}
```

The `ps` command in OpenWrt doesn't have many options, so you can't just display a process by its PID (`ps 14535` won't work).

For this purpose, the following part:

```bash
ps $(get_pid)
```

we change to:

```bash
ps | grep $(get_pid) | grep -v grep
```

> The `grep -v grep` command is intended to exclude the grep package from the response we get.

This way, all commands of the *cloudflared* package work and we are ready for further configuration.

```bash
Usage: /etc/init.d/cloudflared {start|stop|restart|status}
```

## Logging into the tunnel using the 1.1.1.1 app (Cloudflare WARP)

While our tunnel is running, we need to start configuring our users.

Before this can happen, we need to define who can log into our tunnel.

### Login Method

In the [Cloudflare Zero Trust](https://one.dash.cloudflare.com/) panel go to **Settings** and then **Authentication** where we can add login methods in **Login methods**.

I will focus here on what is enabled by default, namely **One-time PIN** and that is what we will use first.

> As you will notice, there are options available there thanks to which we can specify, for example, that the user will have to log in using a Google account to confirm their identity and, together with the login rule established (at a later stage), connect to the tunnel.

The person logging in to our tunnel will have to provide the "team" name, which we specified at the beginning in the `cloudflareaccess.com` domain.

> Let me remind you that we can see it in **Settings** > **Custom pages**.

Before we do that, we need to define who can log in by setting a login rule.

### Login Rule

To do this, in **Settings** go to **WARP Client** > **Device enrollment permissions**. By clicking the **Manage** button, we will create a new rule in the **Policies** section using the **Add a rule** button.

1. I set the Rule name to **Allowed emails**.
2. I left the Rule action to **Allow**
3. In the **Include** section I selected **Emails** and in the Value field I entered my email address.

> Here we can also specify that all users in the domain can log in to the tunnel (**Emails ending in**). If we have our own domain and email addresses configured in it, this will reduce the need to add each email address/user separately.

When logging in to the 1.1.1.1/Cloudflare WARP app, I will be asked to provide my email address, where I will receive a one-time password to enter in the app, which will allow me to be authenticated and logged in.

{{% ads-in-article %}}

## App

Let's start with the application on our mobile device.

> For iOS, it is available in [App Store](https://itunes.apple.com/app/1-1-1-1-faster-internet/id1423538627). All others (links to them) are displayed when we go to the page [1.1.1.1](https://1.1.1.1) in our web browser.

After the initial start-up and configuration of the VPN profile to the standard WARP service, go to settings (three horizontal lines) > **Account** > **Login to Cloudflare Zero Trust**

At this stage we will be asked for the name of our "team" and will be redirected to the login page. We enter the approved email address there, then open our email and read the received code, which we enter in the application.

After logging in, my Cloudflare WARP (1.1.1.1) app will look a bit different and the options will be limited to a single button to turn the **Zero Trust** tunnel on/off.

[![Cloudflare WARP App Zero Trust](cloudflare_warp_app_zero_trust.png)](cloudflare_warp_app_zero_trust.png)

We can do this in the application on our computer in a similar way (**Preferences** > **Account** > **Login to Cloudflare Zero Trust**).

## Maintain tunnel if IP address changes (optional)

The only problem I have left is making sure that the tunnel will continue to work if the IP address of the internet interface changes or the internet is redirected through a different interface.

In my case, when the main internet connection with a static IP address stops working and the emergency one (behind CG-NAT) is activated.

As I have checked, an active tunnel does not detect the fact that the IP address or access interface has changed. Even though the tunnel is enabled, it will be inactive.

### With mwan3 package

> Post reference [Adding a second internet connection to an OpenWrt router](/en/adding-second-internet-connection-router-openwrt/)

In my case, when the Internet switches to a failover connection, the `mwan3` package will make sure that there is still an Internet connection in the local network.

The `mwan3` package has the ability to execute a command when one of the connections goes down. I could theoretically use this to stop the Cloudflare tunnel and start it on a new connection.

In the **LuCI** panel go to **Network** > **MultiWAN Manager** and the **Notify** tab.

Here we can execute the following script.

```bash
if [ "${ACTION}" = "ifdown" ] || [ "${ACTION}" = "ifup" ] && [ "${INTERFACE}" = "wan" ] ; then
   (/bin/sleep 30; /etc/init.d/cloudflared restart >/dev/null) &
fi
```

In case our WAN interface goes down (or restarts), the script will wait 30 seconds and then restart our Cloudflare tunnel.

Another example:

```bash
if [ "${ACTION}" = "ifdown" ] || [ "${ACTION}" = "ifup" ] ; then
 if [ "${INTERFACE}" != "loopback" ] && [ "${INTERFACE}" != "self" ] ; then
 (/bin/sleep 30; /etc/init.d/cloudflared restart >/dev/null) &
 fi
fi
```

When any interface goes down or recovers (ignoring the `loopback` interface), wait 30 seconds and restart the Cloudflare tunnel.

---

However, I would like to explore other options as soon as our connecting IP address changes.

### By analyzing the IP address

As I described in my post [Setting domain for dynamic IP address (OpenWrt and DDNS)](/en/setting-domain-for-dynamic-ip-address-openwrt-ddns/) and section [Supporting multiple internet connections with DDNS (when the above solution does not work)](/en/setting-domain-for-dynamic-ip-address-openwrt-ddns/#support-multiple-internet-connections-with-ddns), using `curl` we can read the external IP address from a given interface.

If our backup interface has an IP on the router 192.168.8.2, we execute the following command to read the IP.

```bash
curl -s --interface 192.168.8.2 'http://icanhazip.com'
```

This will allow us to read the current IP address.

Personally, at home, with one interface, I will save my IP address to a file, execute the compare command, when the IP address changes, I will restart the tunnel.

The command to read the IP address and save it to a temporary file is as follows.

```bash
curl -s 'http://icanhazip.com' > /tmp/ip_read
```

I will add reading the IP address to the `cron` schedule so that it executes once a day, one minute after midnight.

```bash
01 0 * * * curl -s 'http://icanhazip.com' > /tmp/ip_read
```

I will also add my script to the schedule that will read the IP address and compare it to the one read earlier. When the IP address changes, the tunnel will be restarted. The script will run every 5 minutes.

```bash
*/5 * * * * /bin/sh /root/ip_check_script
```

Contents of the file `ip_check_script`

```bash
FILE1="/tmp/ip_read"
curl -s 'http://icanhazip.com' > /tmp/ip_check
FILE2="/tmp/ip_check"

if cmp -s -- "$FILE1" "$FILE2"; then
  # IP not changed, don't do anything
  :
else
 # ip address differ, run the following
 /etc/init.d/cloudflared restart > /dev/null
 # update ip_read
 cp /tmp/ip_check /tmp/ip_read
fi
```

We add rights to execute (run)

```bash
chmod +x ip_check_script
```

We will also add to the `cron` schedule an IP address check after the router reboots.

```bash
@reboot sleep 15 && curl -s 'http://icanhazip.com' > /tmp/ip_read
```

To prevent the tunnel reset command from being executed every 5 minutes (even though the IP address has not changed), when the IP address read currently changes, the `ip_read` file will be updated.

## Automatic tunnel start on router startup

By default, the `cloudflared` package from OpenWrt 22.03 repository, `/etc/init.d/cloudflared`, which was broken and which we replaced and fixed, had the option to start the service during router startup (`enabled`).

The new, official, file has only four options (`start`, `stop`, `restart` and `status`).

To make our tunnel start after startup, we will use the `cron` scheduler.

We add the following line.

```bash
@reboot sleep 15 && /etc/init.d/cloudflared start
```

I added a 15 second wait to the line above. In some cases, you may need to wait a bit longer, especially if the router takes a while to connect to the internet.

## Failsafe - Periodic check if the tunnel is working

If we did everything correctly, our tunnel should work without any problems, however there are situations when our tunnel (process) stops working.

Therefore, it is worth introducing some kind of check. When it is detected that the tunnel is down, execute the command to resurrect it.

For this purpose we can use 2 types of commands. Choose one that you think is right. Personally, I prefer the first solution.

We will add the selected command to the `cron` schedule that executes every 5 minutes. When our command detects that our tunnel is down, it will try to start it again.

```bash
*/5 * * * * /bin/sh /root/cloudflared_check
```

### Checking with /etc/init.d/cloudflared status

```bash
if [[ $(/bin/sh /etc/init.d/cloudflared status) == "Running" ]];
then
 :
else
 /bin/sh /etc/init.d/cloudflared restart
fi
```

We save the above command to the file `/root/cloudflared_check` and give it execution rights `chmod +x /root/cloudflared_check`.

### Checking with pgrep package

```bash
if pgrep cloudflared >/dev/null
then
    :
else
    /bin/sh /etc/init.d/cloudflared restart
fi
```

We save the above command to the file `/root/cloudflared_check` and give it execution rights `chmod +x /root/cloudflared_check`.

## User Management

While everything is up and running and users can use the new service to see what devices and users are available, we can do so from the **My Team** and **Devices** and **Users** sections respectively.

There we can also revoke login rights for a given user using the **Revoke** option.

## Including configuration files in OpenWrt backup

If you are backing up OpenWrt from **System** > **Backup / Flash Firmware**, in the **Configuration** tab add the following folders to be included in the backup file.

```bash
/etc/cloudflared/
```

Personally, since I also have other packages, including WireGuard, my folders look like this:

```bash
/etc/ssl/
/etc/wireguard/
/etc/cloudflared/
/etc/config/
/etc/init.d/
/root/
```

## Bonus

I don't know if you know that as a bonus to all this fun, being connected to your own tunnel gives you access to the network using IPv6 (from the users' side, not the router's).

---

Sources:

* [Cloudflared Tunnel in OpenWrt - Hector Molina](https://hmolina.dev/p/cloudflared-tunnel-in-openwrt/)
* [Securely access home network with Cloudflare Tunnel and WARP - Savjee, Simply Explained](https://savjee.be/blog/securely-access-home-network-with-Cloudflare-Tunnel-and-WARP/)
* [Cloudflare tunnel - OpenWrt.org](https://openwrt.org/docs/guide-user/services/vpn/cloudfare_tunnel)
* [Cloudflare Tunnel, /etc/init.d/cloudflared not doing anything - Forum OpenWrt](https://forum.openwrt.org/t/cloudflare-tunnel-etc-init-d-cloudflared-not-doing-anything/164478/2)


---
## Google is killing another service, this time Google Domains
- **URL:** https://dariusz.wieckiewicz.org/en/google-killing-another-service-google-domains/
- **Date:** 2023-06-18
- **Tags:** Google, Google Domains, Domains, Squarespace, Cloudflare

### Content

It's not the first time we've been in this situation where when we start using a service, it's turned into a cash cow or killed like a fly.

Google is famous for killing its services. This time, they're not exactly killing another one, but selling it to another company is no different.

<!--more-->

Well, Google Domains isn't something that's very popular. Although the service, registering domains with Google, has supposedly existed since 2005, Google Domains officially launched 9 years ago. It wasn't long after that that I discovered the service and started using it initially for my `.org` domain.

After settling in, because the price offer is unbeatable, I liked the new interface implemented some time ago. Additionally, the options available for free tempted me to transfer several domains to this place.

In addition to domain parking, DNS entry management, I also got tempted by Email Forwarding. It's a shame that post I created a year ago about it became outdated so quickly.

The changes we are seeing in Google are not going in the right direction, especially for users of their services.

I would also understand that a service like Google Domains would not generate income, but that is not the case. Despite this, as reported by [The Register](https://www.theregister.com/) in its article [Google Domains to Shut Down and Move to Squarespace](https://www.theregister.com/2023/06/18/google_domains_shutting_down/), Google intends to inject itself with $180 million in cash. It is just a shame that we will have to pay for it.

Although the service of registering and servicing domains with Google did not become popular directly in Poland due to the lack of support for domains ending in `.pl`, it was nevertheless a good alternative with affordable prices, especially for people staying abroad.

As we will read, the business in question will concern almost ten million users, including me.

Of course, the service is not being killed, but sold, but I don't think that's in the best interest of their users. Let's be honest, Squarespace's services aren't the cheapest, so why shouldn't they make some money on it?

While Google and Squarespace have agreed that for a period of 12 months from the start of the transition, Squarespace will tolerate Google's offered prices for all domain renewals, that doesn't mean that it won't become very expensive later on.

I wouldn't be surprised if Squarespace introduced what [Namesco](https://names.co.uk) is introducing in the UK, which charges an administration fee for releasing a domain (transferring it to another company), which is sometimes higher than renewing it with them, which also discourages action.

Personally, I have 3 domains registered with Google and I don't think about moving to Squarespace, because I'm not sure what I will be offered and what I will have to pay extra for.

I personally have an account in [Cloudflare](https://cloudflare.com), where I have managed most of my (and collaborators') domains for years, so I know what to expect there. Additionally, Cloudflare also offers the possibility of using a domain for the purpose of email forwarding, called Email Routing. I wrote about it earlier in the entry [Email in your own domain with Cloudflare (and Gmail)](/en/cloudflare-email-in-your-own-domain/).

Cloudflare also offers the option of registering and transferring domains, so why not take advantage of it.

Of course, I could wait for the official position of Google, because it would be good to inform users about it, but honestly I'm tired of this and I'll decide to transfer before the new owner starts throwing obstacles in my way.

I had other plans when it comes to Domains registered with Google, but I need to verify myself a bit.

If you are in a similar situation to me, I encourage you to look into Cloudflare and see how much it will cost to maintain a domain with them. Initially, as I looked, interestingly, in some cases it is cheaper than with Google.

Remember, however, that in order to start transferring a domain from Google Domains, you must "unlock" the given domain. Going to our domain and "Registration settings", in the "Domain registration" section, we need to switch the button next to the option "Domain is locked"

[![Domeny Google - Registration settings - Domain is locked](domeny_google_registration_settings.png)](domeny_google_registration_settings.png)

Then, using the option below called "Transfer out", we need to generate an authorization code, which we give to our new service provider.

[![Domeny Google - Transfer Out](domeny_google_transfer_out.png)](domeny_google_transfer_out.png)

It was supposed to be so beautiful, and once again they have to waste my time and nerves on playing with something I hadn't planned.

{{% ads-in-article %}}


---
## A better way to send photos via WhatsApp
- **URL:** https://dariusz.wieckiewicz.org/en/a-better-way-to-send-photos-via-whatsapp/
- **Date:** 2023-06-18
- **Tags:** WhatsApp, Google Photos, images, Storage Saver

### Content

I've lost count of how many times I've told my friends and their friends not to send pictures over WhatsApp. If you must do it, please at least change this one thing first to make everyone's life easier.

<!--more-->

In most cases, pictures sent over WhatsApp are only useful as a preview on screen. They are often too low-quality to be printed or used on websites.

WhatsApp offers two options for sending pictures: Data Saver, which compresses the image to 0.9MP (720x1280, approximately 80kB), and Best Quality, which sends the image at its original resolution of 1.4MP (899x1599, approximately 113kB).

By default, WhatsApp is set to Auto (recommended), which means that it will automatically choose the best quality setting for the image based on your internet speed and the recipient's device.

If you can't reuse pictures sent in either resolution due to poor quality, receiving them in 0.9MP is the worst-case scenario. Therefore, you should always choose "Best" quality as your default.

Please open WhatsApp, go to `Settings > Storage and Data > Media Upload Quality`, and change the setting to Best Quality today.

Even though you still won't be able to reuse picture that you received, it will look better. If the image contains any details, it will be much clearer.

You can compare these settings to watching a movie on a 4K screen. Just like how a 4K movie will look much clearer on a 4K screen than on a 1080p screen (Full HD), a 1.4MP image will look much clearer than a 0.9MP image.

Furthermore, compare this to buying a high-end 4K TV just to watch content that is not even available in Full HD. It would be like buying a Ferrari to drive around your neighbourhood.

Overall, WhatsApp is not the best app for sending or receiving pictures. If you don't need to, I recommend using Google Photos instead. Google Photos offers a wider range of features, such as the ability to add pictures to albums and share albums with your contacts.

{{% ads-in-article %}}

Google Photos offers two backup quality options: original resolution and Storage saver. I recommend Storage Saver to everyone, as it provides good-quality images without taking up too much storage space.

Storage saver optimizes your photos by compressing them while maintaining their resolution up to 16MP (which is about 5312 x 2988 pixels). This is a significant difference. If you have an iPhone with a 12MP sensor, your photos will still be available for post-processing, such as cropping, even after they have been compressed. This will give you some wiggle room, especially if you want your final image to be 2048 pixels in size.

I recently listened to a podcast where the guest claimed that a resolution of 1200 pixels is sufficient. If that were the case, the pictures sent by WhatsApp would be fine. However, I disagree with that assessment. Given the prevalence of retina displays and Full HD screens, I recommend 2048 pixels as a starting point.

Conclusion: If you want to send high-quality photos, WhatsApp is not the best option. The best way to send photos on WhatsApp is to not send them at all. If you do need to send photos, I recommend using Google Photos instead.


---
## Supercharge your headings in Hugo with Render Hooks
- **URL:** https://dariusz.wieckiewicz.org/en/supercharge-your-headings-in-hugo-with-render-hooks/
- **Date:** 2023-05-21
- **Tags:** Hugo, Headings, Render Hooks, Render heading, Markdown, Copy to clipboard, Clipboard, Onclick, Onclick action, Accessibility, A11y, Aria label, Media print, Anchor, Title, Data title, Visualisation, HTML, CSS, JavaScript, WebDev

### Content

The great thing about Hugo, a static site generator, is that it got a lot of options for customisation and more are constantly added.

There are templates embedded into it, but they can be easily overridden by custom templates, like headings, through render hooks.

<!--more-->

When you write text with markdown, a single hash `#` resolve as the title of the document. This symbol is not really in use in the content that you writing in Hugo and is replaced with `title` used in frontmatter when the website template is set right.

```markdown
---
title:
---
```

However, other symbols, like `##` resolve as headings, adding sections to the text you are writing. In this instance, this double hash resolves as `<h2>`.

In the default approach, Hugo will generate it from markdown into HTML in the following way:

```html
<h2 id="this-is-your-second-heading">This is your second heading</h2>
```

With just a simple tweak, but adding `render-heading.html` placed in `\layout\_markup\` you can take control of how these parts will be generated. For example, you can add a direct link to the heading like mentioned [here](https://gohugo.io/templates/render-hooks/).

```html
<h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }} <a href="#{{ .Anchor | safeURL }}">¶</a></h{{ .Level }}>
```

You can hover over the `¶` symbol, or whatever you decide to use (I used initially `#`) and by right-clicking on it you can copy a link to that section.

This super simple approach is great, but I would like to get something more.

I have been inspired by [Google Search Central Documentation](https://developers.google.com/search/docs/essentials) and their approach to linking to headings of the document.

By default, an icon (button) showing that the heading got a link is only reviled when you hover your mouse on it (on desktop). At that point, you will see a link icon on the side, which will give you the ability to copy a link to the clipboard when you click on it.

You cannot hover over it and do a right-click to get a link, as it works as a button rather than a standard link (`<a href`), but there are other things that are appealing in a matter of usability.

Firstly, it is considered at the beginning to give the user feedback on wheat this icon is. When you hover your mouse over it you will have a tooltip saying `Copy link to this section: ...`. This incorporate accessibility (a11y) approach in the background with the utilisation of `aria-label`.

When you click on this "not-typical" button, the link will be copied into your clipboard and additionally, you will be informed about that by a pop-up box in the left bottom corner (on desktop) or on the bottom of your screen (on mobiles).

This is something that I am interested to achieve.

I put this into a todo list:

- [ ] Full link icon visible when hovered over, or when clicking on the heading (on mobile devices). In other instances is still visible but with less transparency;
- [ ] Copy the link to the clipboard when clicked on it;
- [ ] Tooltip when hovering over (on desktop);
- [ ] Receive a visual prompt about copy to clipboard action.


I always want a simple approach. I know that to achieve the above I will need to look into involving some JavaScript magic, **but do I?**

Considering my approach to simplicity, I want to do this with performance in mind. Less reliance on JavaScript is better as some dudes are surfing without JavaScript enabled.

But first I want to improve my heading and then look into ways how it's implemented on the example from Google Search Central.

## The base heading with anchor

The base `render-heading.html` currently looks as follows.

```html
<h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }} <a class="anchor" href="#{{ .Anchor | safeURL }}">#</a></h{{ .Level }}>
```

I changed `¶` to the `#` symbol.

### The anchor problem

The problem with this approach is when somebody will highlight text on your website and copy it into the clipboard, it will copy this `¶` to this `#` symbol as well.

Also, when printing a page, this will be visible.

The printing aspect can be sorted by hiding it by implementing simple CSS.

```css
@media print {
	a.anchor { display: none; }
}
```

### The anchor solution

To solve this problem I decided to change my `#` symbol to an icon in SVG.

In theory, it was simple, however, as you notice, each heading got a different size controlled by a specified font size. I would like to have SVG icons responsible based on that.

I can specify in CSS the size of the SVG icon for each heading, but that's adding unnecessarily 5 lines (for h2 to h6). If you remove CSS the icon will display **huge**!

Then I found the post [Control Icons with Font Size](https://css-tricks.com/control-icons-with-font-size/) quickly explaining how to have icons aligned with text by just implementing `width="1em" height="1em"` into our SVG and controlling the rest through font size in our CSS.

> This approach let me rethink the use of SVG images on my, and others, website. I decided to revisit all of them with disabled styles (in Safari > Develop > Disable Styles) to see where my SVGs are **huge** and how to change it. This reminds me of a [CSS Naked Day](https://css-naked-day.github.io) that typically runs on the 9th of April.

Before I will go any further, I need my icon. For this purpose, I used a link icon from [Material Symbols in Google Fonts](https://fonts.google.com/icons?selected=Material%20Symbols%20Outlined%3Alink%3AFILL%400%3Bwght%40400%3BGRAD%400%3Bopsz%4048), where I just downloaded SVG file.

## Simple approach

Let `class="anchor"` be partly visible by default and be shown fully when the mouse will hover over the heading. 

The problem is, that this will only work on devices where you can hover (typically when used with a pointer). On any touch devices like mobiles (with touch screens), this will not work.

I have looked at how to implement this to work independently if you hover or you touch. For this purpose, I found out very useful video [Dealing with hover on mobile by Kevin Powell](https://www.youtube.com/watch?v=uuluAyw9AI0)

So I used media classes in CSS to work differently on **hover-able** devices and **touch-able**.

### Visualisation

At first, the `class="anchor"` will be visible with some transparency and will become fully visible when hovering over the heading.

On the second, it will be fully visible from the start as the hover effect doesn't apply to it.

```css

a.anchor {
  color: var(--main);
  text-decoration: none !important;
}

@media (hover: hover) {
	a.anchor {
	  opacity: 0.6;
	}
  h2:hover a.anchor,
  h3:hover a.anchor,
  h4:hover a.anchor,
  h5:hover a.anchor,
  h6:hover a.anchor {
    opacity: 1;
  }
}

@media (hover: none) {
	a.anchor {
	  opacity: 1;
	}
}

```

Let's don't forget (as mentioned earlier) to remove our anchor from prints.

```css
@media print {
	a.anchor { display: none; }
}
```

---

My variable `color: var(--main);` is specified at the beginning of my CSS file as:

```CSS
:root {
  --main: #137faa;
}
```

---

### Accessibility for all

I have added a descriptive label for my anchor link using `aria-label` for users using screen readers, but also `title`, to add descriptive information for all others, to let them know what is the purpose of it.

```html
<h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }} <a class="anchor" href="#{{ .Anchor | safeURL }}" title="Link to section: {{ .Text | safeHTML }}" aria-label="Link to section: {{ .Text | safeHTML }}">#</a></h{{ .Level }}>
```

## Advanced approach

Some of you may stay at the simple approach, but others, like me, would like to experiment a bit further.

Here I will cover relacing `#` with the SVG link icon that I downloaded earlier and presenting a visual tooltip. 

### Link icon

Let's change a bit in our downloaded [SVG link icon](https://fonts.google.com/icons?selected=Material%20Symbols%20Outlined%3Alink%3AFILL%400%3Bwght%40400%3BGRAD%400%3Bopsz%4048) by opening it in VS Studio Code or any other editor.

There I changed it from:

```html
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48">
```

To:

```html
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 96 960 960" width="1em">
```

By copying the whole code in an SVG file I paste it into my `render-heading.html` file in place of the `#` symbol.

To get this displayed on the side of the heading, I just added a small fix in CSS

```css
a.anchor > svg { display: inline-block; }
```

This way I got a link icon that inherits size from the heading font size as well as changing its opacity when hovered over.

There was just a small issue here.

When I used `#` inside `<a class="anchor"` the symbol inherits the colour of the links. In my case blue-ish. 

The predefined anchor colour as below does not work any more.

```css
a.anchor { color: var(--main); }
```

This is because I replace text, that colour is defined by the CSS `color` option, with an icon, that colour is based on CSS `fill` element.

After changing `color` to `fill` all come back to the intended behaviour.

---

This way I completed this part:

- [x] Full link icon visible when hovered over, or when clicking on the heading (on mobile devices). In other instances is still visible but with less transparency;

---

### Copy the link to the clipboard

The default behaviour of a link, when you click on it, under the `#` or SVG link icon is that your browser will head to it. The URL will change to the one that includes a link to the header and the site will scroll. At this stage, you can copy the link from the browser bar to get a pointer to a specified header in the text.

This default behaviour is not bad, however, not everybody would like this type of link to behave like that.

The ideal behaviour will be copying the anchor link to the clipboard without changing the URL in the browser but that will require replacement of the anchor with a button (like Google did).

Let's start with implementation into anchor before we will work with the button later.

The easiest way to add this type of behaviour will be to add `onclick` action.

```html
onclick="navigator.clipboard.writeText({{ print .Page.Permalink "#" .Anchor | safeURL }});"
```

> Hugo will print the current page link, merge it with the `#` symbol and link to the header.

A part of the code will look like that:

```html
<a class="anchor" href="#{{ .Anchor | safeURL }}" title="{{ T "AnchorText" }}{{ .Text | safeHTML }}" aria-label="{{ T "AnchorText" }}{{ .Text | safeHTML }}" onclick="navigator.clipboard.writeText({{ print .Page.Permalink "#" .Anchor | safeURL }});">
```

The **link will still behave as a link** when is clicked, but will also copy the address into the clipboard.

---

The `{{ T "AnchorText" }}` is specified in `i18n\en.toml` file as:

```toml
[AnchorText]
other = "Link to section: "
```

**If you are not using multilanguage implementation on your website you can hardcode this text there.**

---

This way I completed this part:

- [x] Copy the link to the clipboard when clicked on it;

---

### Converting anchor into a button

You may ask what to do if we don't want a link (as above) to behave as a link (redirect to address) but just do one thing only, which is copying the address into the clipboard. 

If you will start looking into this through Google, some people will advise you to leave it as an anchor (`<a`) but remove `href=` reference. **Please don't!**. Instead, let's replace this link with a button as Google did in their documentation.

Example from Google:

```html
<button type="button" class="devsite-heading-link button-flat material-icons" aria-label="Copy link to this section: What is SEO?" data-title="Copy link to this section: What is SEO?" data-id="what-is-seo"></button>
```

At the current stage, my code for `render-heading.html`, with implemented inline SVG link symbol instead `#` symbol, looks like that:

```html
<h{{ .Level }} {{- range $k, $v := .Attributes -}}{{- printf " %s=%q" $k $v | safeHTMLAttr -}}{{- end -}}>{{ .Text | safeHTML }} <a class="anchor" href="#{{ .Anchor | safeHTMLAttr }}" title="{{ T "AnchorText" }}{{ .Text | safeHTML }}" aria-label="{{ T "AnchorText" }}{{ .Text | safeHTML }}" onclick="navigator.clipboard.writeText({{ print .Page.Permalink "#" .Anchor | safeHTMLAttr }});"><svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 96 960 960" width="1em"><path d="M450 776H280q-83 0-141.5-58.5T80 576q0-83 58.5-141.5T280 376h170v60H280q-58.333 0-99.167 40.765-40.833 40.764-40.833 99Q140 634 180.833 675q40.834 41 99.167 41h170v60ZM325 606v-60h310v60H325Zm185 170v-60h170q58.333 0 99.167-40.765 40.833-40.764 40.833-99Q820 518 779.167 477 738.333 436 680 436H510v-60h170q83 0 141.5 58.5T880 576q0 83-58.5 141.5T680 776H510Z"/></svg></a></h{{ .Level }}>
```

> Ranging `.Attributes` will include `.Anchor` in output, hence no need to add it separately.

Let's replace `<a href=` with `<button type="button"` at first and adjust the CSS accordingly.

```html
<h{{ .Level }} {{- range $k, $v := .Attributes -}}{{- printf " %s=%q" $k $v | safeHTMLAttr -}}{{- end -}}>{{ .Text | safeHTML }} <button type="button" class="anchor" title="{{ T "AnchorText" }}{{ .Text | safeHTML }}" aria-label="{{ T "AnchorText" }}{{ .Text | safeHTML }}" onclick="navigator.clipboard.writeText({{ print .Page.Permalink "#" .Anchor | safeHTMLAttr }});"><svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 96 960 960" width="1em"><path d="M450 776H280q-83 0-141.5-58.5T80 576q0-83 58.5-141.5T280 376h170v60H280q-58.333 0-99.167 40.765-40.833 40.764-40.833 99Q140 634 180.833 675q40.834 41 99.167 41h170v60ZM325 606v-60h310v60H325Zm185 170v-60h170q58.333 0 99.167-40.765 40.833-40.764 40.833-99Q820 518 779.167 477 738.333 436 680 436H510v-60h170q83 0 141.5 58.5T880 576q0 83-58.5 141.5T680 776H510Z"/></svg></button></h{{ .Level }}>
```

```CSS
button.anchor {
  fill: var(--main);
  display: inline-block;
}

@media (hover: hover) {
	button.anchor {
	  opacity: 0.6;
	}
  h2:hover button.anchor,
  h3:hover button.anchor,
  h4:hover button.anchor,
  h5:hover button.anchor,
  h6:hover button.anchor {
    opacity: 1;
    cursor: pointer;
  }
}

@media (hover: none) {
	button.anchor {
	  opacity: 1;
	}
}
```

By default, our anchor link inherits styling from the main anchor. When we replace it with a button we need to remove some default stylings so it will look the same (without button borders).

> Added also cursor behaviour to a button to change into a pointer when hovered over, which is typical behaviour for links, but not necessarily for buttons. Thanks for the suggestion for [Sid](https://discourse.gohugo.io/u/Sid).

I did that by replacing `button.anchor` with the following:

```CSS
button.anchor {
  fill: var(--main);
  background-color: inherit;
  border: none;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: inherit;
  padding: 0;
}
```

Let's don't forget to remove the button from printed pages

```CSS
@media print {
	button.anchor { display: none; }
}
```

This way we got an anchor button that acts like an anchor. Browsers do not follow the link but only copy the link into the clipboard.

When we click on our new button, the problem is that we don't have any prompt or visualisation that the **copy to clipboard** even happens. This is where we need to add something more so the user will know what happens unless they hover over the button for a couple of seconds to get the `title=` output showing (on desktop).

To add the visualisation we will get rid of the `title=` element, and replace it with something else.

### Visual tooltip on button hover

My `render-heading.html` contains `aria-label` for accessibility and `title` for visual information when you hover over the link (on desktop).

The default behaviour of the `title` attribute is strictly dependent on the browser and appears after a while when hovering over the element with it.

If I want to use this for a visual tooltip I will resign from the `title` attribute in favour of [the use of data-* attribute to embed custom data](https://www.w3schools.com/tags/att_global_data.asp) (in my case `data-title`).

> In my code I replaced `title=` with `data-title=`. This will remove default browser behaviour, as it will be missing the title attribute, but this will not have an impact unless you browsing websites without styles, which probably will only happen on the next CSS Naked Day.

For this purpose, I will use the approach that I found at stackoverflow in the post [Change how fast "title" attribute's tooltip appears](https://stackoverflow.com/questions/9150796/change-how-fast-title-attributes-tooltip-appears).

```CSS
@media (hover: hover) {
  [data-title] {
  position: relative;
  }

  [data-title]:after {
  font-size: var(--h6);
  content: attr(data-title);
  position: absolute;
  left: 50%;
  top: 100%;
  color: var(--white);
  background-color: var(--black);
  width: max-content;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
  padding: 0.4rem 0.5rem;
  border-radius: 5px;
  }

  [data-title]:hover:after {
  opacity: 1;
  }
}
```

I have wrapped it in `@media (hover: hover)` as this is only relevant to devices where you can put a pointer over the element.

My variables in the above CSS are as follows:

```CSS
:root {
 --h6: 0.67rem;
 --black: #222;
 --white: #fff;
}
```

---

This way I completed this part:

- [x] Tooltip when hovering over (on desktop);

---

{{% ads-in-article %}}

### Visual tooltip on click on the button

Now we need to sort out the last thing. When somebody will click on our anchor link (button), they need to have a prompt about what happens. This is especially important on touch devices where the previous point (hovering over) is not relevant.

For this purpose, I found a method how to incorporate it into the `onclick` action that was used to copy the link to the clipboard by injecting HTML into it.

```javascript
this.insertAdjacentHTML('afterend', '<div class=link-copied>Link copied</div>');setTimeout(() => { document.querySelectorAll('.link-copied').forEach(el => el.remove()); }, 3000);
```

```css
.link-copied {
  font-size: var(--h5);
  position: fixed;
  left: 1rem;
  bottom: 1rem;
  margin: 1rem;
  color: var(--white);
  background-color: var(--black);
  width: max-content;
  padding: 0.4rem 0.7rem;
  border-radius: 5px;
  z-index: 1;
}
```

My additional variable in CSS:

```CSS
:root {
 --h5: 0.83rem;
}
```

This visual prompt has its timeout specified after which it will disappear.

This way my combined `onclick` action will look as follow:

```html
onclick="navigator.clipboard.writeText({{ print .Page.Permalink "#" .Anchor | safeURL }});this.insertAdjacentHTML('afterend', '<div class=link-copied>{{ T "LinkCopied" }}</div>');setTimeout(() => { document.querySelectorAll('.link-copied').forEach(el => el.remove()); }, 3000);"
```

The `{{ T "LinkCopied" }}` is specified in `i18n\en.toml` file as:

```toml
[LinkCopied]
other = "Link copied to clipboard"
```

---

This way I completed this part:

- [x] Receive a visual prompt about copy to clipboard action.

---

## The final code

Combining a simplified and advanced approach my code for `render-heading.html` with appropriate CSS styling will look as follow.

`render-heading.html`

```HTML
<h{{ .Level }} {{- range $k, $v := .Attributes -}}{{- printf " %s=%q" $k $v | safeHTMLAttr -}}{{- end -}}>{{ .Text | safeHTML }} <button type="button" class="anchor" data-title="{{ T "AnchorText" }}{{ .Text | safeHTML }}" aria-label="{{ T "AnchorText" }}{{ .Text | safeHTML }}" onclick="navigator.clipboard.writeText({{ print .Page.Permalink "#" .Anchor | safeHTMLAttr }});this.insertAdjacentHTML('afterend', '<div class=link-copied>{{ T "LinkCopied" }}</div>');setTimeout(() => { document.querySelectorAll('.link-copied').forEach(el => el.remove()); }, 3000);"><svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 96 960 960" width="1em"><path d="M450 776H280q-83 0-141.5-58.5T80 576q0-83 58.5-141.5T280 376h170v60H280q-58.333 0-99.167 40.765-40.833 40.764-40.833 99Q140 634 180.833 675q40.834 41 99.167 41h170v60ZM325 606v-60h310v60H325Zm185 170v-60h170q58.333 0 99.167-40.765 40.833-40.764 40.833-99Q820 518 779.167 477 738.333 436 680 436H510v-60h170q83 0 141.5 58.5T880 576q0 83-58.5 141.5T680 776H510Z"/></svg></button></h{{ .Level }}>
```

`i18n\en.toml`

```toml
[AnchorText]
other = "Copy link to section: "

[LinkCopied]
other = "Link copied to clipboard"
```

`style.css`

```CSS
button.anchor {
  fill: var(--main);
  background-color: inherit;
  border: none;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: inherit;
  padding: 0;
}

@media (hover: hover) {
	button.anchor {
	  opacity: 0.6;
	}
  h2:hover button.anchor,
  h3:hover button.anchor,
  h4:hover button.anchor,
  h5:hover button.anchor,
  h6:hover button.anchor {
    opacity: 1;
  }
}

@media (hover: none) {
	button.anchor {
	  opacity: 1;
	}
}

@media (hover: hover) {
  [data-title] {
  position: relative;
  }

  [data-title]:after {
  font-size: var(--h6);
  content: attr(data-title);
  position: absolute;
  left: 50%;
  top: 100%;
  color: var(--white);
  background-color: var(--black);
  width: max-content;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
  padding: 0.4rem 0.5rem;
  border-radius: 5px;
  }

  [data-title]:hover:after {
  opacity: 1;
  }
}

.link-copied {
  font-size: var(--h5);
  position: fixed;
  left: 1rem;
  bottom: 1rem;
  margin: 1rem;
  color: var(--white);
  background-color: var(--black);
  width: max-content;
  padding: 0.4rem 0.7rem;
  border-radius: 5px;
  z-index: 1;
}
```

Variables in `style.css`

```CSS
:root {
	--main: #137faa;
	--h5: 0.83rem;
	--h6: 0.67rem;
	--black: #222;
	--white: #fff;
}
```

**Job done.**

The effect of this approach you can observe on this page as well as others with headings.


---
## Publish your content in Bing News and Windows feed... if you are lucky enough
- **URL:** https://dariusz.wieckiewicz.org/en/publish-your-content-in-bing-news-windows-feed/
- **Date:** 2023-05-14
- **Tags:** Bing News, Windows feed, news aggregator, RSS, RSS Feed, Atom, Atom Feed, web feed, Bing, Google Publisher Center, Bing PubHub, Publisher Center, Bing Webmaster Tools

### Content

> In early 2025, Microsoft officially deprecated Bing News PubHub, moving away from a manual submission model for news publishers.
>
> The manual submission process is fully retired. Existing publishers who were already approved remain in the index, but the portal for new applications has been disabled.
>
> I am providing the following article for reference only.

Recently I wrote about how to [Publish your content in Google News on Android, iOS and news.google.com](/en/publish-your-content-in-google-news/). Looking further I checked if there is such an option in other search engines like... Bing.

Bing is also offering aggregated News in [Bing News](https://www.bing.com/news) along with serving this through integration into the Windows operating system.

Users can get their personalized content through Bing and Microsoft Start, Windows, Edge and Office.

<!--more-->

Despite that Bing doesn't have the same reach as Google, the Windows operating system, through enabled and pinned into the Start menu/taskbar, weather/news widgets, may give you that reach.

If a particular user is interested in food recipes, he will be suggested with more related content, so why not suggest ours as well?

Google utilise specific Publisher Center to add content to their aggregated news feeds. Bing (Microsoft) operates a Bing PubHub to aggregate information from various sources. 

The [Bing PubHub](https://www.bing.com/webmasters/pubhub?source=pubhub) is integrated into [Bing Webmaster Tools](https://www.bing.com/webmasters), however, the link is not ordinarily visible, hence its existence is not so obvious for an ordinary user.

```
https://www.bing.com/webmasters/pubhub
```

Sometimes it will appear in **recommended** section when we head to the [Bing Webmaster Tools homepage](https://www.bing.com/webmasters/home).

![Bing PubHub in recommended section on homepage of Bing Webmaster Tools](recommended_section_bing_webmaster_Bing_PubHub.png)   

Before we start, it's worth knowing that to publish in Bing PubHub you do not necessarily need to serve news. Both news and non-news sites are supported. Very similar to Google Publisher Center, however [PubHub Guidelines for Publishers](https://www.bing.com/webmasters/help/pubhub-publisher-guidelines-32ce5239) clarify what eligibility criteria need to be met for non-news publishers.

As with Google, here with Bing, we can easily utilise website RSS to spread our content.

> I will recall once again my post from 2021 stating why [RSS is not dead and still matters](/en/why-rss-still-matters-in-2021/).

## Pre-setting up

There are a couple of things that need to be set along the road.

1. **Content submission** is where we will utilise our website RSS feed.
2. **Accountability and transparency** is where we need to state clearly who is the publisher, which includes a physical address and email address.
3. **Content rights and responsibility** is about the content and our right to it. If you publish or repost, somebody's content without obtaining permission, which includes not only text but also images, this may cause you a problem. It's better to address this before to avoid (pricey) disappointment later.
4. **Attribution and representation**.

## Setting up

Let's head to [Bing PubHub](https://www.bing.com/webmasters/pubhub) in Webmaster Tools.

![Bing PubHub - Start Page](Bing_PubHub_start_page.png)

### Site Info

![Bing PubHub - adding Site Info](Bing_PubHub_adding_Site_Info.png)

Let's state the **name**, **language** in which the website is presented and the **region**.

The first website I add was for [Yummy Recipes UK](https://yummyrecipes.uk) where, along with my friend, who is creating the content, we publish (_"with some level of frequency"_) delicious and easy recipes for everybody.

Our intended reach (‌**Audience**) is Global, but also National. Not necessarily Regional or Local, and not industrial. We tick relevant tick boxes.

### Adding our URLs

![Bing PubHub - adding your URLs RSS Sitemaps](Bing_PubHub_adding_your_URLs_RSS_Sitemaps.png)

Here we will select **Link type** as **RSS** and paste a link to our feed. We are using [Hugo](https://gohugo.io) to build our website, our RSS is presented in the root directory as an `/index.xml` file.

```
https://yummyrecipes.uk/index.xml
```

If we got more feeds or sources, we can also add them here, like a sitemap.

```
https://yummyrecipes.uk/sitemap.xml
```

{{% ads-in-article %}}

### Contacts

![Bing PubHub - adding Contacts](Bing_PubHub_adding_Contacts.png)

The last part is to specify **business name** and the person of contact. As a content manager, I specified myself as a first in line for a matter of Bing PubHub.

Once all are filled, we finish by pressing the **Agree and Submit** button.

![Bing PubHub - Awaiting for Approval (11 February 2023)](Bing_PubHub_Awaiting_for_Approval_11_February_2023.png)

Now it's waiting time.

Microsoft or Bing team do not give us a timescale like it was when we add a website to Google's Publisher.

## Follow

Despite this feature being very similar to Google News there is no direct option to follow your source so you cannot see how this will look on your device. All are curated by the Microsoft algorithm.

## Rejection

When you set up your source, surprisingly there is no option to specify under which category you fall with your site.

If at some stage your addition will not be added, there is no forum or way to contact to discuss that apart from just [single email address](https://www.bing.com/webmasters/help/pubhub-publisher-guidelines-32ce5239) with a disclaimer. Your email, as you may suspect, will remain without an answer.

> _"Please contact customer support with any questions about these guidelines. However, please note that we are unable to provide feedback on how to improve your site for evaluation."_

My addition was no different.

![Bing PubHub - Rejected (27 February 2023)](Bing_PubHub_Rejected_27_February_2023.png)

On 27th February 2023, it has been rejected with vogue text:

> _The site application has been rejected. Please resolve the issues communicated in the email and submit the form again. Click on the edit form below to make the necessary changes._

The problem is that **no email has been received**.

The annoying part was the text on top of the button stating "Click on the edit form below to make the necessary changes". It will be nice if the button was active!

![Bing PubHub - Rejected (27 February 2023) - hovering the button](Bing_PubHub_Rejected_27_February_2023_Button_hover.png)

When you hover over the button you will have a tooltip saying:

> _You can re-submit your site for verification after 15:05 on March 29, 2023,_

**No email, no explanation and you need to wait for over a month before you can do anything.**

I am not surprised that webmasters don't give a toss about Bing and its Webmaster tools. Here, even their AI Chatbot will not help change that. Sorry Microsoft, but you are still missing the point. I think Bing, same as it was with Internet Explorer shall end and come back resurrected as a new product to have at least a chance to exist, as it happens with Chromium-based Microsoft Edge.

Once again, despite this text:

> _Please contact customer support with any questions about these guidelines. However, please note that we are unable to provide feedback on how to improve your site for evaluation._

I decided to contact them, not asking about the reason for rejection **but about the email which I didn't receive**.

Patiently waited until the 29th of March after where, after not changing anything (as I didn't know exactly what was the problem and the reason for rejection in the first place), resubmitted the site again.

Sadly, I don't hold a lot of hope for this. Due to a lack of any feedback on my email, I don't understand how this tool is even in use by anybody.

![Bing PubHub - Awaiting for Approval (30 MArch 2023)](Bing_PubHub_Awaiting_for_Approval_30_March_2023.png)

Since my resubmission at 6:41 am on March 30, 2023 nothing changed and the submission stuck at **Awaiting for Approval** for a month and a half and counting.

Despite that I still don't know if the site will be accepted, it's worth it for you, the owner of the website on which you publish some useful content, to see and evaluate new ways to promote and reach a wider audience.

It doesn't cost anything so why not try?

If you decided to do this, let me know in the comments below how it goes. Any success stories would be appreciated. In the meantime, if my addition will be added or rejected or somehow I will get an email back from Microsoft, I will share an update with you all.


---
## Setting hreflang and x-default on a multilingual site (with Hugo)
- **URL:** https://dariusz.wieckiewicz.org/en/setting-hreflang-and-x-default-on-multilingual-site/
- **Date:** 2023-05-12
- **Tags:** Google, hreflang, international SEO, multilingual SEO, language targeting, hreflang attributes, hreflang links, hreflang annotations, hreflang validation, hreflang use cases, x-default, default language, fallback language, multilingual sites, WebDev, Hugo

### Content

Setting a hreflang meta tag on your multilingual website shall be as simple as a piece of cake. Just put the relevant meta tag on your website, refer to the translated version and on translated version refer back to the original one.

Looks as simple as that. End of story? **Wrong!**

<!--more-->

As simple as it sounds, not always, in practice it is like that. If you operating a website in multiple languages, but not all the content is served with its translated counterpart, setting and using a hreflang tag across the website is a bit of a challenge. If you add to that the correct use of the x-default meta tag, this becomes even more of a challenge.

Once you thinking how to implement this correctly, more questions arise and searching the internet will give you answers that don't match to each other.

Even Google in their Google Search Central documentation has its post titled [Tell Google about localized versions of your page](https://developers.google.com/search/docs/specialty/international/localized-versions) which does not clarify some scenarios.

Luckily, on the 8th of March 2023, a new post appears titled [How x-default can help you](https://developers.google.com/search/blog/2023/05/x-default) which changes your perspective on how you shall look into the implementation of a hreflang and x-default meta tags.

**It's all about the [conversions](https://developers.google.com/search/blog/2023/05/x-default#2.-conversions) and not international targeting** as many think. Even Google [pushed back](https://support.google.com/webmasters/answer/12474899?hl=en) from this.

This post finally answers some of my questions.

The main approach is to change your way of thinking about a hreflang and the x-default tag.

> _Your goal is very likely to convert in some way the users that land on your pages._
>
> _(...) if you only published the essay in German, it's unlikely that non-german speakers would convert on that page, so you might want to send them somewhere else where they might actually convert in some other way (...)_

Think about the above when reading further.

---

My main website address (`/`) refers to the Polish version. If you head to `/en/` you land on the English version.

Some posts are translated and nicely linked with each other through the flag in the right-top corner. If the post is available in English and you are on the Polish part you can click the English flag and you reading in English.

> For this type of page there is a hreflang meta tag for Polish and English on both of the posts self-referencing each other.

If is not, I am offering auto-translation using Google Translator, which is not as bad as it was years ago.

The problem is that I am not translating everything into the English language if I am writing in Polish. Same, if I am starting to write a post in English (like this one), not always I will decide to translate it back to Polish. Sometimes it's simply pointless and consumes unnecessarily my time without any gains for my readers.

Sometimes the decision to translate or not is dictated by the context of the post. Sometimes something written in English will make sense for an English speaker but will not make sense at all for a Polish speaker, especially if he is reading it from Poland (with a Polish approach), and not like me from the United Kingdom with an inherited British lifestyle.

You will probably get the point if I will try to translate a word or a meaning that got perfect sense in British English, but in Polish where it simply doesn't exist. This will require you to give a full explanation of what you have on your mind when in English it's just a single word (and vice versa).

The post [How x-default can help you](https://developers.google.com/search/blog/2023/05/x-default) helps me understand how to implement a hreflang and how to use the x-default setting for **conversion purposes**.

I always struggle with x-default, as my website in Polish doesn't contain all that is in English part.

I would not like to suggest for non-(default)-English, and non-Polish speakers to go to the Polish site by default if they are set with a different (default) language, other than these two.

It is much easier for non-English and non-Polish speakers (let's say French speakers with French set as their default language in the operating system) to land on the English part of the website rather than Polish by default. It's more likely that they will understand English rather than Polish.

But also I would like some people to know that if I write something in Polish and it's not available in English, they can use the translate button on the right-top corner to get it translate, rather than simply close the page that they don't understand.

This is where the right setting and the right understanding of how to utilise the x-default meta tag come in handy with the conversion on our minds.

---

Starting from the basic approach when both pages are translated (like my About Me page), the halfling in the head will look like below.

On Polish page about me ([/o/](/o/))
```html
<html lang=pl-pl xml:lang=pl-pl>
...
<link rel=alternate hreflang=pl href=https://dariusz.wieckiewicz.org/o/>
<link rel=alternate hreflang=en href=https://dariusz.wieckiewicz.org/en/about/>
```

On same page in English ([/en/about/](/en/about/))
```html
<html lang=en-gb xml:lang=en-gb>
...
<link rel=alternate hreflang=en href=https://dariusz.wieckiewicz.org/en/about/>
<link rel=alternate hreflang=pl href=https://dariusz.wieckiewicz.org/o/>
```

Thats straight forward approach when both ends are translated.

In **Hugo** this will be implemented in the `<head>` with the following code.

```html
<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .RelPermalink }}">
{{ range .Translations }}
	<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .RelPermalink }}">
{{ end }}
```

But what if I will write a post that is only in English?

I can add a condition, where there is no translation the whole hreflang will be omitted.

```html
{{ if .IsTranslated }}
	{{ range .Translations }}
		<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .RelPermalink }}">
	{{ end }}
	<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .RelPermalink }}">
{{ end }}
```

This will result that some pages will have a hreflang and others not.

> The **conversion in mind** approach is for such a thing, that if the result is in language, that, by default, the user will not understand, let's suggest him something else that may interest him. In such a way it is more likely that he will explore something else in a language that he understands, rather than just leaving the website altogether.

{{% ads-in-article %}}

In [quoted suggestion](https://developers.google.com/search/blog/2023/05/x-default#2.-conversions) I will still serve a hreflang tag, even if that page got only one language, and if the language is not the one that the user understands, will offer **an alternative**. The alternative site will be the [language selection](/en/language-selector) page on which I will explain available languages, the fact that not all pages will be translated by default and that users can still use pages that they don't understand with the auto-translation option.

This will look as below example:

```html
<html lang=en-gb xml:lang=en-gb>
...
<link rel=alternate hreflang=en href=https://dariusz.wieckiewicz.org/en/minimal-google-analytics-4-snippet/>
<link rel=alternate href=https://dariusz.wieckiewicz.org/en/language-selector/ hreflang=x-default>
```

Or

```html
<html lang=pl-pl xml:lang=pl-pl>
...
<link rel=alternate hreflang=pl href=https://dariusz.wieckiewicz.org/microsoft-mial-racje-nie-aktualizuj-do-windows-11/>
<link rel=alternate href=https://dariusz.wieckiewicz.org/en/language-selector/ hreflang=x-default>
```

In this way, each page will utilize a hreflang approach. If there is a translation, there will be additional language listed. As an alternative, there will be a reference to a dedicated page that can be understood by a majority of visitors from which they are more likely to **convert** further (read more).

For that, I will utilize the following code on my Hugo website:

```html
<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .RelPermalink }}">
{{ range .Translations }}
	<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .RelPermalink }}">
{{ end }}
<link rel="alternate" href="{{ .Site.Params.langSelector | absURL }}" hreflang="x-default">
```

In my Hugo config file (`hugo.toml`) I will specify an address for the language selection page

```toml
[params]
	langSelector = "/en/language-selector/"
```

In the frontmatter of the markdown file where I will put my content, I will present the URL.

```markdown
---
url: '/en/language-selector/'
---
```

This will work as explained in [Google's latest blog post](https://developers.google.com/search/blog/2023/05/x-default#2.-conversions).

> _However if you only published the essay in German, it's unlikely that non-german speakers would convert on that page, so you might want to send them somewhere else where they might actually convert in some other way. You can express this with hreflang="x-default"_

Hope that clarifies something for people in a similar situation to mine, where not all posts are translated equally.

---

There are some tools available on the internet that will tell you if you [correctly implemented hreflang](https://hreflangchecker.com). [Others](https://technicalseo.com/tools/hreflang/) will tell you something different. That's because the approach described above is not a typical, most commonly known way of implementation yet still correct.

Gary Illyes, Analyst at Google [said this on his LinkedIn profile](https://www.linkedin.com/feed/update/urn:li:activity:7061239741156839424/):

> _While a hreflang x-default value was implemented to help with very specific needs, incidentally it can also help with feeding Googlebot URLs that the poor thing otherwise might not see. This is not a new thing, but I think it's pretty cool that it has "hidden" use cases._

If you want to learn more, head to the documentation on how to [Tell Google about localized versions of your page](https://developers.google.com/search/docs/specialty/international/localized-versions).


---
## Escape from Bing Jail
- **URL:** https://dariusz.wieckiewicz.org/en/escape-from-bing-jail/
- **Date:** 2023-05-01
- **Tags:** Bing, Microsoft, penalized, secret blacklisting, Shadow banning, duckduckgo, Bing Support, Bing Search, Bing Webmaster Guidelines, Google Search Console, splog, Spam Blog, SEO, Site Scan, WebDev, Indexed Pages, Crawl

### Content

My post about [**Bing Jail**](/en/bing-jail/) gained a bit of attention (**a lot!**). With the traction, there is hate, but I could expect that as well. There was a bit of conversation in the comments on [Hacker News](https://news.ycombinator.com/item?id=35677086) which gives me valuable feedback.

This short, **post scriptum** post is **not** an explanation but rather my experience on the following days. My site reappear in Bing search for one day to be manually removed (blocked) the day after where Bing Support, who surprisingly responded, start looking into the case.

<!--more-->

---

Just 24 hours after my post I find out that [my site start appearing in Bing](https://www.bing.com/search?q=site%3Adariusz.wieckiewicz.org) and consequently [DuckDuckGo](https://duckduckgo.com/?q=site%3Adariusz.wieckiewicz.org) once again.

From a typical (small) number of users visiting my website daily, I gained over 7.79K in just a couple of evening hours (UK time) on a post date followed by over 9.32K a day after. **This traction has some force!**

## Blocklists

Some users, in Hacker News comments, pointed out that my site is blocked by some adblockers. Once I investigated that, it all went into [Polish Annoyance Filters](https://polishannoyancefilters.netlify.app) where my site was added at some point in 2019. This probably does not have a direct impact on Bing being blacklisted three years later but since 2019 lot has changed. There were other filters where my site was added, or simply blindly copied from other lists without checking. I am not surprised if Bing Team do the same.

In 2019 my site was WordPress based and been serving some Google Ads. Since I moved to Hugo in late-2020 a lot on the website itself changed. It become much clearer that the content and user experience are more important than scraps that I received from advertisements, the scraps that overall kill users' engagement.

Resignation from serving ads was also because my site is served now on [Netlify](https://www.netlify.com) which does not cost me as much as WordPress hosting in the past.

I have contacted the maintainers of the lists in a couple of repositories on GitHub and worked together to remove them. 

Even after removal, not all the changes will happen straight away but after just a couple of days, I shall observe change, especially on [AdGuard list 237](https://filters.adtidy.org/windows/filters/237.txt) which was updated on the 25th of April 2023 with my website not been there.

> AdBlock Team upon contact been also helpful to point me in the right direction to get my site removed from the PAF list.

At that time I thought that I escaped from Bing Jail as my site reappeared in full, **but did I?**

As I have no response from Bing Team, my post must reach somebody who knew somebody who decided to check that. Possibly Bing is using AdBlock filter lists (**I doubt it**) to filter their search results from mid-January 2023, especially for non-English websites. Without any feedback, we will never know what's going on here.

When I inspected my homepage (Polish) in Bing Webmaster Tools URL Inspection, Bing Index do not report an issue like previously, instead returned green ticks stating **Indexed successfully**.

![Bing Webmaster Tools - URL Inspection - Indexed successfully](/images/2023/05/Bing_URL_Inspection_Indexed_successfully.png)

The first page that appears back in Bing was indexed at 18:44 UK time on 24th April 2023. That's just not long after a team from Polish Annoyance Filters published their repo with my website removed from their list. **Coincidence?**

![Bing Webmaster Tools - 1st URL Inspection - Indexed successfully](/images/2023/05/Bing_1st_URL_Inspection_Indexed_successfully.png)

Yes, this may be a coincidence, but as we know Bing went through some changes in the middle of January 2023 so maybe one of the changes (not acknowledged) was the use of popular AdBlock filters to clean their indexed pages.

> Finding if your site has been added to any block lists over the Internet is like searching for a needle in hay stag. Only through some helpful people who left comments on Hacker News posts, I have been able to act upon it. But how others can fight that?

On the next day, the 25th, I noticed that a lot more pages starts appearing in Bing results as well. The chart in Webmaster Tools remains at zero, but, similar to Google Search Console charts, the update is typically a couple of days behind.

> It doesn't look like a coincidence when [AdGuard list 237](https://filters.adtidy.org/windows/filters/237.txt) was updated (`TimeUpdated: 2023-04-25T01:01:45+00:00`) not far before more results start reappearing.

On the morning of 25th of April 2023, at 7:25 UK time Bing reported back **2,280 results** when [searched strictly by my site URL](https://www.bing.com/search?q=site%3Adariusz.wieckiewicz.org) and on desktop, the results were fulfilled with [rich snippets](https://www.bing.com/webmasters/help/marking-up-your-site-with-structured-data-3a93e731) on a side.

**Things (initially) changed thanks to all of you who read and shared my post and through the power of [Hacker News](https://news.ycombinator.com) itself.**

Sadly, there are more stories about the same practices without any acknowledgement either in Bing Webmaster Tools or directly from Bing Team upon contact.

I am starting to think what is the sense of having a tool that does not display useful information, especially when you are rejected.

The whole story reminds me of what I learned when I first come to live in the United Kingdom back in 2010. In this country if you want to achieve something you need to get yourself heard, you need to ask, you need to speak and **you need to complain!**

## A bit of optimism

On the morning of the 27th of April Bing Search Performance chart finally refreshed and showed what I had been seeing through earlier days.

If you look closer to the chart you will say that it doesn't look normal. It's not possible to spike from zero to 2.3K indexed pages overnight and you are right, **it's not possible** unless the pages have been there but have been simply **blocked**.

![Bing Webmaster Tools - Search Performance on 26th April 2023](/images/2023/05/Bing_Search_Performance_26-04-2023.png)

The chart clearly shows that someone or something has been blocking my site from Bing and mentioned blacklisting exists. Looks like my post, **through all of you**, reached someone and I escaped from Bing Jail (once again, **did I?**), but there are a lot of other inmates (website) still there.

Nicholas A. Ferrell has been inspired by my [Bing Jail](/en/bing-jail/) post and he decided to share his story as well in post [**The story of our Bing blacklisting**](https://thenewleafjournal.com/the-story-of-our-bing-blacklisting/) (take some time for reading in full, it's worth it). I only hope that he will have his attention as I have and his website reappear in Bing in no time. Please share his story and help in the same way you helped me.

## Failed prison break

I repeated twice the word **“Did I?”** and here is the answer.

**My Prison Break ended in captivity again!**

As I thought that issue had been sorted, I just checked on 27th April 2023 once again does Bing show any results for my site? Just a couple of hours earlier there were **2,280 results** and today morning I was presented with information that [**Some results have been removed**](http://go.microsoft.com/fwlink/?LinkID=617350) and my site disappeared once again from Bing results. **Zero, nada!**

![Bing Search on 27th April 2024 - Some results have been removed](/images/2023/05/Bing_27-04-2024_Some_results_have_been_removed.png)

**I am angry again!**

This time I was presented with a link to documents on how Bing delivers search results. Off course this link wasn't really useful without any feedback from Bing Team.

**That was before noon on 27th April 2023.**

At 2 pm the **hell freezes over**.

## Blacklisting confirmed

At 2:14 pm on 27th April 2023, my inbox landed with a response from Bing Team to my query **REQ00056361**. It looks like the attention gained by my [**Bing Jail**](/en/bing-jail/) post went in the right direction and reached the right people (did it?).

I already start giving up when I saw that my site disappeared from Bing the day after it bounced back.

**But let's get to the email response...**

Straight away when I read the first sentence I shouted inside - **Bing got hidden blacklisting in place!**. Email state the following:

> "Firstly, I am happy to provide you information that our Product Review Group succeeded in resolving the issue which prevented your site from showing in our index. After submitting your site to be reviewed, the team has decided to lift the  block. Allow up to two to three weeks for your site to be crawled, indexed, and serving again."

Straight away when I read it I composed a response email just to verify, is this, what I saw yesterday, was when the block was lifted? What happens today that my site is gone once again? Am I being blocked for a second time or it's just how it's working and it will take mentioned **"up to two to three weeks for your site to be crawled, indexed, and serving again"?**

I will need to monitor it further and patiently wait but I cannot believe that Microsoft indeed doing blacklisting without any acknowledgement. They have in their Webmaster Tools section called **Security & Privacy** with subsection **Copyright Removal Notices**. Why not add there any block information and violations so users will be aware and, if indeed the blocks are valid, they will be able to act upon them?

**But are the blocks valid?**

Reading the email further we got the following:

> "I am unable to provide you the specifics of the block, as our Product Review team does not share the details of the block. However, I wish to help you with a few links and help docs, which will not only help in avoiding blocks, but also help you to rank better in the Bing index."

Of course, they **cannot "provide you the specifics of the block"**, why would they? As I mentioned in my initial post, if that would happen to somebody with a lot of money to spare, this would finish in a lawsuit. I understand that Bing Index is a product that is offered for free, but even free products are bonded with some terms of use and some rules to obey by both parties. Implementing shady practices like this kind of block is **unacceptable!**

I have been provided with the following link which I decided to review to see if they will give me any clue of why this happened in the first place. I doubt that they will (like pointing to Bing Webmaster Guidelines) but will try.

- [Why is My Site Not in the Index?](http://www.bing.com/webmaster/help/why-is-my-site-not-in-the-index-2141dfab)   
- [10 SEO Myths Reviewed](http://blogs.bing.com/webmaster/2014/05/09/10-seo-myths-reviewed)
- [Is SEO The Future? No, And Here’s Why](http://blogs.bing.com/webmaster/2014/04/24/is-seo-the-future-no-and-heres-why)
- [Building Authority & Setting Expectations](http://blogs.bing.com/webmaster/2014/10/17/building-authority-setting-expectations)
- [The Role of Content Quality in Bing Ranking](http://blogs.bing.com/search-quality-insights/2014/12/08/the-role-of-content-quality-in-bing-ranking)

Before I will do that I looked at the next sentence in their response:

> "When Bing crawls and indexes pages on the Internet, it makes decisions about which pages will most likely resonate with searchers, so we look at these signals relative to all other sites on the web as part of our selection criteria. Always ensure you follow webmaster guidelines, especially the section Things to Avoid."

**Seriously Bing?** You think that my content does not **"resonate with searchers"**. Google Search users and results from analytics of my website will disagree!

I will look at the link under [Things to Avoid](https://www.bing.com/webmaster/help/webmaster-guidelines-30fba23a#avoid) once again later, but I doubt that I will find anything explaining this whole situation. Overall this points back to Bing Webmaster Guidances that I went through already.

Email finishes with:

> "Let me know if you have any follow-up questions or concerns regarding this issue and I would be more than happy to assist.  Have a wonderful day ahead!"

Of course, I got a follow-up question which I sent.

{{% ads-in-article %}}

---

I didn't expect a follow-up answer but, to my surprise, it arrived in my inbox at 9:50 (UK Time) on 28th April 2023 stating:

> I am happy to inform you that the issue that prevented your site https://dariusz.wieckiewicz.org/en/ from showing in our index has been resolved.
> 
> It may take up to 2-3 weeks for your site to be crawled indexed and serving again. Additionally, you can submit your URL using the URL Submission feature to get them recrawled faster.
> 
> Please review our Webmaster Guidelines, especially the section Things to Avoid, to avoid this in the future.

Looks like I have been treated differently, as I got somebody responding to my emails.

This email however doesn't change the fact that when I [search my website through Bing](https://www.bing.com/search?q=site%3Adariusz.wieckiewicz.org%2Fen%2F) still got notice that **Some results have been removed** and zero results.

It has been suggested to "submit your URL using URL Submission feature to get them recrawled faster" which I of course do to see if anything changes. **No changes whatsoever!**

At the time of checking, 28th April 2023 11:38 UK Time, the site (the `/en/` as mentioned in the email) **still showing as present in Bing Index despite not being displayed in search**.

![Bing Webmaster Tools - Indexed successfully on 28th April 2023](/images/2023/05/Bing_Indexed_successfully_28-04-2023.png)

> I pressed **Request indexing** button as well.

Once again I have been pointed to **Things to Avoid** section in Bing Webmaster Guidelines, "to avoid this in the future" which I will go into dept then to see if there are **any** signs of explanation.

I once again followed up with an email response, stating that "you can submit your URL using URL Submission feature to get them recrawled faster" was another nonsense. Crawling and indexing is nothing if you are still manually blocked.

![Bing Webmaster Tools - Search Performance on 30th April 2023](/images/2023/05/Bing_Search_Performance_30-04-2023.png)

There are **2.3k** pages indexed but none of them appears in search as they are manually blocked. When you try to do your search you still got the following output:

![Bing Search on 27th April 2024 - Some results have been removed](/images/2023/05/Bing_27-04-2024_Some_results_have_been_removed.png)

> "We request you to please wait for up to 2-3 weeks for your site to be crawled indexed and serving again."

This was the last response I got from Bing Team on 29th April 2023. It looks like, independently of what I will do, I need to let it go for this period.

## Nonsense Crawl Errors

![Bing Webmaster Tools - Search Performance - 6 months Overview](/images/2023/05/Bing_Search_Performance_6m_Overview.png)

The interesting thing was to see that together with a return of my pages to the index (despite not being displayed in search), there was a sudden spike in crawl errors. Even looking into 6 months of data, I never saw such a spike and I decided to look into that as well.

There is no easy, intuitive way of exploring the crawl errors in Bing Webmaster Tools. Instead, you need to go to [**Site Explorer**](https://www.bing.com/webmasters/siteexplorer) and from **Filter by** choose one of two **URLs with Crawling Issues** option.

When I explored **dead links** there I noticed some links to `/professionals/landscape-contractors` or `/products/bathroom-faucets`.

![Bing Webmaster Tools - Site Explorer - Dead Links](/images/2023/05/Site_Explorer_dead_links.png)

Interestingly was that I never got this kind of page. My website wasn't hacked either. The date when this page was last crawled states `25 Apr 2023` which is utter nonsense unless Bing got an issue with Netlify CDN.

Apart from that, I couldn't get any more information, hence these "crawl errors", despite that are "apparently" there, if you cannot get any feedback on what they are, you cannot act upon them. **Nonsense!**

Of course, I added these links to [**Block URLs**](https://www.bing.com/webmasters/searchconfig/blockurl) to prevent them from relating to my website. This looks more like spam websites that point things to my site which shall not be a factor to penalise you in Bing Index. It looks like Bing got a big issue with that where Google is simply ignoring spam links to our websites.

---

Once I have been waiting for these "up to 2-3 weeks", I decided once review some of the links mentioned earlier starting with **Things to Avoid**.

## Review of Things to Avoid

At the beginning, we read:

> "Following the guidelines will ensure your site plays by the rules and is not found to be **spammy**, which could lead to demotion or even delisting your website from Bing search results."

I go through the page and when I reached **Help Bing understand your pages** I stopped at the **Content** paragraph that states:

> "**Content:** Websites that are thin on content, show ads or affiliate links primarily or redirect visitors away to other sites quickly tend to drop in rankings on Bing. In some cases, it may not get indexed at all. Your content should be easy to navigate, rich and engaging to the website visitor, and provide the information they seek."

My site is not content-thin and does not show ads or affiliate links. You may think that some links that I promote on the top of my Polish page are affiliate links but in reality, they are just promo links to my posts.

I am not using any shady redirects and posts are easy to navigate, rich and engaging to the website visitor. That is the main purpose of my website.

**The problem** is with Bing, as going through their **Site Explorer** I see that they are still, almost 3 years after, referring to some WordPress-specific pages that are no longer there.

My content is **created for users, not search engines**. I am trying to be unique and have my content-rich as much as possible. My images are optimised and filled with alt tags. The overall site is working with and without JavaScript and I am optimising it also with accessibility on my mind.

I am using all relevant **HTML Tags** and **Semantic markups**.

All is good here.

---

I reached the **Abuse and Examples of Things to Avoid** section.

I go through this and in my opinion, I do not violate any of the points there. The only part that brings my attention was the section **Keyword Stuffing** then I reviewed my `<head>` section of my website where I remember that I have such a thing as `<meta name="keywords"`.

None of the valuable search engines using this anymore including Bing hence decided to remove this outdated code not only from my website (that is Blacklisted by Bing) but also from all others that I am maintaining (that don't have an issue with Bing).

Apart from that **I haven't learned anything**, especially any answers suggesting why Bing Ban was applied on my site in the first place.

---

Email from Bing Support may suggest that I concentrate too much on the SEO aspect rather than content, but in my opinion, it's not the case (content is always what I am concentrating on). The problem is that Bing is still analysing websites based on technologies that have been used on them in the past and not what is currently there. Moving from WordPress to Hugo changes a lot, sadly Bing robots don't have a clue and don't tend to re-evaluate websites in that aspect very quickly. 3 years and still referring to WordPress links is a bit crazy!

I looked at the other links from the first Bing Support email but they also didn't make anything clear.

At this stage, there is nothing else that I can do but wait this 2 to 3 weeks as suggested. In the meantime, I will be monitoring my presence in [Bing Search](https://www.bing.com/search?q=site%3Adariusz.wieckiewicz.org) and for any responses from Support. After 3 weeks if nothing will change I will ask a question once again hoping to get some more clues as to why I have been blacklisted in the first place.

> Nicholas A. Ferrell, the editor of [The New Leaf Journal](https://thenewleafjournal.com), which is still suffering from Bing Jail, has created a helpful collection of articles about Bing Jail in his [Not-So-Awesome Bing Search Bans and De-Indexing](https://github.com/nafnlj/not-awesome-bing-bans-and-deindexing) GitHub repository. It is worth taking a look.


---
## Bing Jail
- **URL:** https://dariusz.wieckiewicz.org/en/bing-jail/
- **Date:** 2023-04-23
- **Tags:** Bing, Microsoft, penalized, secret blacklisting, Shadow banning, duckduckgo, Bing Support, Bing Search, Bing Webmaster Guidelines, Google Search Console, splog, Spam Blog, SEO, Site Scan, WebDev, Indexed Pages, Crawl

### Content

My personal site has been recently penalized by Bing, or if you prefer different naming for it - **secretly blacklisted** or **shadowbanned**. Don't know exactly why but by the end of January 2023 I lost every indexed page that had been in Bing.

<!--more-->

![My website Bing Search Performance over last 6 months](/images/2023/04/Bing_Search_Performance_DW_6m.png)

Why do I even bother, I asked, when I noticed that trend in February, so I left it for time being.

I do not use Bing, I don't like Bing, however, I use some other search engines that rely on Bing like [DuckDuckGo Search](https://duckduckgo.com/).

> Because of that, when you use the search on my website, if the result were not as expected I suggested a link to search it through DuckDuckGo. Until the issue is sorted I have been forced to change it back to Google.

Firstly, don't bother contacting Bing Support. This **support is simply non-existent**. Nobody will reply to your emails, and nobody will care unless you are heavy paying customer.

> Hey Bing Team. If you want to follow up, my most recent request is **‌REQ00056361**.

There is plenty of forum posts with similar experiences like the [recent one](https://techcommunity.microsoft.com/t5/microsoft-bing/discovered-but-not-crawled-url-cannot-appear-on-bing/m-p/3802346/highlight/true#M2738) in which I decided to participate.

When I don't care too much about Bing Search I am angry because of my lack of site presence on DuckDuckGo.

I started reading various things, and **yes**, I went through Bing Webmaster Guidelines. If you know my site a bit more you may see that is perfectly optimised and all requirements have been met so that wasn't the issue.

Just been thinking that the content of my website is what somebody in Microsoft disliked and decided to ban me behind the scene without acknowledging it.

> It looks like Microsoft is doing some shady secret blacklisting which, if happens to some company with a budget to spare, would finish in a lawsuit. With a niche website like mine, they can sleep without worrying and the support can keep ignoring me.

I got some articles about Microsoft and Windows but all are legit and none of them relates to piracy. **So why?**

The question is **Why have I been thinking that somebody there does not like what I am writing and secretly blacklist my website?** *It's because none of my other websites has been affected.*

All other websites have been built with the same webmaster and SEO practices and techniques, the only difference was content, so **yes**, I am thinking that Bing and Microsoft itself doing some shady job behind scenes and discriminating websites through their search engines.

I would be very happy to have an open discussion on the reasons, but when you don't know the real reasons behind it and you don't have anybody to contact/speak with, that's just making you angry a bit more.

I decided to ask the Bing Chat bot "Why my website is not indexed in  Bing?" and here is what I get.

---

> "Your site is new and Bing hasn’t discovered and crawled it yet. With new websites, it can take Bing time to find links and crawl through to your website."

**No, that's not the case.**

> "Bing is running into issues crawling the site. If Bing consistently cannot crawl your website, it may not select it to be indexed."

No crawling issues were reported, nada.

> "No links are pointing to your website. A common problem for new websites is the lack of links pointing to them from other places on the web. Such links help Bing discover your content and tell us about the popularity of your web pages."

Google know how many links are there and how popular the website is. When importing my website into Bing Webmaster Tools I used direct import from Google Search Console hence that shall confirm the thing that indeed there are links and some are quite popular.

> "You can check if any of these issues apply to your website and take appropriate actions to resolve them. You can also use Bing Webmaster Tools to get more insights into why your website is not being indexed."

It will be nice if I will see any issues. The text "use Bing Webmaster Tools to get more insights into why your website is not being indexed" just angers me even more. **What insights!?**

I am not alone, there is plenty of users reporting the same problems without any support from Microsoft and the Bing team.

---

You may ask what issues are reported when trying to do URL Inspection from Webmaster Tools. The information is very vague.

![Bing Webmaster Tools - URL Inspection through Bing Index](/images/2023/04/Bing_Discovered_but_not_crawled.png)

And that's through **Bing Index** where Live URL doesn't see anything wrong.

![Bing Webmaster Tools - URL Inspection through Live URL](/images/2023/04/URL_can_be_indexed_by_Bing.png)

I, of course, clicked the **Request indexing** button, the same as I am doing when I am publishing any new content.

I even removed my website from Webmaster Tools and re-added it back again, on 21st April, but for the effect on that, I will need to wait (if there will be any).

An interesting fact is that my website is really in a subdomain (`dariusz.`) of my main domain (`wieckiewicz.org`), very similar to my daughter (`anna.`) whose website was not penalized by Bing.

When I started messing with Webmaster Tools by removing my website and re-adding it again, I reminded myself that a couple of years ago Google tend to suggest adding to their Search Console any domains and variations that we got control of. So on 22nd April 2023, I added the main domain (`wieckiewicz.org`) as well. Through this, I added sitemaps to my website (in the subdomain) and my daughter's to see if anything will change. It will be nonsense if I will but let's try.

At the stage when I added the domain and verified ownership through the CNAME DNS setting on the homepage of Bing Webmaster Tools I noticed a chart for Search Performance. As this (in theory) is a newly added site there is no graph showing, however, there were some figures on top of it that makes no sense and I started thinking.

![Bing Search Performance for domain wieckiewicz.org](/images/2023/04/Bing_Search_Performance_wieckiewicz_org.png)

The headings of the flat graph showed **Indexed pages** at the value of **1.8K**. That's a bit nonsense, as firstly, there is no website on my main domain and my daughter got only 123 pages. This starts looking like the figures from my website. When started playing with the date range switch noticed that these figures are most likely for indexed pages that were months ago, hence not very accurate.

I decided to wait a couple of days to see if the graph will update and if anything changed.

> If in fact, something changed in Bing requirements around January (we know about their core update in mid-Jan.), it would be nice if their Webmaster guidelines would at least mention this somehow.

I keep investigating others' experiences in that matter, like [Dave](https://daverupert.com/), who shared a couple of posts about this issue.

Dave took some [steps](https://daverupert.com/2023/01/updates-on-my-bing-ban/) to help him back on track with Bing, which I also followed before I even discovered his website.

He [solved](https://daverupert.com/2023/02/solved-the-case-of-the-bing-ban-theory/) his issue. I decided to follow his lead and complain publically and blog about it as well, hence this text here.

---

I learned new terminology today, which was "splog". Somehow Bing robots most likely classed my site like that which means "Spam Blog". **Total nonsense!**

Seriously, I would appreciate it if somebody at Bing would go through my website and explain to me how I am called a Spam Blog.

Apart from sending a most recent request (REQ00056361) to Bing Webmaster Support Team, there is nothing that I can do about it.

{{% ads-in-article %}}

---

Dave mentioned some crawling issues and SEO errors reported and I decided to look at mines as well. I run a full **Site Scan** from under **SEO** menu to see what this will bring.

What it brings was nothing to do with being classed as "splog", but still decided to go through them.

## Analysing Site Scan results

![Bing Site Scan Completed](/images/2023/04/Bing_Site_Scan_PL_completed.png)

- Total pages scanned: **2.6K**
- Errors: **11**
- Warnings: **277**

![Bing Site Scan Completed - Issue details](/images/2023/04/Bing_Site_Scan_PL_Issue_details.png)

### ERROR: Blocked by robots.txt

I intentionally added one block rule to my `robots.txt` file to prevent indexing links to my download files so people will get them through posts on my website and will understand more what is for than blindly downloading it from a search engine not knowing the context behind it.

There is nothing to fix here, Bing may think differently but it's all intentional.

### ERROR: Meta Description tag missing

Just two pages here with missing meta descriptions. There may be more, but concentrating on these two is an easy fix which I did straight away.

### WARNING: Title too long

**No is not!**

My titles, if they are long, are descriptive enough and in some languages they need to be, as in other cases they will just sound like clickbait titles.

I don't get why Bing still follows this **outdated recommendation** for a title length of 70 characters. This is **total nonsense**. Google and its guys confirmed over the last months that there is no limit for them for titles. If the titles are too long to display on a specified device they will simply truncate them to fit.

So... Bing... **truncate** the titles and **STOP** with this nonsense recommendation!

**Nothing to fix here.**

### WARNING: Meta Description too long or too short

239 pages. I get it, this can be fixed. It requires some work but can be done.

Off course any warnings related to an actual page I will look to fix them (add meta description), but a recommendation to fix the meta description for a specified `/tag/` is a bit excessive so **seriously Bing?**

Luckily to the templating in [Hugo](https://gohugo.io) I have been able to add meta descriptions to all tags with minimum work from myself.

### WARNING: HTML size is too long

> "Evaluated size of HTML is estimated to be over 125 KB and risks not being fully cached. Search engines may not fully acquire the content on a page if the page contains a lot of code. Extraneous code can push the content down in the page source making it harder for a search engine crawler to get to it. A soft limit of 125 KB is used for guidance to ensure all content & links are available in the page source to be cached by the crawler. This means that if the page size is too big, a search engine may not be able to get all of the content or may end up not fully caching it."

Ok, this is something that caught my attention.

As [Hugo](https://gohugo.io) is used to generate my website, I am not using any extensive additions so the pages shall be light and fast. The fact that the website shows above 125kB requires me to look a little bit deeper.

After a short investigation, the highlighted posts have plenty of images and because of that the `<picture>` tags included in the code, which contain a reference to various sizes of the image in the WebP format, cause the pure HTML file to weight a bit more than Bing soft limit.

None of the other search engines complained about that and the code is served through Netlify CDN hence I decided, weighing the pros and cons, to leave it unchanged.

**Bing, you need to deal with it that this is how it will be.**

### WARNING: Meta robots tag contains restrictive robots directives

Yes, intentionally, forget about it and move along. Just a warning that shall not be considered a problem and definitely shall not prevent the site from indexing.

### WARNING: Meta Refresh tag exists

Yes, **once again**, it's intentional, forget about it and move along.

### NOTICE: H1 tag missing

**Nothing to fix here.** Bing reported issues with files that are just meta redirects (aliases) to other pages. All other pages on my site are following this most basic SEO principle.

---

Now I will leave it and see if over the next weeks, months, **or never**, it will change. I am not expecting anybody from Bing to contact me, but if that happens and I will get any positive output will update this post.

> Nicholas A. Ferrell, the editor of [The New Leaf Journal](https://thenewleafjournal.com), which is still suffering from Bing Jail, has created a helpful collection of articles about Bing Jail in his [Not-So-Awesome Bing Search Bans and De-Indexing](https://github.com/nafnlj/not-awesome-bing-bans-and-deindexing) GitHub repository. It is worth taking a look.


---
## A simple way to improve the stability of your OpenWrt router
- **URL:** https://dariusz.wieckiewicz.org/en/simple-way-to-improve-stability-openwrt-router/
- **Date:** 2023-04-22
- **Tags:** cron, harmonogram, OpenWrt, Cache, drop_caches

### Content

Do you encounter a problem that your router slows down from time to time? Websites that usually open very quickly suddenly slow down. It's not always your internet connection's fault. Sometimes the fault lies with the router.

<!--more-->

If you are an intensive user of your Internet connection or your router is heated to red hot by your household members, after a few days you will notice that everything starts to slow down a bit.

The problem is that what a router keeps in cache doesn't always have to be there forever. In this case, the simplest method is to restart the router.

We can do it manually or enter a command in the schedule (cron), which will start on our router at a time when it is least used.

```shell
cron -e
```

Press <kbd>i</kbd> and paste the following command:

```shell
# Restart after 4:00 AM every day
30 4 * * * sleep 70 && touch /etc/banner && reboot
```

Then we press <kbd>Esc</kbd> and end with `:wq` to save our changes.

For most of you, the above command will solve the problem very quickly.

> Adding only the 'reboot' command does not always work. It happens that the router enters the so-called redirect loop, hence the 'sleep' command is first run to wait 70 seconds, then setting the current time and date in the '/etc/banner' file, and then based on it, restart the router.

However, not everyone likes this solution. If we have surveillance cameras connected to the router, each restart is a loss of recording time, especially when the cameras record directly to the cloud.

In search of an alternative, I found this command, which we add to the schedule (cron) instead of the above one.

```shell
00 4 * * * sync && echo 3 > /proc/sys/vm/drop_caches
```

Thanks to this, at 4:00 a.m. our router will empty the cache table, which significantly improves the performance of the device, without the need to restart it.

It may seem like nothing, but it helps improve the stability of our device after a hard day.

```shell
08:45:22 up 78 days,  3:13,  load average: 0.13, 0.10, 0.07
```

---

For those who are not comfortable using the terminal, the above commands can be added from the administrative panel of your router (LuCI) via the **System** > **Scheduled Tasks** menu.

By pasting the above commands and saving the changes with the **Save** button, we will add them to our schedule (cron).

---

Regards.

{{% ads-in-article %}}


---
## Another (free) approach to Windows 11 on Mac with Apple Silicon - VMware Fusion 13
- **URL:** https://dariusz.wieckiewicz.org/en/windows-11-mac-apple-silicon-vmware-fusion-13-free/
- **Date:** 2023-04-21
- **Tags:** Windows 11, Windows 11 ARM, Windows 11 arm64, VMware Fusion, VMware Fusion Free, VMware Fusion 13, Fusion Player, Fusion Personal Use License, Apple Mac M1, macOS, UUP Dump, virtualization, VMware Tools, Windows Update, Microsoft Store, Windows 11 22000, Windows 11 21H2, Windows 11 22621, Windows 11 22H2

### Content

I used to use Parallels Desktop and with my hand on my heart, I can tell that this is one of the best software to run Windows 11 on Mac with Apple Silicon.

There is a big problem for me, however. Parallels Desktop is a bit expensive in long term. As expensive the life become recently, everybody is trying to save some pennies, even me. I cut unnecessary subscriptions by some and Parallels has been one of them (along with Bitdefender in favour of free Avira). I recalculate the use of Windows on my macOS device and the conclusion was that I am paying and not using it. 

<!--more-->

I know that from time to time I will need to head to Windows so I went into the path of using UTM for that.

As much as UTM is great and free, the performance of Windows is a bit poor. Struggles with updates and missing functions put me a little behind. I always want to try something new. Between Parallels and UTM there was always VMware Fusion however I never spend too much time trying it in full.

> Recently VMware Fusion 13 gained official support for Windows on Macs with Apple Silicon.

After the recent update of my Installation of Windows 11 using UTM with Windows 11 Version 22H2 (22621.674), I returned to the problem of missing Microsoft Store and decided to give up for a bit until I found a post [How to install Windows 11 on Apple Silicon Macs with free VMware Fusion Player](https://9to5mac.com/2023/04/14/how-to-install-windows-11-apple-silicon-mac-free-vmware-fusion-player-13-video/) in my Feedly reading list. What appealed to me was the mention of the fact that the application includes a free personal license option. Interesting!

I decided once again to give it a try. The last time I tried (in beta) it wasn't straight forward and I went with UTM. Let's see if following the guide from [9to5mac](https://9to5mac.com) I will be able to get Windows 11 with decent working performance and support for Microsoft Store.

> If you want to know how to generate Windows 11 ISO file (ARM) without the need of installing Parallels Desktop like mentioned in the 9to5mac article, see my post [Installing Windows 11 on macOS](/en/installing-windows-11-macos-apple-mac-m1-utm/)

## Installing VMware Fusion

I followed [step 1](https://9to5mac.com/2023/04/14/how-to-install-windows-11-apple-silicon-mac-free-vmware-fusion-player-13-video/) and visited [VMware Fusion Player 13 page](https://customerconnect.vmware.com/en/evalcenter?p=fusion-player-personal-13) where I logged on my account (if you don't have, create one) and then [registered for a personal account](https://customerconnect.vmware.com/en/evalcenter?p=fusion-player-personal-13) to get the licence.

---

All sounded great but there was one problem. Despite that site state as below:

> "Fusion Player offers a Personal Use License, available for free with a valid CustomerConnect account. Home users, Open Source contributors, students, and anyone else can use Fusion Player Free for Non-Commercial activity."

Each time when I try to register for this product to get a licence I was asked to fill in the **Tell Us About Your Company** section which was a bit nonsense. I am trying to get this for personal use hence there is no **Company** to fill. Even during the creation of a new account I come against this hurdle.

Following the suggestion from the post [Registering personal product requires company name and phone number](https://communities.vmware.com/t5/VMware-Fusion-Discussions/Registering-personal-product-requires-company-name-and-phone/td-p/2827690) I put my name into the company field and the rest as **other** or anything that doesn't match. I finished by clicking the **Start Trial** button despite that I am not starting any trial!?

Thanks to that I received my Personal Licence key and the option to download software.

Once the software has been downloaded, installed and typed the licence on the first run, just after confirmation of EULA. Then I looked back to the step of installation from 9to5mac.

## Installing Windows 11 (22H2)

From the window where we read **Select the Installation Method** press the button stating **Install from disc or image**.

![VMware Fusion 13 on macOS - Select the Installation Method](/images/2023/04/Select_the_Installation_Method.png)

In the next stage drop the ISO image (`22621.674_MULTI_ARM64_EN-GB.ISO`) and press continue.

> **Spoiler Alert**: read further but do not proceed with installation from the 22H2 (22621.674) version. At a later stage will explain why.

![VMware Fusion 13 on macOS - Choose Encryption - TPM](/images/2023/04/Choose_Encryption.png)

Because Windows 11 require to use of TPM even in a virtual environment, on stage **Choose Encryption** I need to type my encryption password. 

I was a bit lazy and chose the option **Auto Generate Password** with the tick **Remember Password and store it in Mac's Keychain**, which does not happen for some reason so I saved it into my notes just in case.

> You may be asked at some point to enter this password so worth to have this saved as without it you cannot regain access to the virtual machine.

![VMware Fusion 13 on macOS - Final setuo step](/images/2023/04/VMware_Fusion_Final_setup_step.png)

In the last step, I just customised a couple of things using **Customize Settings**, like storage, which I changed from the default 64GB to 128 GB (**do that as well**).

Once that is done pressed the big play button to start the machine.

And so on I followed step-by-step instructions to install the system.

> When asked to enter Windows 11 licence key I chose "I don't have a product key" and on the next screen, depending on what licence key we have, selected **Windows 11 Core** or **Windows 11 Pro**. When on further screen I selected **Customised: Install Windows only (advanced)** from **Which type of installation do you want?**

---

After the first restart, as warned in step [Configure Windows 11, install network and display drivers](https://9to5mac.com/2023/04/14/how-to-install-windows-11-apple-silicon-mac-free-vmware-fusion-player-13-video/), we need to do some adjustments to get through the initial setup and later add drivers through VMware tools.

> Windows 11 require a network connection to get through the installation process and by default there are no Network drivers available in Windows 11 for the VMware environment.

On the screen **Is this the right country or region?** press <kbd>Shift</kbd>+<kbd>fn</kbd>+<kbd>F1</kbd> to get to the terminal where you need to type the command `OOBE\BYPASSNRO`. Once we hit Enter the installation will restart and we will be able to **Continue with limited setup**, without the internet connection and need to connect to Microsoft Account at that stage.

---

Once (almost) all done and once we will see our Windows 11 desktop, straight away I noticed **the lack of availability of Microsoft Store**, exactly as it was in UTM.

That makes me think, maybe the image that I have been using in my previous UTM approach and here is wrong.

Looking back into the 9to5mac post, when they download ISO through Parallels they get version `22621.525`. I used `22621.674` from the UUP dump. Then, I looked closely at their screenshots. In their taskbar, **there was no Microsoft Store icon either**.

> I tried with `22621.525` as well with the same result.

The last know version of Windows 11 ARM with working Microsoft Store on UTM straight after installation was [**Windows 11 21H2**](https://uupdump.net/known.php?q=22000.1098) so I decided to install it and see if I can upgrade to 22H2. With working TPM emulation on VMware Fusion (and increased default storage to 128GB), this shall not be a problem, at least in theory.

## Starting with Windows 11 (21H1)

![VMware Fusion 13 on macOS - Create a new Virtual Machine](/images/2023/04/Create_a_new_Virtual_Machine.png)

I have installed `Windows 11 21H2`, but before I head to upgrade I need to install the missing network and display drivers.

To do that I need to install **VMware tools**.

> VMware Tools is installed through PowerShell.

Before VMware Tools can be run in the system we need to allow PowerShell to run `RemoteSigned` scripts.

> Open **Start Menu**, type **PowerShell**, hover over the result and from the right part of the Menu Start choose **Run as administrator**.

```
Set-ExecutionPolicy RemoteSigned
```

Confirm the above PowerShell command with option <kbd>A</kbd> (Yes for All).

Once that is done, from the VMware macOS menu bar select **Virtual Machine** > **Install VMware Tools**.

> VMware Tools will mount a virtual DVD drive.

Head to your computer, click on the DVD drive and start the installation by right-clicking on the **setup** file select **Run with PowerShell**. Confirm any further prompt and wait until it finishes.

> During the installation, the screen can go black.

Once the PowerShell window closes reboot your system and we shall be able to see the internet connection.

---

Before I proceed any further I activated my Windows with my licence.

As mentioned in my post [Trying Parallels Desktop alternative - UTM](/en/parallels-desktop-alternative-utm/), despite having a Microsoft Store icon in the system, there was no possibility to run it, as each time the app crashed. Running `wsreset -i` from PowerShell didn't help much.

At that time the solution was to enrol on the Insider program to get this sorted but this time I will **not be doing that**.

I head to **Windows Updates** and installed what was there.

I re-run **twice** my `wsreset -i` command and **Microsoft Store** was back and operational. Then I head to the **Library** and select the **Get updates** button followed by **Update all**. At this time Microsoft Store updates itself as well.

I returned to Windows Updated and selected **Receive updated for other Microsoft products** from **Advanced options**. After heading back to Windows Update I re-check what's available and let it update itself.

## Update to Windows 11 (22H2)

![VMware Fusion 13 on macOS - Windows 11 22H1 - WhyNotWin11](/images/2023/04/WhyNotWin11_VMware_Fusion_13.png)

Despite the [**WhyNotWin11**](https://github.com/rcmaehl/WhyNotWin11) showing only in red issue with DirectX and in orange processor compatibility, we got **TPM 2.0** and **Secure Boot** sorted! This shall allow us to do an update from 21H2 to 22H2. Let's see if that's the case. 

Firstly, I update all that was available via Windows Updates and see if a prompt to upgrade to 22H2 appears. Sometimes it takes time before this will appear, but I don't want to wait and decided to speed things up.

I downloaded and generated [ISO for 22621.674 from the UUP Dump website](https://uupdump.net/known.php?q=22621.674).

I mounted ISO as a virtual DVD drive inside VMware and started by just double-clocking `setup.exe` and following onscreen instructions.

No errors or incompatibility were reported at that point and the installer started **Getting updated** before installation can commence, followed by **Ready to install** screen.

![VMware Fusion 13 on macOS - Windows 11 (22H2) Ready to install - Update](/images/2023/04/Windows_11_Setup_Ready_to_install.png)

**Let's go then...**

After a short while and reboot all have been installed and see the **Hi** screen and **This may take a few minutes**.

In the end, I **successfully** finished with **Windows 11 (22H2)** and **Microsoft Store**! Not to mention that there is **no issue with updating** to the latest Windows, hence that a huge... and **free**.

> Final step that I did was a bit of cleanup using the **Disk Clean-up** utility to remove the remains of 21H2 (**25.4GB!**).

{{% ads-in-article %}}

## What's not working as expected with VMware Fusion

From the start, I noticed that VMware Fusion **does not offer a shared clipboard** between macOS and the virtual environment. Copying some of the commands has been a bit of a pain as need to retype them.

UTM, thanks to its Spice Tools, offers also **a shared directory between systems**. Thanks to that you can access the macOS file system from inside the virtual environment. VMware, even after installing VMware Tools **didn't offer either of that**.

From the [forum post](https://communities.vmware.com/t5/VMware-Fusion-Discussions/Fusion-13-Where-is-the-setting-for-Shared-Folders/td-p/2946216) that I found we can read:

> "Fusion folder sharing is not yet supported for Windows 11 ARM virtual machines. We hope that VMware will fix this sooner rather than later by releasing a full VMware Tools implementation for Windows 11 ARM."

> "Workarounds are to configure Windows file sharing on the macOS host and access it like you would any other SMB file share, use a cloud file sync app in both host and guest such as OneDrive or DropBox, or use an SCP client such as WinSCP to transfer files back and forth between host and guest."

Despite that VMware Fusion installing its graphics drivers with VMware Tools, there is no dynamic resolution of the operating system. When you will put a window on full screen or you go to full-screen, the content does not adapt to the resolution/size and sticks with 1024x768. Luckily, **we can switch to 2560x1600 that match my Mac's default resolution**.

To correct the sizes of the windows I also switched **Change the size of text, apps and other items** to **175%**. All start looking much better now.

In theory, the windows (resolution of the virtual system) shall change dynamically to adapt to the Window size, but it doesn't work like that or I misunderstand how it is working in VMware compared to UTM and Parallels Desktop.

There may be other things that may not work as expected but the above are the ones that I noticed straight away.

The advantage to VMware Fusion is however an option for **making Snapshots**. I like this in Parallels Desktop and missed it in UTM.

> Once I updated my system and set everything I created a snapshot straight away, so I can do a mess in the system and if something does not go as planned can go back in no time.

Be aware that despite Windows 11 after installation using only 11GB, after upgrading to 22H2 and with snapshots turned on our Virtual image can grow to over 70GB! You can do cleanup inside Windows using the **Disk Clean-up** utility, but later, from VMware Settings you will still need to reclaim unused space. To do that, however, the VMware will require extra space (likely double of the current size). If you will try to reclaim space and you will lack free space your virtual machine may become corrupted.

> After cleanup and reclaiming my Windows 11 (22H2) inside VMware Fusion used only a little over 17GB.

There is another thing that I like about this app. Under the Virtual Machine menu, **there is an option to restart it**. This brings me **'90s nostalgia** when computers tend to have a physical reset button. You pick this option from the menu and **boom!** - **instant reset** (restart) like it used to be. The reset button never cares if the system is writing something or not, almost like pulling the plug from the socket :)

---

VMware may miss some functions (which I hope will re-appear in further versions) but it's great to see having **free** (**for personal use**) alternative to Parallels Desktop along with UTM. I will give VMware Fusion a go for now and see if it will stick permanently (at least for my not so **professional** needs).

## Microsoft Store on ARM64

A quick addition to missing Microsoft Store.

Open PowerShell or Terminal as an Administrator and type:

```powershell
iwr -useb https://raw.githubusercontent.com/DaBigBlob/ms-store-arm64/main/allowARMv2.ps1|iex
wsreset -i
```

> Read more: [Microsoft Store on ARM64 (for UTM)](https://dabigblob.github.io/ms-store-arm64/)

Patiently wait and the Store Experience Host installs in the background. You may have some notifications about that pop-up in the right bottom corner or some hanging-in notifications (when clicked on the clock in the right bottom corner).


---
## There is no such thing as a "lifetime"
- **URL:** https://dariusz.wieckiewicz.org/en/there-is-no-such-thing-as-a-lifetime/
- **Date:** 2023-04-10
- **Tags:** lifetime, lifespam, subscription, subscriptions, warranty

### Content

Do you know there is no such thing as a lifetime? I am not talking here about human life but a lifetime of material things, like a subscription to a service or even a warranty.

<!--more-->

Many companies offer us a deal of a lifetime subscription to their service or brag about their products with a lifetime warranty. Sometimes it sounds generous but the devil is in the details.

The problem is that a lifetime doesn’t always mean what we think it is. A lifetime doesn’t mean forever, but more likely a life of service, or even the company, which can go out of business even the next day.

The most prominent lie began a couple of years ago from TomTom, who offers lifetime map updates, which people think will be forever, to discover later, it’s a lifetime until the device is offered on a market (or supported). After the device stopped being supported there were no more map updates and we were forced to buy a new device with the same or a bit redefined promise.

Total nonsense, but if you look at the lifetime offerings, from the business point of view doesn’t make sense. How it shall make? The lifetime offering pays (earns) one time only and does not pay for future bills and employees' wages. Lifetime is only for getting a one-time cash injection for struggling businesses, but what about the future?

Companies that build devices that last for ages go quickly out of business. People not buying new devices as current ones are fine. If they not breaking and companies not offering service plans, there is no chance of long-term survival. It’s like a lifetime offering, an injection of cash today without a chance to survive the tough future ahead.

It is no surprise that currently, new creations last a limited amount of time so we will be forced to buy new ones. Without going into the IT industry with this though, where technology changes rapidly and the need for an upgrade is obvious, there are things like, for example, furniture.

You will notice that old wood tables will last 20 years, when handled properly, whereas these freshly purchased from a cheap shop will be a useless couple of years.

But even the IT industry is offering us lifetime deals, but that’s another nonsense here. For example lifetime VPN subscription will just work as intended for a year or two whereas later on, you will discover that it got some limits applied, countries reduced, and if you want something more, you will need to pay again.

The perfect example is FastestVPN which lifetime subscription I received when I purchased a bundle of apps, from which I just wanted one at that time, so getting something that will offer me “lifetime” service was good. When finally I need to use it, I found out that things changed and are not as they were. A joy of "lifetime" offerings.

I understand the business behind it, but it’s better to offer a licence for the specified version of the software and when a new will be released, offer paid upgrade, than offer something for a lifetime until the customer discovers that is conned. If I will purchase the FastestVPN lifetime licence intentionally, now I will be very annoyed. After being conned I would never trust that company again.

I am not a fan of subscriptions. Some of them make sense, but others don’t. Like for example Adobe Photoshop and other Adobe software.

Removal of the ability to purchase software with a licence in favour of a monthly subscription was total nonsense for customers. The new approach implements better control over the software but some customers not using it often so they cannot afford to pay monthly. In that case, a one-time purchase would be much better with a paid option to upgrade when needed.

But this one-time purchase, if not done correctly will sound like another lifetime deal unless things change. Like OS updates that braking compatibility with “old” software. The blame game continues. One company will say that it will work for a lifetime with Operating system X, but when system Y will be released, you need to purchase again, an upgrade, to get it working well.

Same as a like change in architecture, from Intel to Apple Silicon, brakes some software when people tried to install them on the newest machines they need to think about purchasing a "compatible" version.

Nothing lasts forever, and not a lifetime, at least not our lifetime.

Next time you will hear about a lifetime deal, please think again.

{{% ads-in-article %}}


---
## I kept (reading) listening...
- **URL:** https://dariusz.wieckiewicz.org/en/i-kept-listening/
- **Date:** 2023-04-04
- **Tags:** Audiobook, Leaders Eat Last, reading experience, listening experience, narrator, Simon Sinek, Apple Books, multitasking, narrator voice, the voice matter, mediocrity, excellence

### Content

I used to use podcasts. Wherever I walk a dog or beat the traffic on my way to, and back from, work, I like to listen to something that I like. When recently I cleared my list of saved podcasts I feel emptiness.

Most of the podcasts are from Simon Sinek and his series "A bit of optimism". When I finished past episodes I was searching to feel that space.

The series didn't finish. The new episodes are still released and available in the UK almost each Wednesday, but once played, there is still something that I want to listen further before the next one.

I tried some other podcasts but I didn’t stick with them. Tried some of Hal Elrod but then I found that some of his views are not aligned with mine and stopped.

Once again I reached for a book.

<!--more-->

This time was **Leaders Eat Last**[^1] by... Simon Sinek.

Knowing that is read by an author I knew that I will like it... until the foreword.

> Post Scriptum at the beginning - this is not a book review.

## The Foreword

The foreword in this book is read by somebody else. 

At first, it didn’t stick with me but I knew that the book need to be read by Simon, at least at a later stage. After a while of listening to the foreword, I understand why this is as it is. It is difficult and will sound strange if Simon would refer to himself in the third person ("In this book Simon Sinek will...").  This would sound odd.

And then the book begins...

## Narrators voice

At this stage, I understood how important it is who is narrating the book. 

Simon's voice sounds appealing to me and when you hear his views, they appeal to you (or not). It’s not about what he is reading (maybe not directly), the story that he is reading or the view that he is spreading. It’s about how you feel hearing the story in his voice.

Without a doubt, Simon got the voice that is building you up from the inside (inspiring). Is like he said, that he feels much better when somebody will come to him and will say that he feels inspired rather than hearing a typical praising voice, that “it was great, I like it”. 

We feel great, and when he knew that, he feel great that we felt inspired!

From just this book I understand how much a tone of voice and passion can change everything.

Computer-generated voice and books read by it will not bring this split-second experience that will last.

I have an opportunity to choose some audio-based LinkedIn Learning courses. On one of them, I get a computer-read (synthesised) course. Despite that, the topic and the content of the course were good but the experience and feel sounded **fake**. I didn’t go through it as I simply can’t stand it. It’s the same with some of the video courses. Some people's voices are simply not meant to be for this, others shall. 

## Our voice

We cannot choose our voice, but we can work on it.

It’s like Rene Richie who, in one of his videos admit, that he, in the past, couldn’t stand himself. The way he talks and presents weren't great for getting attention and **retention**. He didn’t give up but worked hard to get better. Not everybody would like his voice, but some, including myself, will handle it. Some voices, like Simon's, can stand every single day, but like Rene, I would like only from time to time. There is something with it.

I speak two languages. My voice is different in both, and I can't stand listening to myself from the recording. I need to work on this to the level of acceptance myself so I will know that others may do the same.

## Bringing mediocrity to excellence

After a while, in the second book, I realised that Simon could read the most boring (or not), content-rich legislative document like the constitution or human rights law document and we will feel inspired.

The way how things are presented matters.

If Martin Luter King would come with his famous "I have a dream" speech with a synthesised (sound fake) voice, nobody would like to listen. The voice will not touch each individual in the way how it does. Things could go in the wrong direction, but luckily they didn't.

We need more people willing to put forward things in a form that will land in our hearts and soul. So it will not sound alien but will fulfil us inside. That’s the only way when we can be better, not only as leaders but as humans overall.

Sadly, a person with an inspirational voice can go down the wrong path. From good to bad, things can change quickly.

It's like in the book "Start with Why", when Simon narrated a story about a leader, without a small detail known at the beginning. We all assumed that he was talking about somebody remarkable, whose work we will remember and whose words, whose voice will inspire us. In the end, we have been lifted high until we were shocked and our hearts hit the ground.

When I heard that all that was told, and how was told, in a form that was told, refers to Adolf Hitler, I was concerned.

How easily the inspirational voice and the way how it's presented can describe something horrible in a remarkable positive form.

I understand how little (how much) is needed to inspire leaders and extremists in the same way.

The radicals know the word "love" and how to use it for their gain. "Love" can do a lot of good but can also be used as a tool for bad, like everything.

{{% ads-in-article %}}

## The book

I am not here to give you a book review but I can tell, that when you read it you will start thinking differently. The things highlighted, quoted and presented will start making sense. You will start thinking deeper about the organisation that you work in. You will start noticing the problems, resulting in your job being just "fine" (and not an "I love my job" feeling). It will highlight the things that make you feel about your work differently.

It was until chapter 24 (The Abstract Generation) that the high was reached. When Simons refers back to millennials, multitasking and ADHD.

Till then I always thought about multitasking as something positive, that exists, but (reading) listening about it as juggling with our mind between tasks rather than doing real multitasking (two or more things at once).

I started feeling that he got right. There is no **real multitasking** and that the **multitasking doesn't exist**, or at least does not exist in the way how we think about it.

Off course, we multitask in our life. We can drive a car, concentrate on the road and at the same time listen to an audiobook and process the knowledge read (listened). It's not we, who are multitasking, it's our brain. Even in this example, it's not fully true.

There are days when I can drive peacefully to work and listen to a book and days when I met idiots on the road which raises my annoyance at the people and causes a distraction. In such a situation, I am unable to process things in the same way. I cannot concentrate on the book and most of the time I need to rewind or pause and come back to it when I am mentally ready for that. 

We got only two pairs of hands and we cannot do the job that requires three pairs. We can juggle between tasks and in the end, do all of them, but that's not multitasking, that juggling.

Throughout my life, I am taking notes, and making to-do lists, so I will not forget what needs to be done. Too many times something or someone will distract me and I need a bit of time to come back on track with what I have been doing a couple of minutes ago. If we were capable of doing real multitasking, this small distraction would not make a difference. In such a scenario we would need to behave more like machines and less like humans.

When we drive a car, our car camera system can process more information on the road than we can. We just need to concentrate on the point, the size of a coin, to drive safely.

We are humans with limited abilities to do things. We may, through practice, do things quicker and better, but we need to know that we cannot multitask.

> It's like this - if I did a job in 15 minutes rather than 2 hours you still owe me for 2 hours, as I spend years learning things that take 2 hours, to do them in 15 minutes. Knowledge cost and for knowledge we need to pay.

Imagine that you are cutting a piece of wood and vigorously chatting with your friend. Through distractive chat, we rather risking of hurting ourselves than do things correctly. We need to put our attention on one thing or another, but we cannot concentrate fully on two things at once.

You may agree with the fact that **multitasking doesn't exist** or you can strongly oppose it. People are different. There are more neurodiverse people around the world and their minds work differently, but that doesn't change the fact, backed by brain researchers, that **true multitasking doesn't exist**. Think about it. The fact that you can do three things at the same time and complete them all together means as little that you managed to do multiple things together, but you haven't multitasked (do all three things at once). You just juggled between tasks until all of them are completed. Sometimes it's working, other times it's not. If you are good at doing multiple things at once (and somehow complete all of them) but are easily distracted by things around you, the whole perception of "multitasking" falls short.

> "We are not doing two things at once, rather what we are doing is mental juggling, or rapid toggling between tasks".

If you will look into multitasking from the perspective of the above statement from the book, you will start getting it.

The book is another piece of work to inspire us. You cannot say things about this book, you need to read it or listen to it like I did this time.

[^1]: [Simon Sinek - Leaders Eat Last @ Amazon](https://amzn.eu/d/dz2G7eI)


---
## Serving GZIP compressed Favicon with Netlify
- **URL:** https://dariusz.wieckiewicz.org/en/serving-gzip-compressed-favicon-with-netlify/
- **Date:** 2023-03-27
- **Tags:** GZIP, Favicon, Netlify, Content encoding, Compression, uncompressed, Performance Optimization, Compress Transfer, Optimization, WebPageTest, WebPerformance Report, Hugo, WebPerf, WebDev

### Content

Recently I have been annoyed when my weekly [WebPerformance Report](https://webperformancereport.com) email from WebPageTest shows a failure on Compress Transfer.

![WebPageTest Optimiation Summary - Compress Transfer - Result D](/images/2023/03/WebPageTest_Optimization_Summary_Compress_Transfer_D.png)

This failure, reported in **red** was done by just one small file... `favicon.ico`.

<!--more-->

Favicon in ICO format is the only one of a couple used on my, and other, Hugo-based static websites. It's not served first, as SVG and PNG are there as well, however, still WebPerformance Report uses it as default.

As this was just an icon, I haven't bothered to do anything about this, as this does not impact anything, but, I don't like to be in red and it starts annoying me.

Doing a search I noticed, that despite the Netlify Edge network (this is where my sites are served) support Brotli, `favicon.ico` is still served in uncompressed format.

Netlify is not Apache, I cannot just add the `AddOutputFilterByType DEFLATE image/x-icon` to the `.htaccess` file so I decided to investigate it a bit more.

I found a post on the Netlify Support Forum regarding [Serving gzipped favicon.ico](https://answers.netlify.com/t/serving-gzipped-favicon-ico/21562) where the [fifth response](https://answers.netlify.com/t/serving-gzipped-favicon-ico/21562/5) put a bit of light how to achieve that.

> My `favicon.ico` file is a simple collection of prepared, compressed and optimised PNG files as I described in [Simplified way of adding a favicon to the website](/en/simplified-way-of-adding-favicon-to-website/).

I decided to compress my `favicon.ico` as a GZIP file and serve it this way.

{{% ads-in-article %}}

## GZIP Compression

To compress the file I just used single command from [The complete guide to optimize your favicon for a speedy website](https://chaurocks.com/optimize-favicon-for-speed/) by Fong-Wan Chau.

```bash
gzip -k9 favicon.ico
```

This gived me `favicon.ico.gz` file.

I changed the filename (extension) to read back as `favicon.ico`  and the original file I renamed to `favicon_uncompressed.ico` as a backup.

```bash
mv favicon.ico favicon_uncompressed.ico
mv favicon.ico.gz favicon.ico
```

My original `favicon.ico` file weight 15KB where compressed one little below 2KB, but I cannot serve GZIP-ped favicon under `.ico` extension just like that. I need to advise, for browsers, how this file shall be read. In that case I need to tell, that this file is a GZIP file that need to be decompressed before use.

From a browsers point of view, all modern browsers support GZIP compression and can read and display `favicon.ico` correctly even if served GZIP compressed. To do that with Netlify I just need to advise that my file is compressed by specifying the content encoding.

## Content encoding

To advise that our `favicon.ico` is in fact GZIP compressed file we just need to add an information into `_headers` file. On websites built with [Hugo](https://gohugo.io) this file is saved inside the `static` folder.

```
/favicon.ico
  Content-Encoding: gzip
```

When our site is build, Netlify will read this file and add relevant headers to it.

The simple addition of the content encoding information will let browsers know what type of file they are dealing with and when visiting [favicon.ico](/favicon.ico) the browsers will do what they are intended to. They decompress the file and serve it as an ordinary icon by displaying its preview.

This simple approach put me back on the green in [WebPageTest results](https://www.webpagetest.org/).

![WebPageTest Optimiation Summary - Compress Transfer - Result A](/images/2023/03/WebPageTest_Optimization_Summary_Compress_Transfer_A.png)

Achieved what I want, job done!

😏


---
## Firewall for iPhone, iPad and Mac - Lockdown Privacy
- **URL:** https://dariusz.wieckiewicz.org/en/firewall-iphone-ipad-mac-lockdown-privacy/
- **Date:** 2023-02-18
- **Tags:** Mac, AdBlock Plus, Block trackers, Block ads, Block badware, Firewall, iPad, iPadOS, iPhone, iOS, Lockdown, Lockdown Privacy, Open Source, Mac, macOS, Safari, Secure Tunnel, VPN

### Content

If you follow my page, you've probably already come across my post [Blocking Ads in Safari on iOS, iPadOS and macOS](/en/blocking-ads-safari-ios-ipados-macos/). In it, I described how to use the built-in Firefox Focus feature to block trackers and ads without unnecessary configuration.

This method won't work for everyone. Others may opt for [AdBlock Plus](https://apps.apple.com/us/app/adblock-plus-for-safari-abp/id1028871868), which can be set to block ads in Safari similarly to the method described using Firefox Focus. Daily I use Firefox Focus and AdBlock Plus in my Safari browser on my phone.

No matter what you choose, every solution is good with one **but…**

<!--more-->

The above blocking is based strictly on the Safari browser. What if someone is using a different browser?

While pure Firefox is equipped with appropriate tools by default, just like mobile Microsoft Edge (equipped with AdBlock Plus), blocking ads and trackers outside the browser, in various types of applications, becomes a problem.

Some time ago I got hooked on the **Woody 99 - Sudoku Block Puzzle** app. While its simplicity allows you to relax and exercise your brain, if you lose (sooner or later), the full-screen few-second ads you're forced to get a bit annoying. I understand that the developers of applications, especially free ones, earn money for their hard work in this way. Some ads however drive you crazy when you are unable to close them because the **(X)** close button refuses to work.

My son recently discovered the **Alphabet Lore** games. The biggest problem with these games are ads. Not without reason, the applications from these series get amazingly poor ratings close to one star. Everyone's pissed, my son's pissed. The biggest problem is the difficulty in closing the ads. My autistic son has a bigger problem with it, and when he comes for help, even we as parents have a problem. The application called **Lockdown Privacy**, which runs in the background and requires no unnecessary configuration or attention, solved this problem once and for all.

Over the last few years, we couldn't do much about in-app advertising, especially on the iOS/iPadOS platform. While Android is a different pair of wellingtons, Apple's system is more closed in this matter, caring more about our security (and system stability), so blocking ads and trackers system-wide is not that easy.

## Lockdown Privacy

Fortunately, I recently came across the tool **[Lockdown Privacy](https://lockdownprivacy.com)**, which has been available on the iOS platform since July 2019, and it became famous again when it become available for macOS.

Why did I become interested in this application?

Well, because it is **free**, it offers a solution that allows you to **block trackers and ads within all applications**, as well as the fact that it is [Open Source](https://github.com/confirmedcode/Lockdown-iOS) so that anyone with a bit of programming knowledge can review how it works and verify that it doesn't track us instead.

The app offers two basic features.

[![Lockdown Privacy - the main window of the application with two basic functions - Firewall and Secure Tunnel VPN](lockdown_privacy_firewall_secure_tunnel_VPN.png)](lockdown_privacy_firewall_secure_tunnel_VPN.png)

### Secure Tunnel

Starting with the second feature is a kind of VPN (**paid**) designed to, together with the integration of a banking level of security, protect us from revealing our real location, our IP address and what we browse on the internet.

There are plenty of VPNs available. Most of them try to encourage users with the issue of security and privacy, which is currently trending. At the moment, I have several other solutions for this purpose, so I will focus on the basic, free option in the application, which is **Firewall**.

### Firewall

The main purpose of the firewall ([firewall](https://en.wikipedia.org/wiki/Firewall_(computing))), not only in this application, but also in systems such as Windows, or even those built into our home router, is to block potential attacks. The purpose of the **Firewall** in the **Lockdown Privacy** application is to _"block persistent and dangerous connections in all applications"_ on your phone or tablet - in other words, any trackers and advertisements that may interfere with our privacy.

We don't need to configure too much here. When you start the application for the first time, you will be asked if you want to create an account in the application. **This is an optional step.**

[![Lockdown Privacy - First Run on iOS - Sign Up or Login](lockdown_privacy_first_run_ios.png)](lockdown_privacy_first_run_ios.png)

By selecting **Sign Up** on the next screen, we will have a **Skip** option in the upper right corner. At a later stage, we can decide whether we want to create an account or not.

After that, a short tutorial will explain to us what the different elements are for. We, on the other hand, must press one main button in the **Firewall** section and confirm that we have read the application's privacy policy. 

[![Lockdown Privacy - First screen after activating the firewall](locakdown_privacy_firewall_fist_activation.png)](locakdown_privacy_firewall_fist_activation.png)

The application will inform us that blocking takes place 100% on our device and that no data is collected and transferred to any external entities.

Looking at the number of positive reviews by reputable sites like [MacRumors](https://www.macrumors.com/2019/07/24/lockdown-firewall-app-privacy-protection/), [9TO5Mac](https://9to5mac.com/2019/07/24/lockdown-ios-firewall-open-source/) or [Cult of Mac](https://www.cultofmac.com/640998/lockdown-open-source-ios-firewall/), I won't argue with that.

When using the application for the first time, we will be asked for permission to **create a VPN profile**. However, it is not a VPN like Secure Tunnel. Its purpose is to create a local connection with our application, through which all connections will pass and will be filtered by built-in rules.

[![Lockdown Privacy - Lockdown would like to Add VPN Configurations](locakdown_privacy_add_VPN_configuration.png)](locakdown_privacy_add_VPN_configuration.png)

After successfully activating the **Firewall** module, we will be asked if we are interested in also enabling **Secure Tunnel** (described above). If so, we can activate (or not) a trial period for a week. Since I focus on the **Firewall** option, I chose the **Skip Trial**.

[![Lockdown Privacy - Firewall Activated - Question about a trial of Secure Tunnel VPN](lockdown_privacy_firewall_activated_trial_question.png)](lockdown_privacy_firewall_activated_trial_question.png)

And so, without unnecessary configuration, everything is active and working, and most importantly, it works in the background.

For those who want to check to be sure, we can go to **Settings** > **VPN** and then click on the **(i)** icon next to **Lockdown Configuration**. There we will see information that our server is running at the local address 127.0.0.1 and the time since the connection.

[![Lockdown Privacy - Active VPN connection](lockdown_privacy_active_vpn_connection.png)](lockdown_privacy_active_vpn_connection.png)

It's time to see how **Firewall** performs in external applications.

For this purpose, I fired up **Woody 99** and started a game. After the first loss, when the full-screen ad should have appeared, I saw nothing but the option to start the next game.

**So in theory, it works.**

{{% ads-in-article %}}

I activated the app on my son's tablet and let him play one of the Alphabet Lore games. After a while, we noticed that the ads disappeared and with it his frustration!

I went back to the **Lockdown Privacy** app on my phone and saw that in that short time, the **Firewall** had blocked over 200 connections. **Pretty good!**

{{% gallery %}}
[![Lockdown Privacy - Firewall ON](lockdown_privacy_firewal_on.png)](lockdown_privacy_firewal_on.png)
[![Lockdown Privacy - Firewall logs](lockdown_privacy_firewal_logs.png)](lockdown_privacy_firewal_logs.png)
{{% /gallery %}}

For comparison, after half an hour on my son's tablet, this value increased to over **2 thousand** blocked connections!

Of course, not always the application will work as we want. If we have an application that uses/requires us to be connected to our Facebook account, the problem may appear at this point. Fortunately, as the application develops, the rules become smarter and some that should not be enabled are disabled at the start and it's up to us whether we want to enable them.

Another quick comparison. For a game like **Archery King**, after less than one game, **Lockdown Privacy** blocked **4 thousand (!) connections**, but the game still works.

As for the Facebook application itself, it works without any problems.

The Lockdown Privacy app works great on **macOS**, offering us exactly what it offers on iOS, even though in macOS itself, there are not as many programs based on displaying advertisements for profit.

So will **Lockdown Privacy** replace **AdBlock Plus** for us? I'm not entirely sure, although if you like, I don't mind using both.

It would be nice if the blocking did not take place on both systems using a VPN, but for now, this is the only available method to circumvent the restrictions, which is the fact that the application cannot interfere with other functions and other applications in the Apple system.

What's more, in the Lockdown Privacy application, under the **Block list**, we have additional options to modify what is and what is not blocked by default. Pretty good for an application that you get practically for free because the only paid option is a VPN tunnel (**Secure Tunnel**).

If we are satisfied with what the application offers, there is nothing else to do in the iOS application to set up an account (**Sign Up**) to receive all available benefits.

From what we can see, the project is thriving, so it can be recommended to anyone who struggles with persistent ads in free games and applications.

Regards.


---
## Publish your content in Google News on Android, iOS and news.google.com
- **URL:** https://dariusz.wieckiewicz.org/en/publish-your-content-in-google-news/
- **Date:** 2023-02-05
- **Tags:** Google News, news aggregator, RSS, RSS Feed, Atom, Atom Feed, web feed, Google, Google Publisher Center, Publisher Center, Publisher Center Help, Search Console, Google Search Console, Hugo, HTML, CSS

### Content

> Sadly, on **25 April 2025**, Google [announced](https://support.google.com/news/publisher-center/answer/14859160?sjid=2136619422920343189-EU) the following:
>
> _As of today, publishers can no longer add publications to the Publisher Centre. We are making this change as part of a transition to roll out automatically created publication pages later this year._
>
> _Publishers with manually created publication pages will continue to have access to customisation features until later this year, when pages will shift to being automatically created._
>
> I am providing the following article for reference only.

Do you have a website or blog where you publish new things, either daily or from time to time?

Do you know that you can publish them in **Google News**?

Recently, when I read one of the articles on [9to5mac](https://9to5mac.com) noticed, that after their post they got this neat feature.

[![Google News button implemented on 9to5mac website](Google_News_9to5mac_implementation.png)](Google_News_9to5mac_implementation.png)

An option to follow their site through Google News.

It gives them an additional way to get more visitors but also convinces them to stay connected with their content.

My first impression was... I want this as well on one of my websites, so I start exploring how to do that. When I did that, I have been surprised at how relatively easy it was without any extra work from myself. By utilising the website RSS Feed and going through initial configuration and approval (that took approximately 2-3 days) my first site was live and posts were updated when published.

> This is another reason to say that [RSS is not dead and it still matters](/en/why-rss-still-matters-in-2021/).

Here is how I did that and how you can do it as well!

<!--more-->

On one of my websites where I am a content moderator we are publishing [yummy recipes](https://yummyrecipes.uk) on a routine basis. We promote them on various social media platforms including [Pinterest](https://www.pinterest.co.uk/yummyrecipesuk), that is utilising the RSS feed to push the content there. So in reality, we don't need to do anything. The website reads our RSS feed and when change is detected publishes the content for us.

> I have mentioned [Pinterest](https://www.pinterest.co.uk/yummyrecipesuk/) for one reason. Through the website, RSS posts are published with the utilisation of Recipe Schema to display additional features like ingredients. However, Pinterest is a bit behind in the "right" technology (Schema) to use to get the "right" elements to be displayed. This result that only 1st ingredient is listed there despite that any other site that reads Recipe Schema can do that without an issue. This is why because the main way to get structured data into Pinterest is through [h-recipe formats](https://developers.pinterest.com/docs/rich-pins/recipe-pins/) of Schema and not the well-standardised Schema.org. I will need to have a look at that deeper in the future.

Google News is no different, but I want to get as much traction as possible from it.

Of course, I am not expecting a sudden spike in traffic (like we got from Google Discover) but any additional way (the proper way) to reach our audience is always good.

Yummy Recipes UK was my first try to get my existence in Google News. As an example, I decided to add my website and both my feeds, for the Polish and English parts of the website.

## Publisher Center

Let's head to the [Google Publisher Center](http://publishercenter.google.com) and add our publication.

Firstly we need to create an **organisation** under which we will add **publications**.

An organisation is in theory a company responsible for publications and the publications are sources of content that will be displayed. In my example I am my organisation and my Polish part of the website will be one publication and the English one will be the second one.

If you already have created an organisation, as I have for Yummy Recipes UK, you need to remember to create a new one under **Manage organisations** from the top-right menu.

[![Publisher Center - top right menu](Publishing_Center_top-tight_menu.png)](Publishing_Center_top-tight_menu.png)

Creating an organisation is only limited to putting an organisation's name.

[![Publisher Center - New organisation](Publishing_Center_New_organisation.png)](Publishing_Center_New_organisation.png)

For myself, I created an organisation under the **wieckiewicz.org** name.

When we got that we will need to add our first publication.

[![Publisher Center - Get Started by adding your publication](Publishing_Center_Get_Started_add_publication.png)](Publishing_Center_Get_Started_add_publication.png)

In **your publication's URL** I put my website's main URL `https://dariusz.wieckiewicz.org` and hit the **Add** button.

Now we need to fill the gaps in the form where we will specify **publication name**, in my instance is `Dariusz Więckiewicz 🇵🇱`, and **location**.

> As you noticed, if you reading from a non-Windows device, my publication name contains a flag emoji to have this unified with my site title. On Windows, it will be displayed as `PL`, as Windows still don't want to play with flag emojis (looks like political correctness rather than anything else).

When that's done we just need to click the tick box before we will be able to add a publication.

> _"By ticking this box, you certify that your publication is principally and permanently located in the country that you selected"_

The statement is a bit confusing. Yes, my posts on the main website (in Polish) are mainly oriented toward polish readers however they are not "permanently located" in Poland, as polish people are everywhere. The meaning of the **location** setting is, in the later part of the setup, explained as **location of your publication's headquarters**. In my instance, even for the Polish part of the publication, my headquarter is in the **United Kingdom** and to this law, I am taking greater care to obey this.

Before I start setting up publication, RSS and other options, I will add another one for the English part of my website (`https://dariusz.wieckiewicz.org/en/`)

[![Publishing Center - Add another publication](Publishing_Center_Add_another_publication.png)](Publishing_Center_Add_another_publication.png)

This time as a **publication name** I will specify `Dariusz Więckiewicz 🇬🇧` (with a British flag – on Windows it will display as `GB`) and **location**, the location of your publication's headquarters, as the United Kingdom.

Now I can move between publications from the right-top menu.

[![Publishing Center - Menu switching between publications](Publishing_Center_menu_switching_between_publications.png)](Publishing_Center_menu_switching_between_publications.png)

From the same menu, we will click the cog icon and start customising some of the settings like **primary language**, in the General tab, according to the language used on the website.

Scrolling down we need to confirm **Primary website property URL** which I will do by verifying through Google Search Console, by clicking the **Verify in Search Console** button.

[![Publishing Center - Primary website property URL](Publishing_Center_primary_website_property_URL.png)](Publishing_Center_primary_website_property_URL.png)

> If you got your website added to Google Search Console, this shall be just a one-click exercise.

The last thing that we can do (but not necessarily need to) is to provide a **point of contact for your publication** in the Contact section (General tab).

Now we can go to ‌**Visual styles** tab in settings to add your logo for publication.

I will just concentrate on adding the **Square logo**. This will allow us to easily identify our site when we will be searching for it in Google News.

> Square logo should be in PNG file format and at least 512x512 px in dimensions (recommended 1000x1000 px).

For each square logo (as it will be the same for both of my publications) I will customise it with the country flag in the bottom right corner for easy identification.

After you have done changes in each tab remember to hit the blue **save** button on the right top part of the page.

In such a way, we set the base for our publication. Now we need to add more information regarding the content that we publish and want to appear in Google News.

When we head back to our [Publication Center](https://publishercenter.google.com/) homepage in the **Explore products** section we will have the information that our **Google News** product **Not started**.

[![Publishing Center - Explore Products - Google News](Publishing_Center_Explore_Products_Google_News.png)](Publishing_Center_Explore_Products_Google_News.png)

Let's click on that then.

Now we will be configuring our website to display content in Google News.

[![Publishing Center - Google News](Publishing_Center_Google_News.png)](Publishing_Center_Google_News.png)

By clicking the blue **edit** button we will go through a couple of sections split between three tabs: **General**, **Content settings** and **Review and publish**.

Starting with category, my website fits mostly with **Science & Technology**. The distribution I leave as it is set by default for **worldwide**.

Now we can go to the **Content settings** tab where we will add **Sections** by clicking the **New section** button.

[![Publishing Center - Google News - Add section from RSS feed](Publishing_Center_Google_News_add_section_from_RSS_Feed.png)](Publishing_Center_Google_News_add_section_from_RSS_Feed.png)

Here we got a couple of options.

I will be adding my RSS Feed (**Feed**) through which my posts will be published.

> The Sections part can be used to split the website into different categories and deliver them separately. You may think about how to utilise this feature if you publish a lot. For my purpose, I will just use a single section.

Similarly to how I set my publication, I will fill **section title** as my website title (with flag-emoji).

In **RSS or Atom feed URL** I will paste the link to my feed (for PL `https://dariusz.wieckiewicz.org/index.xml`, for EN `https://dariusz.wieckiewicz.org/en/index.xml`)

> As you start thinking about it, I could utilise a single publication to serve two sections in different languages. If both publications would be in the same language that makes sense, as language is set at the publication level and not the section level. This is why I will finish with two publications and a single section in each of them.

That's all that we need to do in the **Content settings** tab.

Its time for **Review and publish**

[![Publishing Center - Google News - App publishing status](Publishing_Center_Google_News_app_publishing_status.png)](Publishing_Center_Google_News_app_publishing_status.png)

In **Google News app publishing status** we got two things that we need to review, **Content** and **Terms of Service**.

As you will see, clicking on the **review** button will bring you back to the **Content settings** tab. This is because our RSS feed needs to be refreshed by Google, which is not yet done. In the preview on the right side you will see the message **You haven't added any content to this section yet**.

[![Publishing Center - Google News - Sections - RSS Feed](Publishing_Center_Google_News_Sections_RSS_Feed.png)](Publishing_Center_Google_News_Sections_RSS_Feed.png)

In sections, you will need to hit the **refresh** button and wait patiently. Typically it is taking a couple of minutes at max to refresh it. When that's done, you will see a preview of your feed on the right side in the **Review and publish** tab, like below.

[![Publishing Center - Google News - App publishing status refreshed](Publishing_Center_Google_News_app_publishing_status_refreshed.png)](Publishing_Center_Google_News_app_publishing_status_refreshed.png)

Now we can review the terms of service.

[![Publishing Center - Google News - Terms of Service](Publishing_Center_Google_News_Terms_of_Service.png)](Publishing_Center_Google_News_Terms_of_Service.png)

There we need to read the main part and fill out the form on the right.

The **name**, **contact email** and your **title** – I typed Content creator. In the case of **organisation** is a bit tricky. If we add your own website you can safely state **None**. I set that when I set it for Yummy Recipes UK, it was approved without any problems.

When that's done, the last part will be to hit the blue **publish** button and wait, as our publication will be sent to Google for review (typically it takes up to a week).

[![Publishing Center - Google News - App publishin status ready](Publishing_Center_Google_News_app_publishing_status_ready.png)](Publishing_Center_Google_News_app_publishing_status_ready.png)

When we will head to our Publisher Center homepage we will see that our product – Google News is **in review**.

[![Publishing Center - Google News - In Review](Publishing_Center_Google_News_In_Review.png)](Publishing_Center_Google_News_In_Review.png)

Once the review is finished this status will change to **live** as below for Yummy Recipes UK.

[![Publishing Center - Google News - Live](Publishing_Center_Google_News_Live.png)](Publishing_Center_Google_News_Live.png)

If somebody will start **following** you through Google News, you will also see that there.

Let's start following ourselves, even at the stage when our publication is **in review**.

Heading once again to **Review and publish** tab we will see the section to **test your publication**.

[![Publishing Center - Test your publication](Publishing_Center_Test_your_publication.png)](Publishing_Center_Test_your_publication.png)

Let's hit the **Follow publication** button and see how it looks at [news.google.com](http://news.google.com), or through a dedicated app for [Android](https://play.google.com/store/apps/details?id=com.google.android.apps.magazines) and [iOS](https://apps.apple.com/app/google-news/id459182288).

By visiting the **Following** section we will be able to see our sites in **Sources** section.

[![Google News - Following - Sources](Google_News_Following_Sources.png)](Google_News_Following_Sources.png)

From there we can click on each source and see how our RSS Feed is displayed in Google News as well as share with others.

[![Google News - Source - Yummy Recipes UK](Google_News_Yummy_Recipes_UK_source.png)](Google_News_Yummy_Recipes_UK_source.png)

Under the share button, we will be able to copy the direct link to your publication, which we can use later. But that's not all.

## Search Console

As all is connected with Google Search Console, once your publication is live you will be able to trace impressions and clicks on your publications in the dedicated **Google News** section, similar as it is for **Search results** and **Discover**.

[![Google News in Google Search Console](Google_News_in_Google_Search_Console.png)](Google_News_in_Google_Search_Console.png)

Now let's add a button to our website.

## Website button

Before we start constructing our "button", that will allow others to start following us in Google News let's see how the address of our publication is constructed.

Heading to [news.google.com **following** section](https://news.google.com/my/library) and clicking on one of our following sources we can use the share button to get a direct link that we need to pass to others.

[![Google News follow-share buttons on Yummy Recipes UK](Google_News_Yummy_Recipes_UK_Follow_share.png)](Google_News_Yummy_Recipes_UK_Follow_share.png)

By clicking the **copy link** icon there we will get an URL like:

```
https://news.google.com/publications/CAAqBwgKMIvhxwswv_zeAw?ceid=GB:en&oc=3
```

We will make it a bit simpler by removing not needed parameters and it will look like that:

```
https://news.google.com/publications/CAAqBwgKMIvhxwswv_zeAw
```

You can see that `CAAqBwgKMIvhxwswv_zeAw` is a unique publication identifier and the rest is just a static URL `https://news.google.com/publications/`. I am mentioning this, as depending on what framework you using, you may want to make it more suitable for use on multiple sites with the same code.

I am using [Hugo](https://gohugo.io) to build my website, hence in my website layout, I will set the code with a parameter (publication identifier) that will be taken from the config file (`hugo.toml`).

```toml
[params.social]
  google_news = "CAAqBwgKMIvhxwswv_zeAw"
  google_news_icon = "/svg/google_news.svg"
```

In a multilingual environment, where each language will have its publication identifier you may want to do the following:

```toml
[languages]
	[languages.pl]
		[languages.pl.Social]
		google_news = "CAAqBwgKMOmdyAswmbnfAw"
		google_news_icon = "/svg/google_news.svg"
	[languages.en]
		[languages.en.Social]
		google_news = "CAAqBwgKMPSdyAswpLnfAw"
		google_news_icon = "/svg/google_news.svg"
```

Before we start, we need to get the Google News icon in SVG format.

Heading to [Google News page in Wikipedia](https://en.wikipedia.org/wiki/Google_News) from where we can grab and download [Google News icon.svg](https://commons.wikimedia.org/wiki/File:Google_News_icon.svg).

Before I use any SVG downloaded from the internet I like to sanitize it through [SVG Sanitizer Test](https://svg.enshrined.co.uk). By opening the SVG file in the code editor (like VS Studio Code) I copy the "dirty SVG" code and after processing paste "clean" from the website and then save the SVG file.

Here is my approach to how I implement an icon in the following section (on top and bottom, in the footer) as well on the recipe page after the content, on [Yummy Recipes UK](https://yummyrecipes.uk).

The Follow section with inline SVG:

[![Follow buttons on Yummy Recipes UK](Yummy_Recipes_UK_Follow_buttons.png)](Yummy_Recipes_UK_Follow_buttons.png)

```html
<div class="follow-buttons">
  <div class="google-news">
    <a title="Follow us on Google News" href="https://news.google.com/publications/CAAqBwgKMIvhxwswv_zeAw" target="_blank" rel="noreferrer noopener">
      <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" viewBox="0 0 6550.8 5359.7" xml:space="preserve">
        <path fill="#0C9D58" d="M5210.8 3635.7c0 91.2-75.2 165.9-167.1 165.9H1507c-91.9 0-167.1-74.7-167.1-165.9V165.9C1339.9 74.7 1415.1 0 1507 0h3536.8c91.9 0 167.1 74.7 167.1 165.9v3469.8z"></path>
        <polygon opacity=".2" fill="#004D40" points="5210.8,892 3885.3,721.4 5210.8,1077"></polygon>
        <path opacity=".2" fill="#004D40" d="M3339.3 180.9L1332 1077.2l2218.5-807.5v-2.2c-39-83.6-134-122.6-211.2-86.6z"></path>
        <path opacity=".2" fill="#FFFFFF" d="M5043.8 0H1507c-91.9 0-167.1 74.7-167.1 165.9v37.2c0-91.2 75.2-165.9 167.1-165.9h3536.8c91.9 0 167.1 74.7 167.1 165.9v-37.2C5210.8 74.7 5135.7 0 5043.8 0z"></path>
        <path fill="#EA4335" d="M2198.2 3529.1c-23.9 89.1 23.8 180 106 202l3275.8 881c82.2 22 169-32.9 192.8-122l771.7-2880c23.9-89.1-23.8-180-106-202l-3275.8-881c-82.2-22-169 32.9-192.8 122l-771.7 2880z"></path>
        <polygon opacity=".2" fill="#3E2723" points="5806.4,2638.1 5978.7,3684.8 5806.4,4328.1"></polygon>
        <polygon opacity=".2" fill="#3E2723" points="3900.8,764.1 4055.2,805.6 4151,1451.6"></polygon>
        <path opacity=".2" fill="#FFFFFF" d="M6438.6 1408.1l-3275.8-881c-82.2-22-169 32.9-192.8 122l-771.7 2880c-1.3 4.8-1.6 9.7-2.5 14.5l765.9-2858.2c23.9-89.1 110.7-144 192.8-122l3275.8 881c77.7 20.8 123.8 103.3 108.5 187.6l5.9-21.9c23.8-89.1-23.9-180-106.1-202z"></path>
        <path fill="#FFC107" d="M4778.1 3174.4c31.5 86.7-8.1 181.4-88 210.5L1233.4 4643c-80 29.1-171.2-18-202.7-104.7L10.9 1736.5c-31.5-86.7 8.1-181.4 88-210.5L3555.6 267.9c80-29.1 171.2 18 202.7 104.7l1019.8 2801.8z"></path>
        <path opacity=".2" fill="#FFFFFF" d="M24 1771.8c-31.5-86.7 8.1-181.4 88-210.5L3568.7 303.1c79.1-28.8 169 17.1 201.5 102l-11.9-32.6c-31.6-86.7-122.8-133.8-202.7-104.7L98.9 1526c-80 29.1-119.6 123.8-88 210.5l1019.8 2801.8c.3.9.9 1.7 1.3 2.7L24 1771.8z"></path>
        <path fill="#4285F4" d="M5806.4 5192.2c0 92.1-75.4 167.5-167.5 167.5h-4727c-92.1 0-167.5-75.4-167.5-167.5V1619.1c0-92.1 75.4-167.5 167.5-167.5h4727c92.1 0 167.5 75.4 167.5 167.5v3573.1z"></path>
        <path fill="#FFFFFF" d="M4903.8 2866H3489.4v-372.2h1414.4c41.1 0 74.4 33.3 74.4 74.4v223.3c0 41.1-33.3 74.5-74.4 74.5zM4903.8 4280.3H3489.4v-372.2h1414.4c41.1 0 74.4 33.3 74.4 74.4v223.3c0 41.2-33.3 74.5-74.4 74.5zM5127.1 3573.1H3489.4v-372.2h1637.7c41.1 0 74.4 33.3 74.4 74.4v223.3c0 41.2-33.3 74.5-74.4 74.5z"></path>
        <path opacity=".2" fill="#1A237E" d="M5638.9 5322.5h-4727c-92.1 0-167.5-75.4-167.5-167.5v37.2c0 92.1 75.4 167.5 167.5 167.5h4727c92.1 0 167.5-75.4 167.5-167.5V5155c0 92.1-75.4 167.5-167.5 167.5z"></path>
        <path opacity=".2" fill="#FFFFFF" d="M911.9 1488.8h4727c92.1 0 167.5 75.4 167.5 167.5v-37.2c0-92.1-75.4-167.5-167.5-167.5h-4727c-92.1 0-167.5 75.4-167.5 167.5v37.2c0-92.1 75.4-167.5 167.5-167.5z"></path>
        <path fill="#FFFFFF" d="M2223.9 3238.2v335.7h481.7c-39.8 204.5-219.6 352.8-481.7 352.8-292.4 0-529.5-247.3-529.5-539.7s237.1-539.7 529.5-539.7c131.7 0 249.6 45.3 342.7 134v.2l254.9-254.9c-154.8-144.3-356.7-232.8-597.7-232.8-493.3 0-893.3 399.9-893.3 893.3s399.9 893.3 893.3 893.3c515.9 0 855.3-362.7 855.3-873 0-58.5-5.4-114.9-14.1-169.2h-841.1z"></path>
        <g opacity=".2" fill="#1A237E">
          <path d="M2233.2 3573.9v37.2h472.7c3.5-12.2 6.5-24.6 9-37.2h-481.7z"></path>
          <path d="M2233.2 4280.3c-487.1 0-882.9-389.9-892.8-874.7-.1 6.2-.5 12.4-.5 18.6 0 493.4 399.9 893.3 893.3 893.3 515.9 0 855.3-362.7 855.3-873 0-4.1-.5-7.9-.5-12-11.1 497-347.4 847.8-854.8 847.8zM2575.9 2981.3c-93.1-88.6-211.1-134-342.7-134-292.4 0-529.5 247.3-529.5 539.7 0 6.3.7 12.4.9 18.6 9.9-284.2 242.4-521.1 528.6-521.1 131.7 0 249.6 45.3 342.7 134v.2l273.5-273.5c-6.4-6-13.5-11.3-20.1-17.1L2576 2981.5l-.1-.2z"></path>
        </g>
        <path opacity=".2" fill="#1A237E" d="M4978.2 2828.7v-37.2c0 41.1-33.3 74.4-74.4 74.4H3489.4v37.2h1414.4c41.1.1 74.4-33.2 74.4-74.4zM4903.8 4280.3H3489.4v37.2h1414.4c41.1 0 74.4-33.3 74.4-74.4v-37.2c0 41.1-33.3 74.4-74.4 74.4zM5127.1 3573.1H3489.4v37.2h1637.7c41.1 0 74.4-33.3 74.4-74.4v-37.2c0 41.1-33.3 74.4-74.4 74.4z"></path>
        <radialGradient id="gn" cx="1476.404" cy="434.236" r="6370.563" gradientUnits="userSpaceOnUse">
          <stop offset="0" stop-color="#fff" stop-opacity=".1"></stop>
          <stop offset="1" stop-color="#fff" stop-opacity="0"></stop>
        </radialGradient>
        <path fill="url(#gn)" d="M6438.6 1408.1l-1227.7-330.2v-912c0-91.2-75.2-165.9-167.1-165.9H1507c-91.9 0-167.1 74.7-167.1 165.9v908.4L98.9 1526c-80 29.1-119.6 123.8-88 210.5l733.5 2015.4v1440.3c0 92.1 75.4 167.5 167.5 167.5h4727c92.1 0 167.5-75.4 167.5-167.5v-826.9l738.3-2755.2c23.8-89.1-23.9-180-106.1-202z"></path>
      </svg>
    </a>
  </div>
</div>
```

For Hugo with the use of parameters in `hugo.toml` (previously `config.toml`) file.

```html
<div class="follow-buttons">
  <div class="google-news">
    <a title="Follow us on Google News" href="https://news.google.com/publications/{{ .Site.Params.social.google_news }}" target="_blank" rel="noreferrer noopener">
      <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" viewBox="0 0 6550.8 5359.7" xml:space="preserve">
        <path fill="#0C9D58" d="M5210.8 3635.7c0 91.2-75.2 165.9-167.1 165.9H1507c-91.9 0-167.1-74.7-167.1-165.9V165.9C1339.9 74.7 1415.1 0 1507 0h3536.8c91.9 0 167.1 74.7 167.1 165.9v3469.8z"></path>
        <polygon opacity=".2" fill="#004D40" points="5210.8,892 3885.3,721.4 5210.8,1077"></polygon>
        <path opacity=".2" fill="#004D40" d="M3339.3 180.9L1332 1077.2l2218.5-807.5v-2.2c-39-83.6-134-122.6-211.2-86.6z"></path>
        <path opacity=".2" fill="#FFFFFF" d="M5043.8 0H1507c-91.9 0-167.1 74.7-167.1 165.9v37.2c0-91.2 75.2-165.9 167.1-165.9h3536.8c91.9 0 167.1 74.7 167.1 165.9v-37.2C5210.8 74.7 5135.7 0 5043.8 0z"></path>
        <path fill="#EA4335" d="M2198.2 3529.1c-23.9 89.1 23.8 180 106 202l3275.8 881c82.2 22 169-32.9 192.8-122l771.7-2880c23.9-89.1-23.8-180-106-202l-3275.8-881c-82.2-22-169 32.9-192.8 122l-771.7 2880z"></path>
        <polygon opacity=".2" fill="#3E2723" points="5806.4,2638.1 5978.7,3684.8 5806.4,4328.1"></polygon>
        <polygon opacity=".2" fill="#3E2723" points="3900.8,764.1 4055.2,805.6 4151,1451.6"></polygon>
        <path opacity=".2" fill="#FFFFFF" d="M6438.6 1408.1l-3275.8-881c-82.2-22-169 32.9-192.8 122l-771.7 2880c-1.3 4.8-1.6 9.7-2.5 14.5l765.9-2858.2c23.9-89.1 110.7-144 192.8-122l3275.8 881c77.7 20.8 123.8 103.3 108.5 187.6l5.9-21.9c23.8-89.1-23.9-180-106.1-202z"></path>
        <path fill="#FFC107" d="M4778.1 3174.4c31.5 86.7-8.1 181.4-88 210.5L1233.4 4643c-80 29.1-171.2-18-202.7-104.7L10.9 1736.5c-31.5-86.7 8.1-181.4 88-210.5L3555.6 267.9c80-29.1 171.2 18 202.7 104.7l1019.8 2801.8z"></path>
        <path opacity=".2" fill="#FFFFFF" d="M24 1771.8c-31.5-86.7 8.1-181.4 88-210.5L3568.7 303.1c79.1-28.8 169 17.1 201.5 102l-11.9-32.6c-31.6-86.7-122.8-133.8-202.7-104.7L98.9 1526c-80 29.1-119.6 123.8-88 210.5l1019.8 2801.8c.3.9.9 1.7 1.3 2.7L24 1771.8z"></path>
        <path fill="#4285F4" d="M5806.4 5192.2c0 92.1-75.4 167.5-167.5 167.5h-4727c-92.1 0-167.5-75.4-167.5-167.5V1619.1c0-92.1 75.4-167.5 167.5-167.5h4727c92.1 0 167.5 75.4 167.5 167.5v3573.1z"></path>
        <path fill="#FFFFFF" d="M4903.8 2866H3489.4v-372.2h1414.4c41.1 0 74.4 33.3 74.4 74.4v223.3c0 41.1-33.3 74.5-74.4 74.5zM4903.8 4280.3H3489.4v-372.2h1414.4c41.1 0 74.4 33.3 74.4 74.4v223.3c0 41.2-33.3 74.5-74.4 74.5zM5127.1 3573.1H3489.4v-372.2h1637.7c41.1 0 74.4 33.3 74.4 74.4v223.3c0 41.2-33.3 74.5-74.4 74.5z"></path>
        <path opacity=".2" fill="#1A237E" d="M5638.9 5322.5h-4727c-92.1 0-167.5-75.4-167.5-167.5v37.2c0 92.1 75.4 167.5 167.5 167.5h4727c92.1 0 167.5-75.4 167.5-167.5V5155c0 92.1-75.4 167.5-167.5 167.5z"></path>
        <path opacity=".2" fill="#FFFFFF" d="M911.9 1488.8h4727c92.1 0 167.5 75.4 167.5 167.5v-37.2c0-92.1-75.4-167.5-167.5-167.5h-4727c-92.1 0-167.5 75.4-167.5 167.5v37.2c0-92.1 75.4-167.5 167.5-167.5z"></path>
        <path fill="#FFFFFF" d="M2223.9 3238.2v335.7h481.7c-39.8 204.5-219.6 352.8-481.7 352.8-292.4 0-529.5-247.3-529.5-539.7s237.1-539.7 529.5-539.7c131.7 0 249.6 45.3 342.7 134v.2l254.9-254.9c-154.8-144.3-356.7-232.8-597.7-232.8-493.3 0-893.3 399.9-893.3 893.3s399.9 893.3 893.3 893.3c515.9 0 855.3-362.7 855.3-873 0-58.5-5.4-114.9-14.1-169.2h-841.1z"></path>
        <g opacity=".2" fill="#1A237E">
          <path d="M2233.2 3573.9v37.2h472.7c3.5-12.2 6.5-24.6 9-37.2h-481.7z"></path>
          <path d="M2233.2 4280.3c-487.1 0-882.9-389.9-892.8-874.7-.1 6.2-.5 12.4-.5 18.6 0 493.4 399.9 893.3 893.3 893.3 515.9 0 855.3-362.7 855.3-873 0-4.1-.5-7.9-.5-12-11.1 497-347.4 847.8-854.8 847.8zM2575.9 2981.3c-93.1-88.6-211.1-134-342.7-134-292.4 0-529.5 247.3-529.5 539.7 0 6.3.7 12.4.9 18.6 9.9-284.2 242.4-521.1 528.6-521.1 131.7 0 249.6 45.3 342.7 134v.2l273.5-273.5c-6.4-6-13.5-11.3-20.1-17.1L2576 2981.5l-.1-.2z"></path>
        </g>
        <path opacity=".2" fill="#1A237E" d="M4978.2 2828.7v-37.2c0 41.1-33.3 74.4-74.4 74.4H3489.4v37.2h1414.4c41.1.1 74.4-33.2 74.4-74.4zM4903.8 4280.3H3489.4v37.2h1414.4c41.1 0 74.4-33.3 74.4-74.4v-37.2c0 41.1-33.3 74.4-74.4 74.4zM5127.1 3573.1H3489.4v37.2h1637.7c41.1 0 74.4-33.3 74.4-74.4v-37.2c0 41.1-33.3 74.4-74.4 74.4z"></path>
        <radialGradient id="a" cx="1476.404" cy="434.236" r="6370.563" gradientUnits="userSpaceOnUse">
          <stop offset="0" stop-color="#fff" stop-opacity=".1"></stop>
          <stop offset="1" stop-color="#fff" stop-opacity="0"></stop>
        </radialGradient>
        <path fill="url(#a)" d="M6438.6 1408.1l-1227.7-330.2v-912c0-91.2-75.2-165.9-167.1-165.9H1507c-91.9 0-167.1 74.7-167.1 165.9v908.4L98.9 1526c-80 29.1-119.6 123.8-88 210.5l733.5 2015.4v1440.3c0 92.1 75.4 167.5 167.5 167.5h4727c92.1 0 167.5-75.4 167.5-167.5v-826.9l738.3-2755.2c23.8-89.1-23.9-180-106.1-202z"></path>
      </svg>
    </a>
  </div>
</div>
```

```css
:root {
    --googlenews: #5383ec;
    --googlenews-bg: #ecf7ff;
}


.follow-buttons {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: baseline;
    vertical-align: middle;
}

.follow-buttons {
    margin: 0.5rem 0 1rem 0;
}

.follow-buttons > div {
    position: relative;
    display: inline-block;
}
.follow-buttons > div:hover {
    cursor: pointer;
}

.follow-buttons > div svg {
    margin: 0 0.4rem;
    border-radius: 10px;
}

.follow-buttons > div svg {
    height: 1.5rem;
    padding: 0.6rem;
}
@media (max-width: 834px) {
    .follow-buttons > div svg {
        height: 1rem;
        padding: 0.6rem;
    }
}

.follow-buttons > div.google-news svg {
    border: 2px solid var(--googlenews);
}
.follow-buttons > div.google-news:hover svg {
    background-color: var(--googlenews-bg);
    border: 2px solid var(--googlenews);
}
```

After content (with SVG in IMG tag):

[![Button for following Yummy Recipes UK in Google News](Yummy_Recipes_UK_Follow_in_Google_News_button.png)](Yummy_Recipes_UK_Follow_in_Google_News_button.png)

```html
<div id="google-news">
  <div class="google-news">
    <a title="Follow Yummy Recipes UK on Google News" href="https://news.google.com/publications/CAAqBwgKMIvhxwswv_zeAw" target="_blank" rel="noreferrer noopener">
      Follow Yummy Recipes UK on Google News<img src="/svg/google_news.svg" alt="Follow Yummy Recipes UK on Google News" height="24" width="29">
    </a>
  </div>
</div>
```

For Hugo with the use of parameters in `hugo.toml` (previously `config.toml`) file.

```html
<div id="google-news">
  <div class="google-news">
    <a title="Follow {{ .Site.Title }} on Google News" href="https://news.google.com/publications/{{ .Site.Params.social.google_news }}" target="_blank" rel="noreferrer noopener">
      Follow {{ .Site.Title }} on Google News<img src="{{ .Site.Params.social.google_news_icon }}" alt="Follow {{ .Site.Title }} on Google News" height="24" width="29">
    </a>
  </div>
</div>
```

```css
:root {
    --googlenews: #5383ec;
    --googlenews-bg: #ecf7ff;
}


#google-news {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: baseline;
    vertical-align: middle;
    padding-bottom: 1rem;
  }

#google-news .google-news {
    background-color: var(--googlenews-bg);
    border: 2px solid var(--googlenews);
    border-radius: 4px;
    padding: 0.5rem 0.8rem;
}
#google-news .google-news:hover {
    border: 2px solid var(--googlenews);
    cursor: pointer; 
}

#google-news .google-news a {
    color: var(--googlenews);
    text-decoration: none;
}

#google-news .google-news a:hover {
    text-decoration: underline;
}

#google-news .google-news img {
  vertical-align:middle;
  display: inline;
  height: 1.5rem;
  width: auto;
  margin: 0 0 0 0.5rem;
}

@media (max-width: 834px) {
    #google-news .google-news {
        font-size: 0.8rem;
        padding: 0.5rem 0.6rem;
    }
    #google-news .google-news img  {
        height: 1.25rem;
    }
}
```

This is just my implementation. Feel free to adjust it to your needs.

{{% ads-in-article %}}

## Review and Rejection

Even though I set Yummy Recipes UK as a first, and it got approved without any issues, the grass is not always green.

Even if you set up everything correctly and think your site is highly valuable for users, your publication can still be rejected.

This happens to both of my publications. My English part of the website has been rejected once and my Polish part three times before it was finally approved.

In the first instance, I have been advised that through my articles I am serving redirection links. In the second instance, through redirection links, I am redirecting users to a no-news website, followed by information that my site contains promotional content (twice).

In all these situations, it was total nonsense. I am not serving any affiliate links and links through my posts are just references to other sites. I removed all ads from my website years ago.

Each time I have been advised that my redirection links/promotional content are against Google News content policy. **But you know what?** In Google News content policy there is no word about that. I read it fully and all the rejections are invalid in my opinion so I decided to **complain**.

On one of my posts I link to [John Mueller's website](https://johnmu.com) (a guy from Google), hence saying that I am serving a redirection link to that particular site was a bit stupid.

I even asked John about that on Mastodon. Though John is not involved directly with Google News he serves a good insight stating *"some automation gets confused by the links to my site"*.

I decided to complain on the [Publisher Center Help](https://support.google.com/news/publisher-center/thread/198556076/) community to see if I can get some clarification on the rules.

Overall I see that Google rely heavily on automation and the automation is wrong in some instances, like mine.

After the initial rejection of my English publication feed and complaints on the publisher centre, where a Google employee took this further my publication was finally accepted and live.

As we see, automation is in many cases done through machine learning and has no real human review until it's required. That happens here this is why my publication was eventually approved.

My Polish publication has been rejected three times and after discussion and helpful intervention from a Google employee, after two weeks all my feeds are live on Google News.

> Through that issue I noticed, that if you add the publication to Google News, which is written in a non-English language, during review it's translated into English (as seen on the screenshots provided from the rejection emails). This probably is confusing machines and links are mangled and mistaken for redirection/promotion.

**Be patient during the review process.**

Each time my publication was rejected, I resubmit without making any changes. I followed up on my conversation on the publishers' discussion. With Google support, all have been approved.

Advice for you. If it's not approved initially, don't give up, try again and [use available tools of communication](https://support.google.com/news/publisher-center/).

Good luck!


---
## Add and use an image sitemap with Hugo
- **URL:** https://dariusz.wieckiewicz.org/en/add-and-use-an-image-sitemap-with-hugo/
- **Date:** 2023-01-29
- **Tags:** hugo, sitemap, image sitemap, Custom Output Formats, Use an image sitemap, sitemap for images, Google images, Google Search Console

### Content

Not so far ago I elaborated on [adding copyright information for images on a Hugo-based website](/en/adding-copyright-information-images-hugo/). Through this approach, I managed to learn how to get images per post, then list and use in Schema for Images.

Recently, when I read updated [Google image SEO best practices](https://developers.google.com/search/docs/appearance/google-images) I noticed a section called [Use an image sitemap](https://developers.google.com/search/docs/appearance/google-images#use-an-image-sitemap) where we read:

> "You can provide the URL of images we might not have otherwise discovered by submitting an image sitemap".

I decided to see how I can implement that into my Hugo website.

<!--more-->

I started by looking at the [example of image sitemap](https://developers.google.com/search/docs/crawling-indexing/sitemaps/image-sitemaps#example-sitemap) and decided to give it a try.

---

Hugo gives you flexibility in adding additional output files. Through this, I decided to create a sitemap for images.

## Configuration

I started with specifying additional output for my sitemap in the Hugo configuration file (`hugo.toml`).

```toml
[outputFormats.imagessitemap]
  baseName  = 'imagessitemap'
  mediaType = 'application/xml'
  noUgly = true # default is false
```

Further, in the same file, I added it to my outputs.

```toml
[outputs]
  page = [ "html"]
  home = [ "html", "rss", "imagessitemap"]
```

---

## Multilingual adjustment

If you using a multilingual approach you may need to do an additional action here.

My Polish site is served in pure baseURL `/` where my English part is `/en/`.

The above output will generate the `imagesitemap.xml` file in `/` (Polish) and `/en/` (English).

The problem is that, with a multilingual approach, the `/sitemap.xml` is not a sitemap for the Polish part of the website. This file is serving as a Sitemap Index file listing sitemaps in language folders.

For the Polish part of the website, despite it being in `/`, the sitemap with posts will be `/pl/sitemap.xml` and for English `/en/sitemap.xml`.

This may be a bit of OCD, but I would like my sitemap for images to be generated in the language folder. I would like the Polish part to be in `/pl/imagessitemap.xml`. To do that, I need to add in the configuration file, in my main language section, the following:

```toml
  [languages.pl.outputFormats.imagessitemap]
    baseName  = 'imagessitemap'
    mediaType = 'application/xml'
    noUgly = true # default is false
    path  = 'pl'
```

For the English part, it is not required as it will, by default, generate inside `/en/` folder.

----

## Layout

Now we need to create our custom output layout.

I created file called `home.imagessitemap.xml` in `layouts\` folder.

```xml
{{- $pctx := . -}}
{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
{{- $pages := slice -}}
{{- if or $.IsHome $.IsSection -}}
{{- $pages = $pctx.RegularPages -}}
{{- else -}}
{{- $pages = $pctx.Pages -}}
{{- end -}}
{{- $limit := .Site.Config.Services.RSS.Limit -}}
{{- if ge $limit 1 -}}
{{- $pages = $pages | first $limit -}}
{{- end -}}

{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">

{{ range where $pages "Sitemap.Disable" "ne" true }}
  {{ if or (.Params.featuredImage) (findRE `(?s)<img.+?>` .Content) }}
    {{- if .Permalink -}}
      <url>
        <loc>{{ .Permalink }}</loc>
        {{ if .Params.featuredImage }}

          {{- $ftimgsrc := "" -}}
          {{ if hasPrefix .Params.featuredImage "/" }}
              {{ $ftimgsrc = resources.Get .Params.featuredImage }}
          {{ else }}
              {{ if .Page.BundleType }}
                  {{ $ftimgsrc = .Page.Resources.GetMatch .Params.featuredImage }}
              {{ else }}
                  {{ $path := path.Join .Page.File.Dir .Params.featuredImage }}
                  {{ $ftimgsrc = resources.Get $path }}
              {{ end }}
          {{ end }}

          <image:image>
            <image:loc>{{ $ftimgsrc.Permalink }}</image:loc>
          </image:image>{{ end }}
          {{ if (findRE `(?s)<img.+?>` .Content) }}{{ range $k, $_ := findRE `(?s)<img.+?>` .Content }}{{ if $k }}{{ end }}
            <image:image>
              <image:loc>{{ replaceRE `(?s).*src="(.+?)".*` "$1" . | absURL }}</image:loc>
            </image:image>{{ end }}
        {{ end }}
      </url>{{- end -}}
  {{ end }}
{{ end }}
  
</urlset>
```

In this file, I am using sitemap exclusion implemented in Hugo 0.125.0 (`Sitemap.Disable`) for posts that got it specified in frontmatter in the following way:

```yaml
sitemap:
  disable: true
```

{{% ads-in-article %}}

I followed it with a condition `if or` where I will list the post only if got either `featuredImage` specified in the frontmatter or any image added through the content utilising `findRE` function that I learned before.

In this way, the post URL, specified between `<loc>` will appear only if there are images to report.

By running Hugo locally we can verify, under `localhost:1313/imagessitemap.xml`, or if we have multilanguage site `localhost:1313/en/imagessitemap.xml` or `localhost:1313/pl/imagessitemap.xml` are our site is there.

{{% ads-in-article %}}

## Announcing new sitemaps

The last bit is to report the sitemap in such a way, that Google and other search engines will be able to detect them.

The best approach is to report it in the `robots.txt` file that is normally located in our `static\` folder.

> If you don't know how to create `robots.txt` file, read [How to write and submit a robots.txt file](https://developers.google.com/search/docs/crawling-indexing/robots/create-robots-txt) at Google Search Central.

Below other sitemaps that may be already there I added the following:

```
Sitemap: https://dariusz.wieckiewicz.org/pl/imagessitemap.xml
Sitemap: https://dariusz.wieckiewicz.org/en/imagessitemap.xml
```

To speed things up, I manually added them in [the sitemaps section at Google Search Console](https://search.google.com/search-console/sitemaps).

And that's all!


---
## I listen to a book
- **URL:** https://dariusz.wieckiewicz.org/en/i-listened-to-a-book/
- **Date:** 2023-01-23
- **Tags:** Audiobook, Start With Why, reading experience, listening experience, narrator, Simon Sinek, Apple Books

### Content

As much as I am **not** a fan of reading books, there are some titles that I really would like to go through. There is only one problem, I barely got time to do that.

If I want, I would find the time, but there are so many distractions, that this will still be a challenge.

I even purchased a book months back to read (Simon Sinek - Start With Why). I started, and it was interesting but then I do not come back to it despite leaving it on my desk so each time I am going to bed I see that this is not finished.

<!--more-->

To read a book you need to dedicate yourself to it, at least in my example. I am not a person who will read a bit, put a bookmark and go back to it next time. I would like to read it, part, chapter or section, and then maybe pause.

With my mentality, that I would like to do as much as possible in my free time, I lack time for reading.

I never managed to sacrifice myself to read a book unless I need to.

Most of the books, that I had been forced to read through school were boring. I don’t like that, I was not a fan of the content and quickly I lose the patience to read.

The situation was a bit different when I go to the University. There, I read the necessary books to gain knowledge. This was different. I have been reading something that I need and I want to learn to progress. Nobody force me to do so and I knew they this was something that I need to spend my time.

Right now, when I am reading on screen a lot throughout the day, I don’t have time for books. 

I purchase a book so I want to force myself into it again, especially since I want to read it.

What I noticed recently, the only time that I got for myself and my head is when I am walking a dog or driving to work. I can listen to music at that time, but instead of that, I tried first with podcasts. Sadly, doing these two tasks, I cannot read at in same time.

I started to listen to podcasts sometime now and find out, even though I have been sceptical about that, that is a quite good way to fill my head with things that I am interested in.

However, what I noticed, it all depends on the person and the narrator. If the person's voice is not appealing to me, making me sleepy or boating, this will not work.

> I found some courses on LinkedIn that present some interesting topics but the lecturer's voice is not great and going through the course is like dragging me through it. It's difficult, I understand that. It's not this person's fault. I can't stand my voice in recorded form hence I don't think I could be a good pre-recorded lecturer either.

I found a podcast for a person that I am currently interested in and that I found his voice appealing (Simon Sinek, but also Hal Elrod).

Simon Sinek released a book that I purchased. 

I found out that Simon's podcasts worked well, so I decided to look into audiobooks.

I found out that the book that I purchased in paper form is narrated by himself, the author. I like Simon's voice, hence having him narrate his book was appealing. So I purchased it and start listening.

The podcasts however were different from than narrated book. Podcasts have been more alive and more energetic – different.

The beginning of the book sounds a bit artificial. Like "just a reading".

Same person, same voice, however, something has been missing. 

I keep going and noticed that this was just the beginning. It quickly changed once you go further and further. **Great!**

The book, which has 7.5 hours of listening time, connect with me and I got the same feeling when I listened to his podcasts. I want more!

Each time I walk a dog or drive a car I am moving further and further in it.

When I arrive at my destination I am trying to find a perfect spot to pursue to not lose the plot.

This feels different because I couldn’t imagine pausing reading in the middle of the section. When I carry on listening I feel the continuity. I don’t need to go back to “re-read” the previous paragraph. I can carry or.

Books may not be for everybody, but accessing books through audiobooks is a good solution for busy people, for people like me. 

It feels odd to say that I read a book, so is more likely better to say that I listened to a book, but is that any different?

You read or somebody read to you. If you pay attention and digest it in your head it's becoming like "a reading experience".

In the end, I “read” a book and I feel that this is not the last and will give it another try to another one. Overall I got three other books from Simon waiting in my "want to read" section in Apple Books.

From the book **Start With Why**[^1] there is one thing that stuck with me deeply as it represents my curret feeling in my professional life:

{{% ads-in-article %}}

> "For all organisations that go through the split, they are no longer inspired by a cause greater than themselves. They simply come to work, manage systems and work to reach certain present goals. (...). The passion is gone and the inspiration is at a minimum. (...) for most who show up every day what they do is just a job."

But there is hope, there is a light...

> "What if we showed up to work every day simply to be better than ourselves?" (...) for no other reason than because we want to leave the organization in a better state than we found it"

[^1]: [Simon Sinek - Start With Why @ Amazon](https://amzn.eu/d/9JgWIDi)


---
## Adding FAQ (Frequently Asked Questions) Schema to Hugo-based website
- **URL:** https://dariusz.wieckiewicz.org/en/adding-faq-schema-to-hugo-website/
- **Date:** 2023-01-09
- **Tags:** Hugo, FAQ, FAQ structured data, FAQ Schema, FAQPage, frequently asked questions, Schema, Structured data, Enhancements, Google Search Console, Rich Results Test

### Content

Do you write on your website a series of frequently asked questions (FAQs) and try to answer them? Do you know that putting text on a website is not enough to gain traction? Even if your questions and answers are unique and could be desired by users, they may never find their audience.

Playing with the SEO aspect may help, but if we concentrate only on the **surface** – visible part, we will still be missing out. What is important is what **beneath**, just in the background. This is how we can simply describe what is Schema. 

Structured data (Schema) is presented on a website in a way that is not visible to an ordinary visitor but processed, when found, by search engines.

Schema is very important and will be even more this year (2023), as mentioned directly by many people at Google.

To get your question-answers into search engines you should put your interest into the **Frequently Asked Questions (FAQ) Schema**.

Here is how I did this on some of the websites that I made with [Hugo](https://gohugo.io).

<!--more-->

Before we start you need to be aware that **there is no single way to implement FAQ Schema into your website**.

> When I wrote this article I found a different (better) approach to some of the elements, so at the same time as I describe here, I improve my code.

I will present you my approaches in a **single page FAQ** (with multiple questions and answers presented separately on a page) and **questions and answers on their pages** (a single page containing the question and answer). I will show you also how to use the details disclosure element on a single-page FAQ.

The solutions work for me but do not necessarily may work for you, or, based on them, you can create your solution. Feel free to share your approach in the discussion under the post.

---

Before you start, here are a couple of websites that you may need to understand the structure of FAQ Schema as well as how to test it before putting it live.

* [**FAQ structured data**](https://developers.google.com/search/docs/appearance/structured-data/faqpage) on [Google Search Central](https://developers.google.com/search) will give you walk thorough overview of structured data for the schema.
* [**FAQPage**](https://schema.org/FAQPage), [**Question**](https://schema.org/Question) and [**Answer**](https://schema.org/Answer) on [Schema.org](https://schema.org) will give you more technical aspects of how to build frequently asked questions schema.
* [**Rich Results Test**](https://search.google.com/test/rich-results) will allow you to test your implemented schema. By using the **Code** tab we will be able to paste our development code and test it before we will go live.
* [**Google Search Console**](https://search.google.com/search-console) will allow you to track, in the Enhancements part, your progress in the long term.

Also, make sure that you got the following code added to your Hugo config file (`hugo.toml` or `config.toml`)

```toml
[markup]
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true	
```

---

## FAQ on a single page

My single page layout `single.html` contains the following part to display the content.

```html
<section id="content">
	{{ .Content }}
</section>
```

We need to start, in layout, by telling, through frontmatter, when the page is a FAQ page. This FAQ page will need to contain `itemscope itemtype="https://schema.org/FAQPage"` information as follows:

```html
<section id="content"{{if .Params.faq }} itemscope itemtype="https://schema.org/FAQPage"{{ end}}>
      {{ .Content }}
</section>
```

In such a way, when we specify `faq: true` in the frontmatter of our markdown file, we will display the necessary start point that will tell that the page will contain a reference to FAQ Schema.

```markdown
---
faq: true
---
```

### Content

To create our FAQ page, let's create our markdown file `faq.md` in the content folder.

```markdown
---
title: FAQ
faq: true
---

Lorem ipsum dolor sit amet...
```

Into the content (`Lorem ipsum dolor sit amet...`) we will type out questions and answers. As the title in frontmatter is our `<h1>` tag (equal to `#` in markdown) we will compose our questions as `<h2>` elements (`##`).

> I am using heading elements as you can [link directly to each of them from different pages using the ID attribute](https://developers.google.com/style/headings-targets).

```markdown
## Customers asking me how to do this fancy thing?
To make this fancy thing you need to have this fancy stuff.

## What fancy stuff do I need?
You will need fancy elements and fancy liquid.
```

Each question above `##` contains an answer underneath.

These questions and answers are just text. To allow search engines to detect which one is a question and which answer is to which one, we need to do some work.

For this purpose, we will create **two** shortcodes in `layouts\shortcodes`. One is called `faq-question.html` and the other `faq-answer.html`.

Each question we will wrap between shortcode as follow:

```markdown
{{%/* faq-question */%}}
## Customers asking me how to do this fancy thing?
To make this fancy thing you need to have this fancy stuff.
{{%/* /faq-question */%}}

{{%/* faq-question */%}}
## What fancy stuff do I need?
You will need fancy elements and fancy liquid.
{{%/* /faq-question */%}}
```

Now we will have separated questions on our FAQ page.

Each question needs to be wrapped in `itemscope itemtype="https://schema.org/Question" itemprop="mainEntity"`, this is what we will put into our shortcode `faq-question.html`.

```html
<span itemscope itemtype="https://schema.org/Question" itemprop="mainEntity">
    {{ .Inner }}
</span>
```

Now we need to tell which part inside the question block is an answer. We will wrap an answer into our `faq-answer.html` shortcode.

```markdown
{{%/* faq-question */%}}
## Customers asking me how to do this fancy thing?
{{%/* faq-answer */%}}
To make this fancy thing you need to have this fancy stuff.
{{%/* /faq-answer */%}}
{{%/* /faq-question */%}}

{{%/* faq-question */%}}
## What fancy stuff do I need?
{{%/* faq-answer */%}}
You will need fancy elements and fancy liquid.
{{%/* /faq-answer */%}}
{{%/* /faq-question */%}}
```

Each answer needs to be wrapped in `‌itemscope itemtype="https://schema.org/Answer" itemprop="acceptedAnswer"`, this is what we will put into our shortcode `faq-answer.html`.

```html
<span itemscope itemtype="https://schema.org/Answer" itemprop="acceptedAnswer">
    <span itemprop="text">{{ .Inner }}</span>
</span>
```

We don't need to worry about formatting, as the question and answer will be processed by the search engine in plain text form.

**There is one thing missing.**

We got our **FAQ Page specified**, **Questions split** between each other and **Answer** to them easily identified. We need to let know that `<h2>` that contains our question is indeed a question to our FAQ Schema.

### Customising heading

Each question shall contain the `itemprop=name` element. In that case our `<h2>` which will contain `id="customers-asking-me-how-to-do-this-fancy-thing"` need to have added `itemprop=name` as well.

The easiest way is to add a markdown attribute.

For example, this:

```markdown
## Customers asking me how to do this fancy thing?
```

Will render as:

```html
<h2 id="customers-asking-me-how-to-do-this-fancy-thing">Customers asking me how to do this fancy thing?</h2>
```

If we add `{itemprop=name}` after the heading (**in same line**) like that:

```markdown
## Customers asking me how to do this fancy thing? {itemprop=name}
```

This will render as:

```html
<h2 id="customers-asking-me-how-to-do-this-fancy-thing" itemprop="name">Customers asking me how to do this fancy thing?</h2>
```

The element `{itemprop=name}` will not be visible to the visitor.

In such a way, we got everything ready and working.

**However, the markdown attribute is not always working.**

If we got customised `render-heading.html` in `layouts\_markup`, as [described here](https://gohugo.io/templates/render-hooks/#heading-link-example), the markdown attribute will not be passed through.

```html
<h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }} <a href="#{{ .Anchor | safeURL }}">¶</a></h{{ .Level }}>
```

Let's change it by adding `.Attributes` to the code:

```html
<h{{ .Level }} {{- range $k, $v := .Attributes -}}{{- printf " %s=%q" $k $v | safeHTMLAttr -}}{{- end -}}">{{ .Text | safeHTML }} <a href="#{{ .Anchor | safeHTMLAttr }}">¶</a></h{{ .Level }}>
```

> Ranging `.Attributes` will include `.Anchor"` in output, hence no need to add it separately.

At this time I would want to customise one more thing. The element `¶` (on my website is the symbol `#`), which serves as a link to the section, will be passed with the question into the schema. We need to exclude that by telling when the page is FAQ, this shall not be displayed.

Replacing:

```html
<a class="anchor" href="#{{ .Anchor | safeURL }}">#</a>
```

With:

```html
{{ if (not .Page.Params.faq) }}<a class="anchor" href="#{{ .Anchor | safeURL }}">#</a>{{ end }}
```

### Validation

Run our Hugo (`hugo server`) on our local machine, go to the page and see the **page source** (In Safari on macOS right click on a page and select `Show Page Source`).

Copy the whole page source into your code editor and by using the option search/replace find `http://localhost:1313` and replace it with `https://example.com`.

Then copy the whole code again and head to [Rich Results Test](https://search.google.com/test/rich-results) tool and in **Code** tab paste out the code and click the **Test Code** button.

After a short analysis, you should see detected new structured data.

[![FAQ Schema with 1 Valid item detected](/images/2023/01/FAQ_1_valid_item_detected.png)](/images/2023/01/FAQ_1_valid_item_detected.png)

It will be 1 valid item detected, as this is only a single page. However, if you click on it, you will see that Google is correctly identifying multiple questions and their corresponding answers from this single page.

Here is how it looks on my example page [yummyrecipes.uk/tips](https://yummyrecipes.uk/tips/) that got implemented FAQ using the above method.

[![FAQ Schema of the example website YummyRecipes.uk](/images/2023/01/FAQPage_Question_Answers_YummyRecipes_UK.png)](/images/2023/01/FAQPage_Question_Answers_YummyRecipes_UK.png)

Once you publish your page with FAQ head to [Google Search Console](https://search.google.com/search-console) and crawl your URL and request indexing (or re-indexing, if the page is already in Google).

After that wait patiently. Your new FAQ section in the Enhancements section shall appear in roughly 24 to 48 hours.

[![Google Search Console FAQ Schema with 1 Valid Item](/images/2023/01/Google_Search_Console_FAQ_1_Valid_Item.png)](/images/2023/01/Google_Search_Console_FAQ_1_Valid_Item.png)

## FAQ on individual pages

If your questions require a complex answer, which is not typically fit in 1-2 paragraphs, then it may be worth creating a page for each question.

For example, you may have the following structure:

```
/faq/
/faq/customers-asking-me-how-to-do-this-fancy-thing/
/faq/what-fancy-stuff-do-i-need/
```

> Remember, do not use individual pages by only thinking that this will help to position in Google, as more pages are better for SEO. That's a myth! Think more about this like that. If your question requires a complex answer, which is more than 1-2 paragraphs, then it may be beneficial to have it on a separate page.
> 
> Put ourselves into your reader's (visitors) shoes. Do you prefer to read the question and short answer on the same page, or do you prefer to wondering between pages only to read a single paragraph? Think about **usability first**! 

Here we will start with two things.

1. We will create a page that will list all questions (this will be in `/faq/`). This is optional and depends on your approach and the design of your website.
2. We will create [**FAQPage**](https://schema.org/FAQPage), [**Question**](https://schema.org/Question) and [**Answer**](https://schema.org/Answer) page.

{{% ads-in-article %}}

### Listing all questions

There are multiple ways how to achieve that. I will explain mine, which will work on identifying pages based on category and tag in frontmatter.

Example:
```markdown
---
title: Customers asking me how to do this fancy thing?
category:
 - FAQ
tags:
 - faq
---

To make this fancy thing you need to have this fancy stuff.
```


```html
{{</* faq "faq" */>}}
```

Shortcode:

```html
<ul class="faq-list">
  {{ $tagged := .Get 0 }}
  {{ range .Site.Pages }}
    {{ if in .Params.categories "FAQ" }}
      {{ if in .Params.tags $tagged }}
       <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
       {{ end }}
     {{ end }}
  {{ end }}
</ul>
```

You may ask why I am using **category** and **tag**.

This is why, as I can split FAQ into sections.

In that case, all pages that belong to the FAQ section will have `category` set as `FAQ`. Different questions may be identified by different tags and grouped under the different sections on the same page like below.

```markdown
## Frequently Asked Questions for Sellers

{{</* faq "Sellers FAQ" */>}}

## Frequently Asked Questions for Buyers

{{</* faq "Buyers FAQ" */>}}
```

```markdown
---
tags:
 - 'Sellers FAQ`
---
``` 

### Page with question and answer

Let's start with our single page layout `single.html` that will contain the following elements responsible for displaying a title (taken from frontmatter) and content:

```html
<article>
	<section id="content">
		<div class="page-header">
			<h1>{{ .Title }}</h1>
		</div>
		<div class="page-content">
			{{ .Content }}
		</div>
	</section>
</article>
```

We need to modify this to state that this is a **FAQPage**, the title is our **Question** and the content is our **Answer**.

* Let's start with identifying the page as FAQ by adding `{{ if in .Params.categories "FAQ" }} itemscope itemtype="https://schema.org/FAQPage"{{ end}}` to `<article>` element;
* Let's add `{{ if in .Params.categories "FAQ" }} itemscope itemtype="https://schema.org/Question" itemprop="mainEntity"{{ end}}` to `<section id="content">` element;
* Let's add `{{ if in .Params.categories "FAQ" }} itemprop="name"{{ end}}` to `<div class="page-header">` element;
* Let'a add `{{ if in .Params.categories "FAQ" }} itemscope itemtype="https://schema.org/Answer" itemprop="acceptedAnswer"{{ end}}` to `<div class="page-content">` element.
* Let's wrap `{{ .Content }}` between conditional `{{ if in .Params.categories "FAQ" }}<span itemprop="text">{{ end}}` and closing `{{ if in .Params.categories "FAQ" }}</span>{{ end}}`

This will look as follow:

```html
<article {{ if in .Params.categories "FAQ" }}itemscope itemtype="https://schema.org/FAQPage"{{ end}}>
	<section id="content"{{ if in .Params.categories "FAQ" }} itemscope itemtype="https://schema.org/Question" itemprop="mainEntity"{{ end}}>
		<div class="page-header"{{ if in .Params.categories "FAQ" }} itemprop="name"{{ end}}>
			<h1>{{ .Title }}</h1>
		</div>
		<div class="page-content"{{ if in .Params.categories "FAQ" }} itemscope itemtype="https://schema.org/Answer" itemprop="acceptedAnswer"{{ end}}>
			{{ if in .Params.categories "FAQ" }}<span itemprop="text">{{ end}}
				{{ .Content }}
			{{ if in .Params.categories "FAQ" }}</span>{{ end}}
		</div>
	</section>
</article>
```

### Validation

Run our Hugo (`hugo server`) on our local machine, go to the single page, that contains your single question and its answer, and see the **page source** (In Safari on macOS right click on a page and select `Show Page Source`).

Similarly, like in the previous validation, copy the whole page source into your code editor and by using the option search/replace find `http://localhost:1313` and replace it with `https://example.com`.

Then copy the whole code again and head to [Rich Results Test](https://search.google.com/test/rich-results) tool and in **Code** tab paste out the code and click the **Test Code** button.

It shall once again return as follow:

[![FAQ Schema with 1 valid item detected](/images/2023/01/FAQ_1_valid_item_detected.png)](/images/2023/01/FAQ_1_valid_item_detected.png)

Once you publish your pages with questions and answers and you request indexing (each individual) through [Google Search Console](https://search.google.com/search-console), after a few days (24 to 48 hours) you will start seeing your pages appearing in Enhancement sections.

[![Google Search Console FAQ Schema with 28 Valid items](/images/2023/01/Google_Search_Console_FAQ_28_Valid_Items.png)](/images/2023/01/Google_Search_Console_FAQ_28_Valid_Items.png)

Here is how it looks on my example page that [contains questions](https://www.andrewsfasteners.uk/quality/frequently-asked-questions/). Each question is referring to each FAQ page.


## FAQ on a single page with details disclosure element

Sometimes you may have plenty of questions and answers gathered. None of them fit into separate pages approach but putting them on a single page will create a chaotic document. Sometimes it will work when it's implemented with a Table of Content, but in other cases may not.

When it's not working for you, you may implement [details disclosure element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details).

Each question will be displayed on the page but the answer will only be presented (for the user) when the user will click on it. Search engines will see whole questions/answers without the need for additional interaction.

This is how I did it on one of my websites.

Repeating the main part, where in layout, by using frontmatter parameter `faq: true` we specify when `itemscope itemtype="https://schema.org/FAQPage"` will appear.

```html
<section id="content"{{if .Params.faq }} itemscope itemtype="https://schema.org/FAQPage"{{ end}}>
      {{ .Content }}
</section>
```

On our page, we will be using a single shortcode (in the first method there were two shortcodes) with a parameter. The shortcode will wrap each question containing an answer. The parameter will be a question and the rest between shortcodes will be an answer.

This will look something like that:

```markdown
{{%/* faq-details "## Customers asking me how to do this fancy thing? {itemprop=name}" */%}}
To make this fancy thing you need to have this fancy stuff.
{{%/* /faq-details */%}}

{{%/* faq-details "## What fancy stuff do I need? {itemprop=name}" */%}}
You will need fancy elements and fancy liquid.
{{%/* /faq-details */%}}
```

It will look less pretty, especially if you preview your markdown files offline, but when served with Hugo all will function as planned.

I am using, inside the shortcode parameter, markdown `##` to render the heading and markdown attribute `{itemprop=name}` [as described earlier](#customising-heading).

The `faq-detail.html` shortcode looks as follows:

```html
<details itemscope itemtype="https://schema.org/Question" itemprop="mainEntity">
  <summary>{{ .Get 0 | markdownify }}</summary>
  <span itemscope itemtype="https://schema.org/Answer" itemprop="acceptedAnswer">
    <span itemprop="text">
      {{ .Inner }}</span>
  </span>
</details>
```

> Noticed that `<span itemprop="text">` is on its own line but `{{ .Inner }}` and closing `</span>` together. This is quite essential as if we want to maintain formatting dictated by markdown, that's how it needs to be. Also, the closing `</span>` after `{{ .Inner }}`, as for some reason it is below it's getting displayed as text on the page.

Doing code validation in [Rich Results Test](https://search.google.com/test/rich-results) we will achieve the same output as in the [first approach](#faq-on-single-page), a single FAQ page with multiple questions and answers.

Here is how it looks on my example page [paraplan.com.pl/kontakt/pytania-i-odpowiedzi/](https://www.paraplan.com.pl/kontakt/pytania-i-odpowiedzi/) (Polish).

---

As mentioned.

This is a guide on how I implement FAQ on three different websites in three different layouts and approaches. I am curious how you can do yours. Share your thoughts below if you want.


---
## Wednesday
- **URL:** https://dariusz.wieckiewicz.org/en/wednesday/
- **Date:** 2023-01-04
- **Tags:** Wednesday, Wednesday Addams, Netflix, Netflix Series, Vivaldi, Four Seasons Winter, Wednesday Plays The Cello, Wednesday playing cello, Nothing Else Matters, Apocalyptica, Sarcasm, Season 1, Comedy horror

### Content

Everybody is amazed by Netflix TV Series Wednesday and I can confirm that it’s justified.

This TV series is a bit different, a bit odd, but that kind of odd that we didn't expect.

<!--more-->

Let’s say this clearly, this TV series is not for anybody below 12 years old (as per rating), and not because of the content but more about the dialogues and the context, catching in many times on sarcasm which is without a doubt hard to understand for kids. Some adults will struggle to understand some bits.  It starts with the piranha scene and goes further and further right to the end.

My daughter (10 years old) didn't catch things that made me and my wife laugh, no surprise. I don't think anybody younger will do. That’s not all. There are plenty of high-end dialogues that are very refined and curated for an adult audience.

Even if you managed to go through the first season, even if you don’t understand half of the dialogues, you can still cherish this essence of the music experience with a deep touch. Like a Wednesday scene with a cello on the rooftop and [Vivaldi Four Seasons: Winter](https://www.youtube.com/watch?v=sbgpF7gb9ds) followed by sentimental [Nothing Else Matters version by Apocalyptica](https://www.youtube.com/watch?v=mjvGjUovxPU) on other one.

The show is, back to the top spot of Netflix shows for the third time, and I don’t doubt why. The show deserves it and definitely, and everybody will look for Season 2. Sometimes we need some grim humour with a horror story behind it.

I have been quite sceptical about the show and all the fame that it gains. I expect that the show will be different, scratching the surface of Stranger Things and other this type of shows, but no, the show is indeed different, a good different.

It’s a less scary move and more something, that it’s hard for me to explain. It is much deeper and unique in its way. The term "comedy horror" doesn't sound right either, even though you can say it's "fun".

Wednesday is a huge achievement but also the requirement to keep it going. The bar is set very high and everybody will expect nothing less in the next season... if ever. Of course, if interested parties finally settle who will air and when.

This is how the show shall be made of. It doesn't need to catch your attention from the beginning, but if it does, it will suck you and take all your blood and replace it with the grim taste of Beetlejuice.

As you think that you sort the whole story after one episode there is twist after twist, so in the end, you think you know, but you don't.

Can you say "I knew it" at the end? I wasn't and this is why it holds you till the last episode.

We sometimes need to be that _smart, sarcastic and a little dead inside_ to survive in this world – be like Wednesday.

{{% ads-in-article %}}


---
## 2022 and New Year Wishes for 2023
- **URL:** https://dariusz.wieckiewicz.org/en/2022-and-new-year-wishes-for-2023/
- **Date:** 2022-12-31
- **Tags:** Ukraine, Energy, Inflation, Pay, Past 2022, New Year Wishes, Wishes for 2023

### Content

Ukraine, Energy, Inflation and Pay. That's how we can summarise the whole year of 2022. Here are my wishes for 2023 for you.

<!--more-->

## 2022

This year run fast, really fast. We barely started and it was supposed to be a glorious time when we start recovering from COVID times but in the end, now we know it wasn't.

We started with the idiot Putin who decided to invade Ukraine. Then we go through energy prices hike and threats to everybody before winter. Inflation (price rises) hit everybody and by the end of it justified strikes of mail and health service workers.

The people in power instead of solving problems steal as much as they can. In the end, they will be blaming others for their actions, how convenient.

Let's put this all behind us (apart from Peace for Ukraine) and try to start fresh. Let's start 2023 as a year for **recovery** in a wide aspect of that meaning.

## 2023

> There are so many things that we can do.\
> There are so many things that we can learn.

We always got so many promises for ourselves to do in the new year, knowing that many of them we didn't accomplish in the passing one.

Life is unpredictable. If you set million of goals for yourself and you achieve them through the year, you are or very lucky person or you sacrifice something bigger to achieve them.

Sometimes it's worth it to risk and thrive, but in many cases, we need to stop and look back to see what's more important in our life.

I got my ideas for new year goals, but I keep following them with the three most important on top of my list. 

### Family

I could not achieve many of my life goals without my wife, kids and other people close to me. Sometimes I need to decide to give up and sacrifice my goals to make sure that my family is always fulfilled. 

Without family, there may be no further goals and the road of life may become more challenging. Let's remember, that there is nothing more important for us than the person who is close to us, who understands us, who shares our passion or who guides us through a difficult time.

This doesn't necessarily need to be a "family" (in that meaning), but the person, who cares about us, who will be close to the term of "family", that we shall treat them like that.

I am lucky enough to have my best friend on my side, my wife.

We can annoy each other face to face but we got our backs all the time when life is challenging us.

I wish many people would experience this in their life. Instead of criticising our other half behind their back, they would listen to themselves and threaten themselves as best friends. Friends don't put themselves down behind backs, they embrace themselves and their friendship.

I wish that people will understand that family is the most valuable asset that we should cherish. In the new year, we shall look at that as the main thing on the goal list.

### Financial stability

Then we go to my second thing, which relates directly to the first (family), which is financial stability and is **nothing** about being rich.

We don't need to be rich to achieve our life goals. Money helps, but never solves problems.

If we can earn enough to make sure that our family is financially secure with options for the future, that's all that is needed.

We all would like to earn a lot, but there is nothing better than financial stability and the security of our lives and our family.

If we can secure financial aspects and our family, then we can achieve other goals in life. 

These two life priorities, when secured, are opening the doors to all possibilities that we may face. Our goals, which we never thought we can achieve, suddenly will be within reach.

{{% ads-in-article %}}

### Things we love

We all shall have something that we love to do, that we can afford to do and that our family is behind us supporting us in it. 

A hobby is a huge part of our live to achieve self-esteem. Self-realisation with the support of close ones is the key to a good life.

**We may be poor but rich at the same time.**

Being rich by having somebody on our side will work better than winning the lottery.

I would like never to be rich if this could jeopardise what I already have.

I wish that people will understand that, that we shall look to be a better person to ourselves and others rather than to be rich and disconnected from reality like so many people recently.

We all shall have a passion that we follow.

---

Based on these things, I am wishing you and your **family** to be together, **financially secure** and fulfilled in **self-realisation** in the thing you love.

And of course... **world peace**.


---
## Apple TV 4K (2022) – good gaming console with missed opportunities
- **URL:** https://dariusz.wieckiewicz.org/en/apple-tv-4k-2022-good-gaming-console-missed-opportunities/
- **Date:** 2022-12-30
- **Tags:** Apple TV 4K, Apple TV 4K (2022), Controllers, Apple Arcade, gaming console, playing games, Controller required, App Store, Apple, developers

### Content

Everybody is writing down about the latest Apple TV 4K 2022 model as a perfect premium box for streaming movies. Due to the upgraded main chip and (already) wide support for controllers, everybody is forgetting that this is quite a decent gaming box as well.

I purchased my Apple TV 4K (2021) with the idea, to get back to playing games on a big screen. I don't have time to invest in game consoles anymore and, for occasional playing, Apple TV as a game console would be a good alternative.

<!--more-->

When I got the 2021 model, I chose the 64GB model for this purpose, as I knew that games weigh a lot and I would need a lot of space.

I already have an Xbox One controller that works with my iPhone, so I just connected it to Apple TV and was ready to play games that support controllers.

The 2021 model has been packed with an A12 Bionic chip, which hasn't been the latest one but shall be enough for my needs. I shortly realised that on some games (Pathless for example) there is a lack of processing power, but on the majority, it's more than enough.

When Apple released the latest model in 2022 they made a huge jump not only in processor (A15 Bionic), which gives 50% extra performance and 30% greater graphics performance but what they did also is to increase top-tier available storage. From last year's configuration of 32/64GB, we got an option to 64 GB/128 GB.

Of course, I went with 128GB. It's not only because I needed storage (after a few games a box has been already screaming for more), but also because only on this model are you getting an Ethernet port available — the other support only on WiFi connectivity.

The best in that was the price. A £169 for top tier Apple TV was a very good deal. I know that many of you can claim, that you can get something better for that, but let's consider the simplicity of the setup. Apple TV 2022 is significantly smaller and lighter than the 2021 model. 

This smaller and lighter design comes with a cost. Once playing for a longer time in graphic demanding games like [Gear.Club Stradale](https://apps.apple.com/gb/app/gear-club-stradale/id1544427904) you may experience an unexpected drop in frame rates for a short period. This is a bit of a surprise, as iPhones are a bit more packed, and my 13 Pro Max, which has the same processor doesn't act like that.

I care about my iDevices, so when new ones come I can still get a decent return from selling the old ones.

This time was no different. By selling on eBay I managed to recoup 60% of the money that I spent on the new one. This was a decent upgrade considering that everything become more expensive these days.

With more storage, I have been able to download more games to try without the need to remove others.

As a subscriber of Apple One, I got access to Apple Arcades where I can move playing from the screen of my iPhone to a large 4K TV screen and cherish the performance and experience.

> When I was writing this text [I learned something new](https://www.macrumors.com/how-to/apple-tv-screenshots-video-mac/) about Apple TV which was a screenshot taking. With the use of MacBook Air M1, I have been able to connect to Apple TV through QuickTime Player to do screen recordings and screenshots. This was a really useful feature for adding images to relevant articles about Apple TV.

There is one problem. The whole of 2022 was an **Apple and developers** year of **missed opportunities**.

We are still in the period, where car manufacturers are releasing supercars to drive them on ordinary roads. Supercars need to drive on the race track and if you buy them, you know where you going on a Sunday morning.

With Apple and Apple TV (but also Mac computers with Apple chips) the problem is, that they are missing the ability to use this "race track".

The most popular games are only cross-available between iPhone and iPad. Very rarely there are any available for Apple TV. Without Apple Arcade, the whole gamin ideology with this box would be... poor.

I am disappointed with the developers that they did not allow games like Minecraft to be downloadable and playable on Apple TV, the same as on Mac computers with Apple Silicon.

Partially I understand that, as they would benefit more from selling the same games for different platforms – gaming consoles, however, from a user perspective this sucks.

With current horsepower under the hood not being able to use it in full is not a good marketing point.

Imagine what spike Apple would have in the sale of Apple TV boxes and Mac computers when people know that they can play Call of Duty on these devices with a controller.

{{% ads-in-article %}}

Microsoft and Sony would profit even further by selling controllers that can be used with them.

If I can play games like Rush Rally 3, why can't play Need For Speed which is available on my other devices?

The games are already ready and working well with controllers, so let's give them hype on a big screen.

This win-win situation is like a dog on a leash. 

We saw this over the last years when a dog (car manufacturers) was held on a leash by petrol empires preventing quicker implementation of electronic cars. A recent year or two put more towards the change than I saw so far in my timeline.

As we reach year-end and New Year wishes, I wish Apple and developers to make a change towards improving the availability of the most demanding games on other Apple devices.


---
## Milestone reached - 40
- **URL:** https://dariusz.wieckiewicz.org/en/milestone-reached---40/
- **Date:** 2022-12-20
- **Tags:** Milestone, Level Up, Level 40 Unlocked, Survived, Friends, Friendship, Knowledge, Life, Lifetime

### Content

I survived!

I should be proud that I reached 40. Some people, some of my friends, will not be able to say that.

It doesn’t matter what’s in the past, we are here and now and we moving forward hoping to change the world for the better.

I reached half of my lifetime, or at least I hope so. I would be very grateful if in further 40 years my mind will still be here and I will be able to see how the world changed.

So far I learned a lot, and even more, I will learn in the future.

What I know already, at this age, I want to share with you.

<!--more-->

## Don't waste time on fake friends

Life is too short. Friends shall "lift" you, not put you down.

Your friends from 10 years ago don't necessarily need to be your friends today. Life changes and people's perception of the world with it. Find your people, your tribe, your real friends.

Have a sit, reflex and look around you. See who is there for you when you need them and who is only there when they need something from you.

Friendship is not a give-and-take relationship. Being present for the other person when they need the most is what is important.

## Know who is your true friend

Remember who is here for you. The word friend is a very powerful word. Calling somebody a friend doesn't always have that same meaning from one person to another and adding somebody to a friend list doesn't necessarily mean that you are friends. You know each other, but you are far away from being friends.

Your closest friend is your family. My other half, my wife, is my dear friend, my best friend! This connection is slightly different, much deeper. 

If you looking into the meaning of friend, look outside of your family.

See, who you can call in the middle of the night and who will answer your call. Who, when you call, will spend hours talking to you just to make sure everything is ok. You may not talk with each other every single day, but when you fill the need to say "hi", without any other reason behind it, that is something more. That's friendship.

Being a friend is not only about being for other people, it's the feeling when you are with that person or when you talk about that person or even think about it. 

## Identify your friends

When you meet with your friend, when you talk with them, you shall feel light. Your soul shall feel lifted and your purpose as a person shall be filled with the feeling of fulfilment.

Avoid friends who drain your life energy. Our life is too short to waste it on them. Move along and find true friends. 

Somebody may feel touched that suddenly you are not for them. I hope that if they look back, they will understand that they were not for us, they were not our friends.

Your friend will be for you. It doesn't need to be here every time, but always when they are, you have this filling inside. It changes you, it brings optimism and joy to your soul.

## Remember who is your friend

I, as a friend, will not say nonsense just to make you hear what you want to hear. As a friend, I can tell you straight to your face what I don't like about you. We may have an exchange of arguments, but we always value each other's opinions. Not necessarily need to agree with it, but we value it.

Somebody said this important sentence.

"The true friend will tell you what they think about you, in your face, and not behind your back!" Let's remember that!

## Young mind in an old body

At the age of 40 I know one thing, I may be 40, but my mind feels like I have been in my 20s all the time.

I haven't grown up.

Inside I am a child, mature, but still a child.

I learned how to coexist in the adult world, but inside I would like to make a funny thing, be silly. Only my body reminds me that I am not as young as I feel and then I feel it... deeply.

But, sometimes is good to be like that. Having a young soul in an old person's body can help others when they need it the most.

## We don't know everything

We are not experts in everything but in the profession that we doing. We try to be the best and we don't like to show weakness, especially in the lack of knowledge.

I understand that well. After I graduate from University I thought that I knew everything and I would not admit that something that I think is right can be wrong. I thought that this will show my weakness.

Right now, I am not afraid to say, that I don't know. I know my value and know what knowledge I have. Some people can be better than me at something, and they always will be. The young generation will know more about the future than I know right now. I don't need always to be right. 

I can get involved in a discussion about something that I am not an expert on, but to the point where my knowledge is exhausted, I will stop and say that I don't know.

**I will say, or at least I will try to say that I don't know.**

It's not easy and it hurt inside to admit to our weaknesses, but at least we do not pretend.

Rather than trying to spread gossip, or even worse, create them with our little minds, let's admit that we are not experts in everything. 

**Lying is a short-term solution.**

{{% ads-in-article %}}

If you don't know something, admit that, but don't finish at this point. Try to learn and gain knowledge, so next time you can share it with others.

We need to remember that at our age, there will be more and more people who knew more than we are. We are not able to learn everything and we need to admit that. We will not like it, but that's life.

We have been born without knowledge and when the time comes we (hopefully) understand, that we still don't know everything. 

---

My only wish for myself is to reach another milestone and be this old, grumpy guy, who's making everybody as proud as embarrassed at the same time.

I only hope that life will allow me for that.


---
## Adding Mastodon discoverability by e-mail address
- **URL:** https://dariusz.wieckiewicz.org/en/adding-mastodon-discoverability-by-email-address/
- **Date:** 2022-12-19
- **Tags:** Mastodon, discoverability, Netlify, Hugo, WebFinger Protocol, Redirects, WebFinger Lookup

### Content

Through the “interesting” days when people started migrating to Mastodon, I found a quite interesting [toot](https://hachyderm.io/@shanselman/109537851479089923) from one of its users, where he mentioned adding Mastodon discoverability for any domain using the WebFinger protocol.

I have been quite interested in how to implement this on my end, as I prefer people to discover me through my long-standing email address rather than a newly created username on a selected Mastodon server.

As my website is hosted on [Netlify](https://www.netlify.com), I decided to check if I could implement this. Here’s how it goes.

<!--more-->

---

For a better understanding of how Scott achieved this on his end, I referred to his original post[^1]. I read some more information about the [WebFinger protocol](https://en.wikipedia.org/wiki/WebFinger) on Wikipedia and then recalled [John Mueller’s post](https://johnmu.com/2022-mastodon-for-your-domain/) from not so far back, where I found a conclusive solution for myself.

[^1]: [Use your own user @ domain for Mastodon discoverability with the WebFinger protocol without hosting a server](https://www.hanselman.com/blog/use-your-own-user-domain-for-mastodon-discoverability-with-the-webfinger-protocol-without-hosting-a-server)

---

Before starting, I need to explain a couple of things.

As mentioned at the beginning, I would like people in the Mastodon network to be able to discover me by my email address rather than a specific username in the Mastodon network (currently `@dariusz_wieckiewicz@mastodon.social`).

I am not using my main domain for my website. My site is served on the subdomain `dariusz` of the domain `wieckiewicz.org`, which is also used to resolve my email address.

Mastodon uses the [WebFinger protocol](https://docs.joinmastodon.org/spec/webfinger/) to discover users.

When using tools like **Lookup WebFinger**, located in the top-right part of the [WebFinger](https://webfinger.net) website, you can type an email address to see how it resolves.

As you will see at the start, Lookup WebFinger will look into the domain that is part of your email, as follows:

```
GET https://wieckiewicz.org/.well-known/webfinger?resource=acct%3Adariusz%40wieckiewicz.org
```

As my website is static, using [Hugo](https://gohugo.io), I don't have real server functionality to add dynamic responses. To handle this dynamic request for WebFinger, I decided to utilise what John mentioned in his [Apache & co](https://johnmu.com/2022-mastodon-for-your-domain/#apache--co) section – **redirects**.

## Redirect method

I already have some redirects in place for my main domain. If you type `wieckiewicz.org` in your browser’s address bar, you will be 301 redirected to `dariusz.wieckiewicz.org`. I am doing this with a `_redirects` file located in the `/static` folder of my Hugo-based website.

```
https://wieckiewicz.org https://dariusz.wieckiewicz.org 301!
https://wieckiewicz.org/* https://dariusz.wieckiewicz.org/:splat                      301!
```

These two rules will not only redirect the main domain but also all links where the subdomain `dariusz.` is missing in the URL.

The original request sent by WebFinger looks as follows:

```
https://wieckiewicz.org/.well-known/webfinger?resource=acct:dariusz@wieckiewicz.org
```

As you may have noticed, symbols such as `:` and `@` are replaced by their Unicode equivalents for compatibility reasons.

We need to keep this in mind when composing a redirect rule in our `_redirects` file to ensure that nothing unintentionally breaks.

> Theoretically, a reference to `.well-known/webfinger` should be sufficient, but some sources, including John, also refer to Web Host Metadata (`.well-known/host-meta`) and Node Info (`.well-known/nodeinfo`), so I will include them as well.

Between the two rules mentioned above, I inserted the following:

```
https://wieckiewicz.org/.well-known/webfinger?resource=acct%3Adariusz%40wieckiewicz.org         https://mastodon.social/.well-known/webfinger?resource=acct%3Adariusz_wieckiewicz%40mastodon.social     301!

https://wieckiewicz.org/.well-known/host-meta?resource=acct%3Adariusz%40wieckiewicz.org         https://mastodon.social/.well-known/host-meta?resource=acct%3Adariusz_wieckiewicz%40mastodon.social     301!

https://wieckiewicz.org/.well-known/nodeinfo?resource=acct%3Adariusz%40wieckiewicz.org          https://mastodon.social/.well-known/nodeinfo?resource=acct%3Adariusz_wieckiewicz%40mastodon.social     301!
```

This may look a bit complicated, but if you have more users on your domain and these users use different servers in the fediverse, it will be easier to add them without restricting them to one instance (server).

Here you can see that when WebFinger requests a response from `.well-known/webfinger?resource=acct:dariusz@wieckiewicz.org` on my domain, it will be redirected to `mastodon.social` and my username there, `dariusz_wieckiewicz@mastodon.social`.

Once the redirect is active, the [WebFinger Lookup service](https://webfinger.net) should return the response for the correct user on the `mastodon.social` server.

> Remember, before applying any `_redirects` in production, check them using [Netlify’s Playground](https://play.netlify.com)!

{{% ads-in-article %}}

## Single file method

Using the redirect method is a bit ambitious. If you are looking for a quick and simple solution, [Alex Guyot on Mastodon](https://mastodon.macstories.net/@alex/109836437717763915) came up with a **dirt simple** solution by faking a WebFinger protocol response served from our domain.

The solution involves creating a `webfinger` file inside the `.well-known` folder (with a dot at the beginning).

By obtaining a response from the same file on the selected Mastodon server, we just need to copy, paste, and save it into our dummy file.

Using the following part of the path, we can get a JSON response from the Mastodon server:

```
/.well-known/webfinger?resource=acct:yourusername@mastodon.host
```

For example:

```
https://mastodon.social/.well-known/webfinger?resource=acct:dariusz_wieckiewicz@mastodon.social
```

This will give you a simple response:

```JSON
{"subject":"acct:dariusz_wieckiewicz@mastodon.social","aliases":["https://mastodon.social/@dariusz_wieckiewicz","https://mastodon.social/users/dariusz_wieckiewicz"],"links":[{"rel":"http://webfinger.net/rel/profile-page","type":"text/html","href":"https://mastodon.social/@dariusz_wieckiewicz"},{"rel":"self","type":"application/activity+json","href":"https://mastodon.social/users/dariusz_wieckiewicz"},{"rel":"http://ostatus.org/schema/1.0/subscribe","template":"https://mastodon.social/authorize_interaction?uri={uri}"}]}
```

Copying, saving, and serving the file in `/.well-known/webfinger` will do the trick.

Dirty simple, yet it works well, so why not give it a try.

---

It's time to check if other users can search for us (find us) in the Mastodon network using our original email address without knowing exactly on which server we created our account.

> Try searching for me by typing my website address, but insert an `@` symbol between my name (`dariusz`) and my surname-domain (`wieckiewicz.org`).

This gives us the flexibility to move between instances, and people who do not follow us can still find us using our original email address. Of course, this works as long as we keep our WebFinger file redirect up to date.

Why not **try**, **find me**, and **say hello**!


---
## Enough is enough. Bye Twitter.
- **URL:** https://dariusz.wieckiewicz.org/en/enough-is-enough-bye-twitter/
- **Date:** 2022-12-14
- **Tags:** twitter, leaving twitter, quit twitter, deactivating twitter account, hate speach, mental health, depression, anxiety, burnout

### Content

After reading today's Guardian post about [Twitter abruptly dissolves safety council moments before meeting](https://www.theguardian.com/technology/2022/dec/12/twitter-safety-council-dissolved-before-meeting) followed by continuously growing hate speech on the platform I decided that I got enough.

<!--more-->

I don't have time to deal with this anymore. All these things going on around Twitter are only causing more and more anxiety which negatively impacts my mental health.

Similarly, I reduced my interactions on Facebook years back, this is similar, but as long as I delayed this, thinking that there may be something positive still, I was wrong. The only good thing is to leave this toxic place.

There are more important things in the world, like family than bothering a guy with problems (and a big ego), who thinks that money can buy everything.

This guy, whose name is not worth mentioning, thinks that he can behave however he wants, only because he got money and power.

Disrespecting people, and their opinions, crushing their lives and allowing the spread of violence and hate speech is enough for me.

Whatever he saying is not worth as much as a long-term weather forecast. I would not pay a penny for it. He said that he will not block somebody's account then he blocked out of the blue. He has been saying that the thug will not be allowed back, and then he is back. Pathetic!

I tough about Twitter as a place where information prevails, but now I feel ashamed to be a part of this platform since he took over and put mud on the table.

There are so many people there who still think that there may be a chance for this platform. I have this hope as well since he took over but now I think it is just another dead bird.

I agree with Nicolas Magand who said most politely, that [**he is dangerous**](https://thejollyteapot.com/2022/12/14/a-few-thoughts-on-elon-musk).

In the past, I tough that this guy's achievements can be praised, but after learning the truth, that none of them is his, I changed my vision about him drastically. He is simply a con man. 

He is a bad seed like Coca-Cola man was for Apple in the past. When people realised that, it was too late.

Luckily, some companies have been able to bounce back but I am unsure now that Twitter will be able to.

Some mention that [Twitter will lose 32m users in two years after his takeover](https://www.theguardian.com/technology/2022/dec/13/twitter-lose-users-elon-musk-takeover-hate-speech) and I will not be surprised if that happens.

Going back a couple of months, when I visited, with my daughter, a couple of high schools to help her make the right decision for the future, it struck me on some of them have in their goals that they will help a child to create their own Twitter account.

This was before this guy's takeover, so this wasn't as scary as it is now. I only hope that in the current situation schools will rethink putting this type of social media into their curriculum.

I look forward to seeing how schools, places where respect shall be promoted, will react on a portal, where respect is fading and hate is rising.

If needed, as a parent, I will initiate an open letter to the headteacher to highlight why this portal shall not be considered in a place like a school, where values shall matter.

I am saying goodbye from Twitter but that doesn't mean I will not return in future if things return to normal, or if I will be forced to return...

{{% ads-in-article %}}

I can still be contacted in plenty of ways but for now, Twitter will not be one of them.

Let's finish this short post on text from Forbes [Don’t Let Social Media Destroy Your Wellbeing](https://www.forbes.com/sites/tracybrower/2022/12/11/dont-let-social-media-destroy-your-wellbeing-5-ways-to-manage/?sh=2b88e7c66460)

> _"Social media (...) can overwhelm you with bad news, take you away from connections in real life and result in depression, anxiety and even burnout."_ 

If any social media, not only Twitter, causes you to feel worse each day, it's time to disconnect from it for good. Some so many young people taking their own lives because of that is scary. Disconnection is not easy, but sometimes necessary and can be in matter of life or death.


---
## Playing with password protected Microsoft Excel files
- **URL:** https://dariusz.wieckiewicz.org/en/playing-with-password-protected-microsoft-excel-files/
- **Date:** 2022-12-06
- **Tags:** Microsoft Excel, Password Protected, XLSX files, XLSM files, Removing password, Protect Sheet, Protect Workbook Structure, Encrypted with Password, Password to modify, Microsoft Visual Studio Code, 7-Zip, ZIP File, XML Files, Office 365, Microsoft 365

### Content

Recently, at work, we have faced an issue where we want to resurrect one of the old Excel files and we found out that, when a file on its own can be opened without any problem, some options, like Workbook Structure or individual Sheets been protected with a password.

The problem was that the person, who initially create the file, was no longer with the company and nobody knew what password was used. As we were able to open the file on its own, as it wasn't protected, knowing about how XLSX (also XLSM) files are constructed, I decided to use the brute method to remove restrictions.

Here's how it goes...

<!--more-->

> Before we move forward, I am not covering here removing passwords from files that are encrypted and require a password to open, as that is not as simple.

The XLSX (and XLSM) files are created in a specific structure, that shortly speaking we can treat them as a compressed ZIP file containing XML files.

We can unpack them like a ZIP file and look for a structure in plain XML files. Thanks to that, by manipulating XML files, we can remove relevant password strings, compress files back into a single file and open without protections.

To do this, we will need a tool like [7-Zip](https://www.7-zip.org).

For purpose of this article, I prepared 4 files.

[![4 Test files prepared for play purpose](excel_files-4_test_files.png)](excel_files-4_test_files.png)

By right-clicking on the file we will be using the **7-Zip** sub-menu (in Windows 11 we need to click at the bottom to show more options and revile 7-Zip) to **Open archive**, **Extract to...** and after work is done, **Add to archive...**.

Starting with the extraction of our XLSX file, we will head into a folder created and see the following structure.

[![File structure of extracted XLSX file](excel_files-xlsx_file_structure_extracted.png)](excel_files-xlsx_file_structure_extracted.png)

Each folder will contain more XML files. These are the files that we will be manipulating.

For manipulation purposes, I will be using [Microsoft Visual Studio Code](https://code.visualstudio.com) and by right-clicking on my folder, with extracted content of the file, I will choose option **Open with Code**.

## Removing password - Protect Sheet

`\Book1-protected sheet.xlsx`

Let's unpack our file by right-clicking and selecting from the **7-Zip** menu option **Extract to Book1-protected sheet** then right-clicking on the folder **Book1-protected sheet** and selecting **Open with Code**.

From VS Code top menu select **Edit** > **Find in Files**, and the search field type word **protect**.

This will bring you a file that contains protection like (`<sheetProtection ...`).

[![XML file with string sheetProtection in VS Code](excel_files-vs_code_sheetProtection.png)](excel_files-vs_code_sheetProtection.png)

Let's remove the whole string, from `<sheetProtection ...` until it's closing tag ` />` and save our file.

Going back to file explorer we head inside our folder **Book1-protected sheet**, selecting all files and folders there and right-clicking on selection, choosing from the 7-Zip menu **Add to archive...**.

[![Compressing back to XLSX file](excel_files-7-zip_compress_xlsx.png)](excel_files-7-zip_compress_xlsx.png)

If it is not selected already, in the 7-Zip window, let's select Archive format **zip** and on top change the desired file name from **Book1-protected sheet.zip** to **Book1-protected sheet.xlsx** and press **OK** to compress.

Now you can open your newly created XLSX file in Excel and your previously protected sheet will be without a password.

_Quite simple, but raising the question, is this protection method shall be so easy to remove in the first place?_

## Removing password - Protect Workbook Structure

`\Book1-protected workbook structure.xlsx`

Similarly to the above let's unpack it by right-clicking and selecting from the **7-Zip** menu option **Extract to Book1-protected workbook structure**, then right-clicking on the folder **Book1-protected workbook structure** and selecting **Open with Code**.

From VS Code top menu select **Edit** > **Find in Files** and in the search field type once again the word **protect**.

This will bring you a workbook file that contains the string `<workbookProtection ...`.

[![XML file with string workbookProtection in VS Code](excel_files-vs_code_workbookProtection.png)](excel_files-vs_code_workbookProtection.png)

Let's remove the whole string, from `<workbookProtection ...` until it's closing tag ` />` and save our file.

Follow into your **Book1-protected workbook structure** folder, select all files and folders there and right-click on the selection, choose from the 7-Zip menu **Add to archive...**.

Archive into **zip** format changing the desired filename to  **Book1-protected workbook structure.xlsx**.

[![Once again compressing back to XLSX file](excel_files-7-zip_compress_xlsx_2.png)](excel_files-7-zip_compress_xlsx_2.png)

Now you can open your newly created XLSX file in Excel and your previous Workbook Structure is not protected anymore.

{{% ads-in-article %}}

## Removing password - Password to modify

Removing passwords from files that require a password to modify the content (but allow to view) can be done in a similar way, but by searching the **password** phrase.

This will look like `reservationPassword="E5F2"`

[![XML file with string reservationPassword in VS Code](excel_files-vs_code_reservationPassword.png)](excel_files-vs_code_reservationPassword.png)

> The password displayed is not in plain text form. 

By removing just this part `reservationPassword="E5F2"` and saving our file, compressing, as before, into our XLSX file it will allow us easily to remove this type of restriction as well.

Similarly, we can experiment with any other restrictions and protection in excel files, especially on files that are freshly converted from old XLS format into new XLSX.

This will however **not work on XLSX files Encrypted and protected with a password**.

## XLSX Files Encrypted with Password

`\Book1-encrypted with password.xlsx`

If you looking into protecting your file more securely, always Encrypt with a Password which will require a password to open a file. This type of file you cannot simply unpack like a ZIP file (or you can, but data will be mangled).

[![Error in 7-Zip when trying to extract Enctyptex XLSX file](excel_files-error_extracting_encrypted_xlsx_file.png)](excel_files-error_extracting_encrypted_xlsx_file.png)

[![File structure of encrypted XLSX file](excel_files-encrypted_xlsx_file_structure.png)](excel_files-encrypted_xlsx_file_structure.png)

For cracking passwords on them you may need to look somewhere else.

---

Even if we cannot remove all restrictions without specialistic software, with the above methods we can at least regain access to some of the restricted files.

> I have tested the above solution with XLSX and XLSM files, but this can also work with other types of files.

Regards.


---
## Adding copyright information for images on Hugo based website
- **URL:** https://dariusz.wieckiewicz.org/en/adding-copyright-information-images-hugo/
- **Date:** 2022-11-07
- **Tags:** Copyright, Copyrights, Copyright Information, Hugo, Images, Google Images, Google Images best practices, Google Search Central, Search Central documentation, Schema, Image metadata, Structured data, Rich Results Test, Licensable badge, findRE, Yummy Recipes UK

### Content

As you are aware, when you create your post with images and publish them on your website, sooner or later they will appear on Google.

Your article will land in Search Results and images will be shown in Google Images.

Sometimes you are taking a lot of effort into your images and restricting their use by providing specific disclaimers or copyright information on your website.

The problem is that Google does not always know that and when you search for an image, that is sourced from your website, the image may be copyright restricted.

The user, who is searching through, will not know that as well and he may come into trouble. This may result in a fine that may need to be paid to the rightful owner.

<!--more-->

Of course, Google protects itself by always adding information under the picture in search results:

> Images may be subject to copyright.

This text contains also a link to [learn more](https://support.google.com/legal/answer/3463239?hl=en) about copyright.

[![YummyRecipes.uk images in Google Image Search](/images/2022/11/yummyrecipes.uk_google_images.png)](/images/2022/11/yummyrecipes.uk_google_images.png)

This not always may be enough, or for us, rightful owners, we would like to inform more about the restricted use of our work.

Luckily, you may add data to Google Image Search results that contain information about copyrights. This is added through structured data (schema) and is very useful, yet not complicated.

Structured data for images can add a link, that will appear under the photo and may contain a reference to the creator, how the image can be used and what are use restrictions (licenses, permissions etc.).

Google describes it in Search Central documentation ([Image metadata in Google Images](https://developers.google.com/search/docs/appearance/structured-data/image-license-metadata)). 

If our images are copyright restricted, by providing information for a licence (terms of use), we may be eligible for:

> "the Licensable badge, which provides a link to the license and more detail on how someone can use the image"

One of my websites, that restricts the use of the images, is [YummyRecipes.uk](https://yummyrecipes.uk) and I have looked into including relevant structured data (not typically visible for ordinary visitors) to make users aware, that they cannot just copy the image and use them as theirs. If they do, they need to be aware of potential legal consequences.

I know, that many users will still don't bother and will "steal" somebody's property and use it as theirs, but better this than nothing, especially if at some point you will decide to pursue your rights.

[Hugo](https://gohigo.io), the static site generator, is such a handful tool, that you can implement plenty of things (way above typical SSG ideology), that can be run on your behalf during the site build. Once all set, this result limits the need for you to do anything extra and just concentrate on the content.

When composing a post in Hugo we use markdown files. All the images are added in markdown form. The idea will be to grab all links to the images from the content of the document and reuse them in structured data form.

Additionally, some images (like featured images), are added by users in frontmatter, hence we will need to get that as well.

At this stage, we will not need to bother with performance and image optimisation that you normally do (serving in various sizes), but just to grab and provide a link to full-size images and add additional data (licence information) along.

> Of course, this part - performance of our images, needs to be already implemented, following [Google Images best practices](https://developers.google.com/search/docs/appearance/google-images), before our images will appear in image search results. I assume that this is already done by you and your images [are displaying there correctly](https://www.google.co.uk/search?q=site:yummyrecipes.uk&source=lnms&tbm=isch).

There are two ways of adding licence information to your photos. You can add structured data or embed information directly into the photo itself. 

I am not a fan of embedding data as this can be easily removed or lost during image processing and optimisation. This is why I am concentrating on Structured data (schema), specifically in JSON-LD format.

My main goal is to add a link to copyright information and a creator of the image (copyright holder).

## Grab the URL for all images

Firstly, let's grab all images per post in Hugo. For this, we can use this handy code for use in our layout.

> Credit to [Joe Mooring](https://discourse.gohugo.io/u/jmooring) from Hugo Community for pointing into right direction.

```
{{ range findRE `(?s)<img.+?>` .Content }}
  {{ replaceRE `(?s).*src="(.+?)".*` "$1" . }}
{{ end }}
```

That will return images URL from the content that we will need to build our structured data.

## Site config parameters

Before we do that, it's worth setting a couple of things first.

You need to have a page where you will describe [Copyright Information](https://yummyrecipes.uk/copyright/), and if you need, specify an additional page, where somebody can contact you requesting rights for use.

I decided, that I need only one page and link to it I provided in my `config.toml` file.

```toml
[params]
	copyright_url = "/copyright/"
```

I already have specified an author (copyright holder) and I will use the site title at some point.

```toml
title = "Site Name"

[params.author]
	name = "Name Surname"
```

{{% ads-in-article %}}

## Schema with image metadata

The initial schema will look as below.

```
<script type="application/ld+json">
[{{ range $k, $_ := findRE `(?s)<img.+?>` .Content }}{{ if $k }},{{ end }}
  {
    "@context": "https://schema.org/",
    "@type": "ImageObject",
    "contentUrl": {{ replaceRE `(?s).*src="(.+?)".*` "$1" . | absURL }},
    "license": {{ $.Site.Params.copyright_url | absURL }},
    "acquireLicensePage": {{ $.Site.Params.copyright_url | absURL }},
    "creditText": {{ $.Site.Title }},
    "creator": {
      "@type": "Person",
      "name": {{ $.Site.Params.Author.name }}
    },
    "copyrightNotice": {{ $.Site.Params.Author.name }}
  }{{ end }}
]      
</script>
```

On the page where I will be implementing it, most posts (recipes) will contain images, but to avoid serving an empty script tag when there are no images, we will add a condition for that.

```
{{ if (findRE `(?s)<img.+?>` .Content) }}
	// our above code
{{end}}
```

## Adding images from frontmatter

If we have images added in frontmatter, like typically featured images, we can add that as well in the following way:

```
{{ if .Params.featuredImage }}

{{- $ftimgsrc := "" -}}
{{ if hasPrefix .Params.featuredImage "/" }}
    {{ $ftimgsrc = resources.Get .Params.featuredImage }}
{{ else }}
    {{ if .Page.BundleType }}
        {{ $ftimgsrc = .Page.Resources.GetMatch .Params.featuredImage }}
    {{ else }}
        {{ $path := path.Join .Page.File.Dir .Params.featuredImage }}
        {{ $ftimgsrc = resources.Get $path }}
    {{ end }}
{{ end }}

 <script type="application/ld+json">
  {
    "@context": "https://schema.org/",
    "@type": "ImageObject",
    "contentUrl": {{ $ftimgsrc.Permalink }},
    "license": {{ $.Site.Params.copyright_url | absURL }},
    "acquireLicensePage": {{ $.Site.Params.copyright_url | absURL }},
    "creditText": {{ $.Site.Title }},
    "creator": {
      "@type": "Person",
      "name": {{ $.Site.Params.Author.name }}
    },
    "copyrightNotice": {{ $.Site.Params.Author.name }}
  }
 </script>
{{ end }}
```

## The full code

In such a way, we will have two parts that will work for us. One will be served if there is a featured image set (via featuredImage in frontmatter) and the second when there are images found in the content.

The code will look as follow:

```
{{ if .Params.featuredImage }}

{{- $ftimgsrc := "" -}}
{{ if hasPrefix .Params.featuredImage "/" }}
    {{ $ftimgsrc = resources.Get .Params.featuredImage }}
{{ else }}
    {{ if .Page.BundleType }}
        {{ $ftimgsrc = .Page.Resources.GetMatch .Params.featuredImage }}
    {{ else }}
        {{ $path := path.Join .Page.File.Dir .Params.featuredImage }}
        {{ $ftimgsrc = resources.Get $path }}
    {{ end }}
{{ end }}

 <script type="application/ld+json">
  {
    "@context": "https://schema.org/",
    "@type": "ImageObject",
    "contentUrl": {{ $ftimgsrc.Permalink }},
    "license": {{ $.Site.Params.copyright_url | absURL }},
    "acquireLicensePage": {{ $.Site.Params.copyright_url | absURL }},
    "creditText": {{ $.Site.Title }},
    "creator": {
      "@type": "Person",
      "name": {{ $.Site.Params.Author.name }}
    },
    "copyrightNotice": {{ $.Site.Params.Author.name }}
  }
 </script>
{{ end }}

{{ if (findRE `(?s)<img.+?>` .Content) }}
<script type="application/ld+json">
[{{ range $k, $_ := findRE `(?s)<img.+?>` .Content }}{{ if $k }},{{ end }}
  {
    "@context": "https://schema.org/",
    "@type": "ImageObject",
    "contentUrl": {{ replaceRE `(?s).*src="(.+?)".*` "$1" . | absURL }},
    "license": {{ $.Site.Params.copyright_url | absURL }},
    "acquireLicensePage": {{ $.Site.Params.copyright_url | absURL }},
    "creditText": {{ $.Site.Title }},
    "creator": {
      "@type": "Person",
      "name": {{ $.Site.Params.Author.name }}
    },
    "copyrightNotice": {{ $.Site.Params.Author.name }}
  }{{ end }}
]      
</script>
{{ end }}
```

## Validation

The last step will be a validation using the [Rich Results Test](https://search.google.com/test/rich-results) tool.

If all goes well, we shall see a new position called **Image metadata**.

[![Rich Results Test with detected Image Metadata for 8 valud items](/images/2022/11/rich_results_test_image_metadata_8_valid_items_detected.png)](/images/2022/11/rich_results_test_image_metadata_8_valid_items_detected.png)

Of course, the change in Google Image Search will not appear straight away as Google Robots need to crawl new information, but at least it's there already.


---
## A short story about life
- **URL:** https://dariusz.wieckiewicz.org/en/a-short-story-about-life/
- **Date:** 2022-10-30
- **Tags:** life, virus, mother earth, sustainability, humans, universe, adapt to change, fate, from generation to generation, die, reborn, inevitable, plague

### Content

We are living in a world that feeds us and looks after us but also kills us.

The air that we breathe gives us life and the same air is killing us slowly.

We destroying our planet so it can destroy us much quicker.

We are like viruses and mother Earth is creating new things to kill us. It needs to kill us so we don’t kill her first.

<!--more-->

We need to die so the planet could live.

It survived millions of years and killed millions of species that threaten it.

We are more resilient and we are in billions, like flies, but still, we are very weak.

We call ourselves an intelligent species but we are so dumb in preventing the inevitable. Our certain extinction.

If you ever tried gardening and if you look at how much this planet is giving us, and how little we giving it back, you will be mind blown.

From one seed we get a whole plant with a fruit that feeds us.

The planet is more self-sustainable than we are. We thinking about sustainability but we don’t have an idea what’s that. We cannot learn from the past so how we will know now and in the future?

Among our species, some see, that we are just a tiny part of the universe. They know that our species need to adapt and change the way how we cherish our life as a guest on a piece of rock called earth.

Sadly, rarely does anybody is listening to them and we keep doing our devastation and sealing our fate.

Not only we killing each other, but we killing our piece of stardust created in our part of the universe.

From generation to generation we become tougher yet weaker - still dumb.

We are doomed, but we cannot acknowledge it yet. 

We will try to survive for a further hundred years until we decide to kill another piece of stardust far away from our own leaving this old rock to die or to be reborn itself without us in another billion years.

We haven’t been created by the all-mighty like some can praise. We have been created from the same dust as our rock which we stamp every single day. To the same dust, we turning from generation to generation.

We may not remember the times of the supernova. We may vaguely remember, through all the rumours passed from ear to ear and mouth to mouth, that there was a species that starts the path towards the inevitable.

If we just could stop for a minute and look at what we doing, we could find that we are the plague that infested the third planet from the sun.

Nobody will be surprised to discover, that the other planets in our solar system are just leftovers from our ancestors who destroy them before our time come. It’s time for us to destroy the last dying star.

But nothing is lost in the universe. As we try to defend ourselves, the stardust is constantly trying to do the same.

Like somebody said, “what doesn’t kill us… will mutate and try again”.

Every single day we find a new way to do the same so let’s don’t think that mother nature is not participating in a war called life.

{{% ads-in-article %}}


---
## The only thing you need to do is to try...
- **URL:** https://dariusz.wieckiewicz.org/en/the-only-thing-you-need-to-do-is-to-try/
- **Date:** 2022-10-27
- **Tags:** try, opportunity, thrive, infinite game, long-term mindset, exceeding potential, learning something new, sell ice to Eskimos, leadership, trying times, being a part of something, family, team, leaders, finite game, it pays the bills, management, think differently

### Content

Someone said, "the only thing you need to do is to try".\
What I would add from myself is to "put a whole heart" into your "try".

From this perspective, you can achieve wonderful things, but there is one problem with it. You need to find the other end to give you this opportunity to “try”.

<!--more-->

We may not always be skilled in what's required, or maybe we are good in a wide range of things, but not the best in this one specific.

If you are such a person, you know what I mean by saying, that it's hard to "try", as not a lot of people want to allow you to do this, worrying that you will not be good at it.

Sometimes you "tried so hard and got so far", but in the eyes of the other end "it doesn't even matter".

"One thing" that may put you down is that "it doesn't even matter how hard you try" if there is no will to put a risk on the table, there is no option to "try", and there is no opportunity to thrive.

How often do we want to get someone to do the job, someone skilled in a task, rather than getting "an average person" and letting them "try"?

In the current world we looking into quick gain, instead of thinking about the long term. I know that from both sides.

Like [Simon Sinek](https://www.youtube.com/user/SimonSinek) well said, it's all about the right mindset. The infinite game mindset is the key to long-term success.

You can see that in the recruitment environment. Either if you are recruiting or you trying to be recruited.

We all, including myself, looking for an employee, for the position that we are filling, to get all the right skills to do the task from day one or shortly after.

We doing this, because we know, how much time and effort we need to put into ordinary people to get them up to speed - trained adequately.

The problem is when these people don't least. You put a precious time and share your knowledge, and the person is just waking away. Or, you give up your precious time to interview the person, and that person does not even bother to show up.

A couple of years back we would not mind hiring a less skilled person, putting time and effort into training or just giving them to “try” and see.

I remember my coworker who was delegated to work with me after "trying" in other departments. He got the right mindset from the start, independently of what type of job he meant to do. He wants to do his job, at the highest level possible can (of course, with the right training by the right people), and that worked.

He receive an option to “try” and he did it. He got a long-term mindset oriented toward exceeding his potential and learning something new.

If we looking into achieving something at a quick pace, we need somebody with the right level of experience and knowledge, who, with just a minimum input will offer maximum output.

In some positions, this will work. Have a look at various salespeople. Hiring somebody who can "sell ice to Eskimos" will work well in short term as well as in long term, as long this person will find it interesting.

Knowing your value, and how good you are at what we doing is important, but this raises a problem as well, at least for the employer.

At the point when an employee knows his value, he can dictate his requirements (in many cases it's all about the money).

At some point, there is no further option for the employer to offer anything more (or extra money is not the solution) and the employee leaves for a place, where they are offered what they want or where they can thrive.

Employees who come with a "try" approach to doing the work, think differently. They know that they are not "perfect" candidates and they need to learn a lot to get to the point when they can say, that they can do their job right.

With the right mindset of the organisation, and what's important, with the right leadership, both parties will benefit.

At times of struggle, both ends will work together to find a solution, to help each other.

Imagine being in a company that suddenly struggles, cannot afford to keep employees and does everything that it can to keep business going. 

With the right mindset and leadership, employees will work towards getting things back on track. They will try to help, even if they will need to sacrifice something, that, in the material world we live in, is more important "than being a part of something".

Having a feeling that what you are doing is important, and that the place where you can show your skills and thrive makes you feel like "family", will keep you going. 

Every company got ups and downs. What's important is to look, at which employees will stay with the company in "try" times, and which ones will decide to leave.

If you hire a perfect candidate, in times of "try", they are more likely to leave, as they know their value and expectations, and they are not patient enough to see what the future will hold.

The average candidate, who received more from the company in their personal development, comparing what they have been able to offer at the beginning, is more likely to stay in "trying" times.

These "trying" times are crucial for building the team for the future if the leaders got the right mindset.

Employers need to be a leader. They need to inspire people and share their vision and mindset through which they will encourage them to stay in trying time, even when the competition offers something better. 

If the leaders know what game they are in, and do not just think about how to balance the books, they will know where they are heading. They will be able to communicate their vision with others in such a way, that they will inspire them, that even if right now is "hard", there is a bright future for us.

But when leaders failed to lead and their mindset in "try" times is changing to a finite game, the spark that they shall maintain in their employees starts fading. With a changed mindset, the employee also will change theirs. Even those who know, that they put their whole heart into what they have been doing, will start thinking about the job in a way, "it pays the bills", and that is all. 

This is where the employees, who think about the job like a "family" will move where they can find this feeling again. Possibly with different business.

It is not easy to extinguish the spark in a person with "try" in their heart. Sometimes some benefits may light this and give fuel to go further.

This fuel will sadly not least in infinity. We need leaders who will lead us. We may have as much fuel, as leaders put into "leading".

When "leading" changes into "management" the infinite game-changing into a finite game and the job becomes a place that just "pays the bills".

The spark fades and people leave.

It’s difficult to leave something behind if you put so much into it. All your passion and enthusiasm worked toward further development through which the company benefit. It’s hard to leave this behind. 

At this time it’s nice to “try” to find somebody who will carry out the torch, despite that our spark is slowly fading. Somebody may find it as an opportunity for them to “try” and through this move forward.

{{% ads-in-article %}}


---
## Installing Windows 11 in UTM on macOS and Apple Mac M1
- **URL:** https://dariusz.wieckiewicz.org/en/installing-windows-11-macos-apple-mac-m1-utm/
- **Date:** 2022-10-23
- **Tags:** UTM, Windows 11, Windows 11 ARM, Windows 11 ARM Retail, Windows 11 arm64, Apple Mac M1, macOS, UUP Dump, virtualization, SPICE Guest Tools, QEMU, Windows Update, Microsoft Store, Windows 11 22000, Windows 11 21H2, Windows 11 22621, Windows 11 22H2

### Content

In a searching for Windows 11 designated to arm64 based processors, (like Apple M1 and newer) I found, on **UUP Dump**, a version **Windows 11 arm64**, which was marked as designed for **Retail**. I decided to try to install it in UTM on macOS and my MacBook Air with M1.

<!--more-->

[![UUP Dump Windows 11 22621.674 Information](/images/2023/02/UUP_Dump_Windows_11_22621_674_Information.png)](/images/2023/02/UUP_Dump_Windows_11_22621_674_Information.png)

> Below post has been updated using Windows 11 version 22H2. If you previously installed version 22H1 saddly there is no easy method for pdate to 22H2 due to further restrictions put my Microsoft. You can try to follow Stephen Wagner post [How to force Windows 11 22H2 Feature Update](https://www.stephenwagner.com/2022/11/09/how-to-force-windows-11-22h2-feature-update/), and try method described there. This however didn't work for me and I finished in reinstalling fresh system with 22H2.

Retail channel (in theory) is classed as stable and designed for end-user. The surprise is that Microsoft is not officially advertising it and you cannot just [download the ISO file](https://www.microsoft.com/software-download/windows11) that will allow you to install it on a compatible device.

> This is an ARM64 build\
> This build is only compatible with:
> 
> Surface Pro X\
> Raspberry Pi\
> Apple Mac M1\
> other glorified mobile phones

Heading to [this page](https://uupdump.net/selectlang.php?id=e925283b-ad4e-4db1-8da1-e1fc160e5932) we may download a file that will allow us to generate an ISO file for Windows 11 22H2 which we will be able to use with UTM at a later stage.

---

Windows 11 22H2 generated from the UUP Dump website somehow is lacking Microsoft Store. The last know working version with it was [Windows 11 21H2](https://uupdump.net/selectlang.php?id=5e9df300-c445-4b61-83eb-a0ba7e84b167). You may consider sticking to this version if you want a full user experience with all apps like on a typical Windows computer.

---

> To generate a UUP Dump file for my purpose I selected **English (United Kingdom)** and in the **next** step, I leave all editions (Windows Home and Windows Pro).
> 
> As a download method I leave the default **Download and convert to ISO** and conversion option, also selected by default, **Include updates (Windows converter only)**.
>
> Finished by clicking **Create download package** and after unpacking it, followed steps from `readme.unix.md`.

Before we start, we need to have [Brew](https://brew.sh) installed in our system followed by additional packages as described later in generated UUP Dump package.

> Even if you have the below commands run in your system some time ago, worth to re-do this again, as brew will update them if there are any newest versions available.

```bash
brew tap sidneys/homebrew
brew install cabextract wimlib cdrtools sidneys/homebrew/chntpw
```

You may also need `aria2` package

```bash
brew install aria2
```

Once that is done, we can start building our ISO file by running the command:

```bash
sh uup_download_macos.sh
```

Depending on how fast your broadband is, it may take some time to complete. Let's wait patiently.

> On mine 200Mbps broadband and MacBook Air M1 download and conversion took just 5 minutes.

After a long while, if your transfer was not interrupted (which in my case was, and I need to re-run the above command) I ended up with my ISO file. Thanks to `aria2` package you can stop downloading at any time and continue when convenient.

> Before you start, you need to remember that you will find a couple of struggles during the installation process as I described in my post [Trying Parallels Desktop alternative - UTM](/en/parallels-desktop-alternative-utm/), and what you can read on [UTM Documentation](https://docs.getutm.app/guides/windows/). One of them was the lack of a Microsoft Store. This is why I tried the Insider Preview version to get this sorted. Let's see if the product marked for Retail is different.

In the below steps, I used [UTM in version 4.1.5](https://github.com/utmapp/UTM/releases).

[![UTM Version 4.1.5 (74)](/images/2023/02/UTM_Version_4_1_5_74.png)](/images/2023/02/UTM_Version_4_1_5_74.png)

## Installation

We will be following the steps as described in [instruction](https://docs.getutm.app/guides/windows/#instructions) with some input from myself.

[![UTM Fresh Window](/images/2023/03/UTM_Fresh_Window.png)](/images/2023/03/UTM_Fresh_Window.png)

From UTM main window click on the **+** icon.

[![UTM Start](/images/2022/10/UTM_Start.png)](/images/2022/10/UTM_Start.png)

Select **Virtualize**

[![UTM Operating System](/images/2022/10/UTM_Operating_System.png)](/images/2022/10/UTM_Operating_System.png)

Select **Windows**

[![UTM Windows](/images/2022/10/UTM_Windows.png)](/images/2022/10/UTM_Windows.png)

By default, it will be a ticked option to **Install Windows 10 or higher** and to **Instal drivers and SPICE tools**. What we need to do is to select our ISO file by clicking the **Browse...** button.

When we are ready, let's click **Continue**.

[![UTM Hardware](/images/2022/10/UTM_Hardware.png)](/images/2022/10/UTM_Hardware.png)

At the next screen, we can specify how much RAM we want to allocate and how many CPU cores. I would recommend leaving this as it is and clicking **Continue**.

[![UTM Storage](/images/2022/10/UTM_Storage.png)](/images/2022/10/UTM_Storage.png)

At the **Storage** step, we can specify the virtual hard drive size (recommend 128GB). This is the maximum hard drive size and this will be used depending on how many Windows will need. In the beginning, you will see that your Windows will use something like 15GB only.

[![UTM Shared Directory](/images/2022/10/UTM_Shared_Directory.png)](/images/2022/10/UTM_Shared_Directory.png)

At **Shared Directory** we can specify the local folder to be visible in a virtual machine. I would recommend setting the **Downloads** folder and then clicking **Continue**.

[![UTM Summary](/images/2022/10/UTM_Summary.png)](/images/2022/10/UTM_Summary.png)

In the summary, we can specify the name of our virtual machine and **Save** the settings.

Right now we just need to press the **play** button and follow the step-by-step installation instruction of the Windows Setup.

{{% gallery %}}
[![UTM Windows Setup](/images/2022/10/UTM_Windows_Setup.png)](/images/2022/10/UTM_Windows_Setup.png)
[![UTM Windows Setup Installing Windows](/images/2022/10/UTM_Windows_Setup_Installing_Windows.png)](/images/2022/10/UTM_Windows_Setup_Installing_Windows.png)
{{% /gallery %}}

After the installation restarts let's **Eject** the Windows ISO file by clicking the disc icon from the top-right corner. This will allow you to start booting your system instead trying to do this once again from the ISO file.

{{% gallery %}}
[![UTM Windows starting Getting ready](/images/2022/10/UTM_Windows_starting_Getting_ready.png)](/images/2022/10/UTM_Windows_starting_Getting_ready.png)
[![UTM Windows starting Just a moment](/images/2022/10/UTM_Windows_starting_Just_a_moment.png)](/images/2022/10/UTM_Windows_starting_Just_a_moment.png)
{{% /gallery %}}

[![UTM Windows starting Initial Setup](/images/2023/03/UTM_Windows_starting_Initial_Setup.png)](/images/2023/03/UTM_Windows_starting_Initial_Setup.png)

---

[![UTM Windows SPICE Guest Tools Installation](/images/2023/03/UTM_Windows_SPICE_Guest_Tools_Installation.png)](/images/2023/03/UTM_Windows_SPICE_Guest_Tools_Installation.png)

The first step after the initial setup was to install SPICE Guest Tools and wait until the system restarted.

> During installation the screen may become green, change its resolution and the system may restart.

[![UTM with Windows 11 ARM on MacBook Air M1](/images/2023/03/UTM_with_Windows_11_ARM_on_MacBook_Air_M1.png)](/images/2023/03/UTM_with_Windows_11_ARM_on_MacBook_Air_M1.png)

After restarting system was ready to use.

Because during installation my licence key didn't show the relevant version available, I need to install it without it and select Windows 11 Professional from the available two options (Core and Professional).

I head to **System** > **Activation** and select **Change product key** to activate followed by logging into my Microsoft Account.

Before I started messing with other things, I head to **Windows Updates** and install whatever was there available.

> Under **Advanced options** I turn on updates to other Microsoft products as well.

I noticed that the opposite to my first try with UTM and Windows 11 Insider, this time I have a Microsoft Store icon available but the app didn't want to start (the same with any other app from Microsoft Store).

Once again I install further updates that have been shown in Windows Update. I need to repeat that couple of times until no more updates were available, before proceeding further.

After that, a couple of restarts later Microsoft Store started working and I got the system ready.

{{% ads-in-article %}}

## Post Scriptum

Don't expect that Microsoft will play nice with people installing their system, on officially not approved by them, software (like UTM), even if you will pay full price for a licence. There is a big business behind it and the fully working software that use TPM and graphic acceleration on Apple computers is Parallels Desktop, which charges extra for this privilege. 

As mentioned in the beginning, especially with 22H2, you may experience an issue with the lack of a Microsoft Store. The last version where everything plays sort of nicely with UTM was [Windows 11 21H2](https://uupdump.net/selectlang.php?id=5e9df300-c445-4b61-83eb-a0ba7e84b167).

When I used the above method with Windows 11 21H2, I installed it without a key during setup and selected Windows Professional as the version. Later, I activated it with the Windows Education key and get Windows 11 Education version. On 22H2 this trick not worked and Microsoft servers returned information that this key cannot be used for activation of this version of Windows. The other option that was available during setup was Windows Core, which I followed.

[![Upgrade your edition of Windows - Windows 11 - UTM](/images/2023/03/Upgrade_your_edition_of_Windows.png)](/images/2023/03/Upgrade_your_edition_of_Windows.png)

During the activation of Windows Core with the Windows Education key I got an option to **Upgrade your edition of Windows** which allows me to land on the Windows 11 Education version.

## Microsoft Store on ARM64

A quick addition to missing Microsoft Store.

Open PowerShell or Terminal as an Administrator and type:

```powershell
iwr -useb https://raw.githubusercontent.com/DaBigBlob/ms-store-arm64/main/allowARMv2.ps1|iex

wsreset -i
```

> Read more: [Microsoft Store on ARM64 (for UTM)](https://dabigblob.github.io/ms-store-arm64/)

Patiently wait and the Store Experience Host installs in the background. You may have some notifications about that pop-up in the right bottom corner or some hanging-in notifications (when clicked on the clock in the right bottom corner).


---
## Where Helpful Content Update did not do as much, Core update did!
- **URL:** https://dariusz.wieckiewicz.org/en/where-hcu-did-not-do-as-much-core-update-did/
- **Date:** 2022-10-19
- **Tags:** Helpful Content, Helpful Content Update, Core Update, Spam Update, Google, SEO, Yummy Recipes, Yummy Recipes UK, Google Search, Google Discover, Google Search Console

### Content

When Google is releasing their search engine updates, there is always a lot of action and a lot of discussions around. Everybody is looking for the impact of the update on their website and position in search engines.

By the end of August 2022, Google comes with a Helpful Content Update (HCU). This highly appreciated (by content creators) update suppose to penalise low-content websites and those generated by AI. I have been happy about it and knew, that none of my websites will be affected, **and I was right!**

<!--more-->

> The Helpful Content Update was mostly oriented into sites written in English, but core updates are much more widespread.

Shortly after HCU finished rolling out we get another Core Update on the 12th of September 2022. Once none of the SEO experts could say much about HCU, due to a lack of documented information on how the algorithm is working, nobody could predict where this will go. In the end, everything aims for a better web experience for ordinary users, and I agree with that. On the internet, there are a lot of crappy websites stuffed with ads and text, that are nowhere relevant to the content. **Crazy!**

As a creator, I always write what I want and what I need to say about a subject. I do not work on the number of words. If my blog post or article will have 100 words or 1,000 words, that's what it will be. I am not trying to artificially fill them with text, to get a better position in search engines. This is the main goal of HCU, to put a stop to people, who create posts stuffed with nonsense, only to get better in position on Google.

After releasing of Core Update things starts to change even more. SEO experts start preaching that, if Helpful Content Update didn't do what was intended to, the Core update will fix that, **and I can see that now**.

Where none, apart from one of my websites, noticed a drop in visitors, I started investigating why. I didn't touch the content or the way how the website is constructed, I looked more at what resulted in the impact rather than what I (the content creator) did wrong. **And the conclusion was, it wasn't me, it was them!**

The website that sees the drop after the Core update, didn't experience this after the Helpful Content Update (in the opposite, we gain). The content created there, from the start has been aimed at better perceptions for visitors (**oriented for readers, not search engines**).

I am talking here about [YummyRecipes.uk](https://yummyrecipes.uk), where we tried to put the end to storytelling recipe websites, where recipes, that are important for readers, are just 10% of the rest of text stuffing content. **We tried something different and people appreciate that.**

Of course, we use other techniques to get our content available for a wider audience, like Recipe Schema (that helps to shine in Google Discover), but that's available for all. To my surprise, these content-stuffed recipe websites not using it, or if they do, they using it incorrectly. **Good for them.**

[![YummyRecipes.UK - Google Search Console - Page Experience Overview](/images/2022/10/yummyrecipes_page_experience_overview.png)](/images/2022/10/yummyrecipes_page_experience_overview.png)

After the Core update, we noticed a slowdown, and not because of our website directly, but because, these low-content websites over the Internet, linking to others or stealing content from others, after releasing the Core update, have finally been penalised.

I could see that through [ahrefs](https://ahrefs.com) analyse of lost traffic (where most of it was generated by spam websites), but with an increase of organic traffic instead.

The loss was quite significant, as we go back with traffic by months. Luckily, after 4-5 weeks, by keeping hard work on the content and not trying any shady SEO techniques, we start bouncing back to values seen just before 12th September.

Every Google update got its purpose and I fully agree with its merit. Sometimes, some decent websites are hit as well due to other players, who through their poor backlink empire suddenly lost their power in the search engine.

> We got considerable traffic originating from so-called "nitter" websites, that are serving stripped posts from social platforms. If one goes out of play, suddenly a website loses backlink power, but that doesn't mean that website on its own is less favourable to its readers.

Everybody would like to gain high-value traffic in the shortest period possible. **It's not always possible.**

Like all experts are saying, **concentrate on your content and find your niche**.

I am sick of tired of people on Twitter claiming that they are creating niche websites and with just 30-50 articles they got like 100k in traffic after just 3 months. **My question is how?**

I don't believe in such a miracle unless you created something revolutionary. In current society is not often without hard work, but when it happens is covered by the media and many people would hear about it.

I am a technical geek and follow plenty of websites for the latest news, but I don't see any widespread acknowledgement of these websites (or solutions on them), hence their claims are not worth a lot.

They tend to share stats but never a link to the relevant website. There is a simple answer to that. Their website is crap and what they doing is an attempt to gain recognition for work, that they shall not do in the first place. They trying to be a self-made influencers without properly backing up with relevant and valid data.

> It's like praising someone who becomes rich after just three months, only because they have been stealing others people's money.

If you, as a niche website creator, want a wide acknowledgement of your work, why are you not sharing it with a link to that, so everybody would assess your claims? **Too many of them are afraid because of their empty claims**.

In most cases, this will probably result in laughter and pointing out shady techniques used to get to the point when they claim themself as **"niche site builders"** which is **"gaining traffic"** quickly with **"a minimum work"** put into it. I don't believe in that, but looking at how quickly these people are gaining followers on social media, the majority are. **That's sad!**

In the last weeks, search results in Google start becoming more relevant concerning these written in English. Currently released [Spam Update](https://developers.google.com/search/updates/spam-updates) hopefully will help with that even further.

I would be very happy to see the impact on other languages, as seriously, there is a lot of crap promoted on the first pages of Google that something like Helpful Content Update (for other languages) shall simply eradicate.

{{% ads-in-article %}}

---

My advice for content creators is.

If you think that you have been affected by any Google algorithm update, before start blaming anybody, have a look at your content first. If your content is done in the way, that you, as a reader would like to read and appreciate the information they provided, then you don't need to worry too much. Sometimes most genuine and valuable websites are hit as well due to other players in the field. **Keeping up with good, hard work, will result, that things will turn back better.**

We all would like to be recognised and get millions of followers and an army of people who will re-share our work (our content). This all is based on our hard work. Don't expect that something happens with a minimum of your input. **Keep up the good work, create helpful content and integrate with your readers.**

Off-site marketing is also beneficial, like this:

![YummyRecipes.uk QR Code](/images/2022/10/yummyrecipes-qr-code.png)


---
## AirDrop - don't be open like a book
- **URL:** https://dariusz.wieckiewicz.org/en/airdrop-dont-be-open-like-a-book/
- **Date:** 2022-10-16
- **Tags:** Apple, AirDrop, AirDrop Privacy, AirDrop Contacts Only, iOS, iPhone, Privacy

### Content

Privacy in recent years is something that everybody is talking about. Some companies undersell their own devices just to gain the information that they will harvest. The others say it aloud that they put privacy on the pedestal, and that includes their devices. This is Apple.

Even if you decided to move away from devices and companies that violate your rights and decided to buy an iPhone, remember, that in the whole of this the weakest link, the hole in a privacy matter is you!

<!--more-->

The iPhone got plenty of privacy-oriented features, but others give it unique usability. This is AirDrop.

One of the features of AirDrop is to allow, in a simplified way, to exchange information between Apple devices and people that are nearby.

The problem is, as seen on [various youtube videos](https://www.youtube.com/results?search_query=airdrop+prank), people are leaving AirDrop open for everybody to communicate and that's not a good thing. You are highly oriented on privacy, yet you allow a stranger to send you unintended files and images, or even stream music from their device to yours!

The problem is bigger than you think. Try to AirDrop file on a plane, train station or in the supermarket and you will quickly see people available that, firstly you don't know, and secondly they are not in your contacts.

Imagine the consequences when somebody decides to send an offensive image to your child's tablet and they accept.

When we are busy, we tend to click accept if something pop-up in the middle of what we are currently doing, that's our nature. Rarely do we make other decisions, or shortly after, we start thinking, what was that?

You may invest in the most advanced door lock, but if you forget to close it, you know what you are risking.

Close your AirDrop, or at least restrict it to the people that you know and "trust". 

Here is how in a couple of easy steps.

Go to **Settings** and **General**.

Find a section called **AirDrop** and make sure you got this set to **Contacts Only** and not everyone.

{{% gallery %}}
[![iPhone - iOS - Settings](/images/2022/10/iPhone_Settings.png)](/images/2022/10/iPhone_Settings.png)
[![iPhone - iOS - Settings - General](/images/2022/10/iPhone_Settings_General.png)](/images/2022/10/iPhone_Settings_General.png)
[![iPhone - iOS - Settings - General - AirDrop](/images/2022/10/iPhone_Settings_General_AirDrop.png)](/images/2022/10/iPhone_Settings_General_AirDrop.png)
{{% /gallery %}}

This setting doesn't change your ability to send things to everybody who they got set **everyone** in their settings, or if they got yourself in their contacts. 

On the other way, you may find it difficult to share a thing with a stranger, but it's not as bad as you think.

If you find out that you are not visible to your friend, when he tries to share something with you, make sure you got them added to your contact in your phone.

Sometimes, depends how they set up their iCloud account, the phone number may not be enough, and you may need to update your contact with their email address (associated with their iCloud).

I never found the need to change AirDrop settings for everyone, and when I need it, it always was, when I want to share or received something intentionally from the person that I know.

Don't be like these people on YouTube, change your AirDrop settings now.

> Good news on that is, that by default AirDrop is set to Contacts Only, however sometimes we may change it, even unintentionally, or somebody will do this, hence always worth checking that.

{{% ads-in-article %}}


---
## How to disable read receipt requests widely for senders from outside organizations in Microsoft 365
- **URL:** https://dariusz.wieckiewicz.org/en/disable-read-receipt-microsoft-365/
- **Date:** 2022-10-08
- **Tags:** Microsoft 365, Microsoft 365 Business, Exchange, Exchange admin centre, Read Receipt, Disable Read Receipt, Mail Flow, Mail Flow rules, New transport rule, Outside the organization, message header

### Content

Privacy is the key and it's not only in our private life but also in business. If you using Gmail (Google Workplace) for your business, something called read receipt is an odd thing.

Many businesses however are using solutions from Microsoft called Microsoft 365 Business (in various plans).

Microsoft, in their subscription service, provides a lot of useful functionalities, but there are some functions, that are heading back to times when Microsoft Outlook started gaining popularity (Microsoft Office 97).

Through these functionalities there was one, requesting a receipt sent back to the sender when the recipient read an email.

<!--more-->

As good as it sounds, this simple functionality comes with a headache when we don't want to let others that we read their email and simply ignored it until the point when we want to deal with it.

When Outlook mostly asks you if you want to get this feature enabled or not, sometimes you may forget that it's there and this will put you in trouble. For business, this may set you as an unreliable person if not even worse if we decide to play the card that: "I haven't read your email yet" or "I haven't received it".

The best solution is to have this option turned off, but in the organisation, you cannot control all user settings.

If you got Microsoft 365 subscription and got administrator rights, you can put a simple rule to block in Exchange (a part responsible for managing emails) any requests for reading receipts and here is how.

> I will be looking into blocking it only for people from an outside organisation, as inside this may be a sort of useful feature.

Firstly, we need to head to [**Exchange admin centre**](https://admin.exchange.microsoft.com).

[![Exchange admin centre](/images/2022/10/disable_read_receipt__exchange_admin_centre.png)](/images/2022/10/disable_read_receipt__exchange_admin_centre.png)

From there we need to head to the section called **Mail flow** > **Rules**.

[![Mail Flow > Rules](/images/2022/10/disable_read_receipt__mail_flow_rules.png)](/images/2022/10/disable_read_receipt__mail_flow_rules.png)

From the screenshot above you already see that I got a set rule called **Disable Read Receipt** which is set with the highest priority (0) and it looks as below.

[![Disable Read Receipt - Preview of a rule](/images/2022/10/disable_read_receipt__preview_of_a_rule.png)](/images/2022/10/disable_read_receipt__preview_of_a_rule.png)

To add this on our end, we need to click **+ Add a rule** button on the top and from **New transport rule** head through the configuration as follows.

[![New Transport Rule](/images/2022/10/disable_read_receipt__new_transport_rule.png)](/images/2022/10/disable_read_receipt__new_transport_rule.png)

We are setting the name of the rule (like **Disable Read Receipt**) and selecting to who this rule will apply. In section **Apply this rule if** we select from dropdown box **The sender**.

[![Set Rule Conditions](/images/2022/10/disable_read_receipt__set_rule_conditions.png)](/images/2022/10/disable_read_receipt__set_rule_conditions.png)

From the dropdown on the right, we need to decide, if this applies to people from an outside organisation (external) and/or inside (internal).

[![Set sender location](/images/2022/10/disable_read_receipt__set_sender_location.png)](/images/2022/10/disable_read_receipt__set_sender_location.png)

In an additional part of the setup, we select our preference. In that case in **select sender location**, from the dropdown box, I selected **Outside the organization** and saved that using the blue button on the bottom.

[![Do the following](/images/2022/10/disable_read_receipt__do_the_following.png)](/images/2022/10/disable_read_receipt__do_the_following.png)

Once we got this done we head to section **Do the following** from which, from the first dropdown box we select **Modify the message properties**.

[![Message Header](/images/2022/10/disable_read_receipt__message_header.png)](/images/2022/10/disable_read_receipt__message_header.png)

From other dropdown boxes, we select to **remove a message header** and from the additional part of the setup, in the **message header** part type as follows:

```
Disposition-Notification-To
```

{{% ads-in-article %}}

We save this part by clicking the save button at the bottom.

[![Set rule conditions - Next Step](/images/2022/10/disable_read_receipt__set_rule_conditions_next_step.png)](/images/2022/10/disable_read_receipt__set_rule_conditions_next_step.png)

Most of the rule is set and looks as on the above.

We can add here some exclusions if needed, but if not, we click **Next** to go to the next step.

[![Set rule settings > Enforce](/images/2022/10/disable_read_receipt__set_rule_settings_enforce.png)](/images/2022/10/disable_read_receipt__set_rule_settings_enforce.png)

In next step, **set rule settings**, we already got set **Rule mode** to **Enforce**. Unless we want to test it first, we click on the next button located at the bottom.

[![Rule > Review and Finish](/images/2022/10/disable_read_receipt__rule_review_and_finish.png)](/images/2022/10/disable_read_receipt__rule_review_and_finish.png)

The last step is just for a **review** before we click **Finish**.

As you will notice, every new rule set receives the next available priority number. This type of rule we would like to have this on the top of our rule list. 

[![Rule priority](/images/2022/10/disable_read_receipt__rule_priority.png)](/images/2022/10/disable_read_receipt__rule_priority.png)

By selecting our rule and using the **^ Move up** button we push it to be number one (Priority 0).

In such a way, all is set.

If somebody will send us, from an outside organisation, a message that requires a read receipt, before it's delivered to our mailbox, this requirement is removed.

It's a small, but very useful rule worth having.

Useful? Let me know.


---
## How's Brexit going lads?
- **URL:** https://dariusz.wieckiewicz.org/en/hows-brexit-going-lads/
- **Date:** 2022-09-03
- **Tags:** Brexit is not working, bollocks to the government, clown as PM, national debt, minimal wage, cost of living, cost of living crisis, minimum living wage in UK, Tory party, benefit system in UK, visa system in UK, united kingdom after brexit

### Content

It was all about immigration.
It was all about controlling our borders.

bollocks, bollocks, bollocks...

How is it going brexiteers when you need cheap labour for simple jobs and you will not get away with a £10 per hour rate?

<!--more-->

I remember my first payslip when I came to the United Kingdom in late 2010. The minimum wage was £5.80, and, despite that this was just enough, people somehow live and cooperate.

The country had already begun its destruction path under the Tory government. The minimum wage was heading towards the limits of affordability value for British businesses. The businesses, who cannot afford that, especially now, before winter and in time of energy crisis. 

Rising wages it's not a solution when other things raise at a faster pace. We are getting poorer from day to day and it will not look better under another rubbish PM that this country will face under the Tory charge.

A lot of British people were annoyed when borders were fully opened for people from countries like Poland (and Romania etc.). When the requirement of the Work Registration Scheme was scrapped for them, they all blamed them for the difficulties that British-born facing in the job market.

It's a different story now when we would like to have this cheap labour to help and ease inflation.

Don't listen to stories saying that immigrants come to this country to claim benefits. Benefits were the last thing that they had been thinking about. The first was to get a safe place to settle, find a job and start building up and living in the United Kingdom.

If on that road we become entitled to benefits, in the same way as British people, then that's not a fault of us, individuals, but the generosity of the system. Remember, we want to be equal. Equal treatment of British people and foreigners working here and paying taxes means that this equality was in everything, including the benefits system.

We have never been treated the same. There were always hurdles like fluidity in speaking in other languages and biased thinking about a person based on his/her nationality.

Before any actions, the new generations of people shall be properly educated about the past.

Nobody from the current middle-aged generation remembers why the European Union was created and what was the reason behind joining the block by the United Kingdom in 1973. I even haven't been born at that time, hence I doubt that anybody at the productive age knew what was all about.

The same people who don't know the history just need a bunch of clowns, from which one becomes the PM, to encourage people with their biased reasons to put shit into their afternoon tea.

If they just could tell the people, that when you stir it, the smell may go away, but the shit taste remains.

To remove this, let's get some Europeans to help Britain in need. Like encouraging them to come to Britain for three months, the months when all would like to spend with their families, to clean the shit for us. That was the case before last Christmas and all mighty clowns were surprised why they didn't come.

Right now for a Polish person to come, settle, live and work in peace here in the UK, one needs to apply for a Visa. The visa is just another hurdle put forward and the laughing requirement of a minimum annual wage set at £25,600 is like laughing even further.

I am a skilled worker and when I come here I didn't bother to get any job to make sure I can be independent and leave without worrying about the money for everyday expenses. 

At the time I haven't even dreamed about such high earnings. I earn maybe 10-20% more than minimum wage at the time, exactly like many other British-born people and I do my job at the top level, if not better!

Times fly and through my personal development and work experience, supported by my love on my side, I managed to get to a better level than when I come here to live.

I come to Britain to live, settle, have a family and eventually become a British citizen. I accomplished all this in a matter of 12 years. If today I would like to apply for a work visa in the United Kingdom, even with my experience, skills and all that I can offer, I doubt that any UK-based employee would offer a Polish guy (in Poland) the wage, that they cannot offer to people living here. 

At the time when the border was open, employees have been worried a bit when hiring foreigners in a higher position in the company as they knew, that they may at some point decide to go back to their country. This wasn't the idea for me, as I chose the United Kingdom as a place to live and stay. If not for this, there are other countries in the world to choose from, but I never thought to go back.

With visa hurdles, it's even worse. Which UK employer will risk so much and don't be sure if that person will stay? Their visa may be revoked and what then? All the training and investments into this employee will go for nothing. If I would like to hire somebody for the long term I would never risk it to hire a foreigner in the first place.

I always thought that the minimum wage was rising at a pace way higher than businesses can handle. We are currently at £9.50 (+63% from 2010, far exceeding summarised inflation over that period) with a proposition to £10.01 from next year.

With the current cost of living crisis, I may understand that, however, that's not the way to stop the crisis that we are currently in.

I appreciate the introduction of a living wage, the real equivalent of earning to the cost of living. Transparency between big companies and disparity in the minimum wage to living wage between employees will say a lot about them.

What we all forget, these people, who are not on minimum wage will rarely see an increase in wage in the range of 6.6% like this change that has been made between 2021 and 2022 for those on a low income.

If the Brexit would work (it wasn't ever designed to work in the first place!) we should be a Cayman Islands right now. With the current cost of living and raising wages, we are going into a dangerous path when all will crash at once. With Tory in power till at least January 2025, we will be given a golden goose to blind our eyesight to what's coming.

Whoever will come to power, after Tory, will be the worst party for people ever. 

United Kingdom's national debt is £2,382.8 billion compared to £294.27 billion of Polish debt. 

Poland is currently governed by sociopaths and racists where rich people get richer and poorer poorest, but still there (without) law and (without) order party got plenty of billions of pounds to steal before anybody will raise a concern.

People forget that this debt is our debt. Sooner or later this need to be repaid. To get this done there needs to be cuts introduced in every aspect of our life. This is why, whoever will come into power in 2025, it's already doomed by society.

There are over 66.84 million people in the UK (as of 2019) which means each of us owns the country £35,649 at the start of our life. Can you imagine that?

Taking this into consideration, right now look at the 20% tax that is taken from our wages each month and companies like Amazon UK with a profit range of £204 million receiving another £1 million of UK tax credit adding to the already awarded £850 million!

Rich people will still get richer and poor people will need to work and give away their money to pay for their private parties once they laugh behind our backs.

Like this clown advising us to invest in the new kettle to reduce our electricity bill by £10 a year. Energy efficient kettle costs on average £35 and its life span doesn't exceed 4-5 years (of the good one), so don't be fooled by the savings.

It would be better if he would just shut up or rather say ["Some of you may die, but it's a sacrifice I am Willing to Make"](https://www.youtube.com/watch?v=hiKuxfcSrEU) when families will face bills this winter that they cannot afford to pay.

That's the difference between the people who are disconnected from the reality of the ordinary people but who (pretend to) “know” what low-income families are facing. They will carry out their strategy of offering benefits and at the same time blindfolding society when other costs will increase.

Do you remember getting £150 off your council tax rebate from which you will not see a penny, as this was already taken by the council and other tax increases?

We need a change, but I think we, the people are too afraid of doing this.

{{% ads-in-article %}}


---
## Polish style Croissants (Rogaliki) with Black Cherry Conserve
- **URL:** https://dariusz.wieckiewicz.org/en/polish-style-croissants-rogaliki/
- **Date:** 2022-08-22
- **Tags:** Rogaliki, Crossants, Rogaliki drożdżowe, Yeast Croissants, Polish, Polish style, Polish Crossants, Polish Rogaliki, Dessert, Polish Dessert

### Content

> Difficulty: **Low**\
> Preparation Time: **30 minutes** + 45 minutes for dough rising\
> Baking time: **15 minutes, 180C with fan** per insert

<!--more-->

## Ingredients

- 675g of plain flour
- 30g of fast-action dried yeast (2 sachets, 15g each)
- 250ml of milk
- 125g of unsalted butter
- 5 tbsp and 1 tsp of sugar
- pinch of salt
- 2 eggs

### Filling
- 225g of Black Cherry Conserve

> You can use any type of Jam, Conserve, in any flavour as long it's nice and thick. You can use poppy seed mix in a tin or experiment with your filling. Make sure the filling is thick-solid, so you can easily roll the croissant.

### For icing
- 250g of icing sugar
- 1 lemon
- 1 tsp of tap water

{{% ads-in-article %}}

## Method

Pour milk into a saucepan and heat slightly (touch warm). 

Fill half of a mug with warm milk, add yeast, 1 tsp of sugar and 3 tbsp (heaped) of flour (approx. 75g) and stir thoroughly. Keep stirring energetically until all ingredients combine. Leave on a side for 5 minutes. You will see how the yeast mixture starts growing inside.

To the rest of the warm milk add butter and stir to make sure it will melt. Add heat if needed but do not overheat the mixture above touch warm feeling.

Pour flour, salt and 5 tbsp of sugar into a bowl and mix. Add yeast mixture, eggs and warm milk-butter mix.

Mix using a spoon initially than using your hand keep kneading the dough for 5 minutes.

Leave the dough in a bowl, cover with a cloth and leave in a warm dry place for 45 minutes. The dough will double in size.

Preheat the oven to 180C with a fan.

Once dought doubled, kneading once for the last time and form the ball. 

Dust the ball with flour and divide it into 3 equal pieces.

Dust the table top surface and roll one piece of the dough very thin (approx. 3-5mm thin).

Cut rolled dough horizontally so you will have long dough strips.

From each strip cut long, but thin triangles (approx. 12-15 cm long and 5-7 cm wide on one end).

Put half of the teaspoon of conserve on the end of each triangle and start rolling from the wider to thinner end.

Once you got your dough rolled twist around your fingers from both ends and form a wide letter U.

> When rolling the triangle, try to stretch both ends once you roll to form a nice long rolled tube.

Transfer your croissant to a baking tray lined with greaseproof paper. Make sure to leave plenty of space in between as they will double in size during baking.

> You will fill roughly 12 (3x4) on a tray of 30x38cm. 

Bake for 15 minutes until nice and golden.

> During baking, the jam (conserve) may come out on the sides. Make sure to do not touch it once hot to avoid burn.

Leave the croissants on the tray for 5 minutes to cool down then transfer them to a plate.

> Do not leave them on the tray for too long, especially when a jam comes out on the sides, as you will have a problem removing them once they will cool down and stick to it.

Leave croissants to cool down fully (approx. 30 minutes).

Put the icing sugar into a bowl.

Squeeze the lemon juice and add, together with water, into icing sugar. 

Mix thoroughly with a spoon and keep mixing until you will get a thick sugar paste.

> If after 2 minutes the icing is too thick, add a teaspoon of water. If icing is too liquid, add more icing sugar and mix through.

Brush each croissant on the top and leave them to try.

You accomplished your recipe for polish style croissant.

Cheers!


---
## Implementing Structured Data (Schema) Carousel for Category pages in Hugo
- **URL:** https://dariusz.wieckiewicz.org/en/implementing-schema-carousel-category-page-hugo/
- **Date:** 2022-08-17
- **Tags:** Hugo, Schema, Carousel, Summary page, Structured Data, ItemList, ListItem, Recipe Structured Data, Recipe host carousel, Rich Results, Rich Results Test

### Content

On websites that I tend to create, I always try to utilise Structured Data (Schema) as much as possible. This invisible for ordinary visitor data is served in the background and is used by search engines and other websites for better positioning of your content.

On [YummyRecipes.uk](https://yummyrecipes.uk) I have already widely implemented Schema for Recipes but would like to do some more.

<!--more-->

Our categories pages (despite, on purpose, not having `/category/` in its URL) present various recipes grouped adequately. As `categories`, like `/tag/` pages, they suffer from exclusion from search engines. Fully understand that as, for example, one recipe can generate 10 or more tag pages, however, category pages are a slightly different part of the story.

I have been looking into [Google Search Central documentation](https://developers.google.com/search/docs) and found something called [Carousel](https://developers.google.com/search/docs/advanced/structured-data/carousel). Despite that, I already saw this before, but never really go into depth with that.

Reading how to [add structured data](https://developers.google.com/search/docs/advanced/structured-data/carousel#add-structured-data) I read through two examples of use cases – **Summary page** and **A single page**.

> The **summary page** has a short description of each item in the list. Each description points to a separate details page that is focused entirely on one item.

> **A single**, the all-in-one-page list contains all carousel information, including the full text of each item. For example, a list of the top movies in 2020, all contained on one page. This page doesn't link out to other detail pages.

The summary page best matches with **category** pages used on Yummy Recipes, for example, category [/dessert/](https://yummyrecipes.uk/dessert/).

The carousel for the summary page requires, that each **details page** (which is just a full recipe page) will have required [structured data for Recipes](https://developers.google.com/search/docs/advanced/structured-data/recipe). I got this already implemented.

In that case, each category page will only require a simplified carousel schema for summary and the magic will happen.

When you read for the first time about Carousel you may be a little overwhelmed when you will go into [**details page**](https://developers.google.com/search/docs/advanced/structured-data/carousel#details-page). It's not. After you sorted out the Schema for Recipes the hard part is done. The Carousel is a **simple** addition!

The carousel only contains two dynamic parts. A `position` is a simple counter (1, 2, 3...) that matches the order of your list on a category page. The `URL` is a link to a details page, which is a link to a full recipe with implemented recipe schema.

I surprised myself with how crazy easy it is, so let's use it.

First, we need to borrow a `range` that is used to display the content of the category page.

To customise how the category list will look like I created `layout/category/category.html` file.

Will not bring the whole file here, just the important bit.

```html
{{ range where .Paginator.Pages "Params.hidden" "ne" true }}
<div class="title">
  <a class="recipe-title" href="{{ .RelPermalink }}">{{ .Title }}</a>
</div>

<!-- some other parts -->

{{ end }}

{{ partial "pagination.html" . }}  
```

As you see, we got already, inside the range link to our recipe which will be used in our `URL` part of the schema.

We just need to sort out `position` element.

Paginator used will make sure that it will display the only number of posts (recipes) as specified in `config.toml` in `pagerSize = 16` part[^1].

[^1]: See more [Pagination — Configuration](https://gohugo.io/templates/pagination/#configuration)

In that case, on other pages (`/page/2/`) the `position` need to reset itself and start counting once again from 1 (up to 16).

Hugo community on Discourse already provided a solution for me in [Adding a counter to Range](https://discourse.gohugo.io/t/adding-a-counter-to-range/16574) post, which I would like to reuse.

```html
<!-- outside the range -->
{{ $counter := 0 }}
<!-- inside the range -->
{{ $counter = add $counter 1 }}
{{ $counter }}
```

{{% ads-in-article %}}

I took the initial example from Google and worked to adopt it.

```html
<script type="application/ld+json">
    {
      "@context":"https://schema.org",
      "@type":"ItemList",
      "itemListElement":[
        {
          "@type":"ListItem",
          "position":1,
          "url":"http://example.com/peanut-butter-cookies.html"
        },
        {
          "@type":"ListItem",
          "position":2,
          "url":"http://example.com/triple-chocolate-chunk.html"
        },
        {
          "@type":"ListItem",
          "position":3,
          "url":"http://example.com/snickerdoodles.html"
        }
      ]
    }
</script>
```

So it will (with help[^1]) looks as follow:

```html
<script type="application/ld+json">
    {
      "@context":"https://schema.org",
      "@type":"ItemList",
      "itemListElement":[
      {{ range $counter, $_ := where .Paginator.Pages "Params.hidden" "ne" true }}{{ if $counter }},{{ end }}
        {
          "@type":"ListItem",
          "position": {{ add $counter 1 }},
          "url": {{ .Permalink | jsonify | safeJS }}
        }
	    {{ end }}
      ]
    }
</script>
```

[^1]: Thank for [Joe Mooring](https://discourse.gohugo.io/u/jmooring/) from Hugo community [for pointing into right direction](https://discourse.gohugo.io/t/a-bit-of-help-with-if-element-is-single-then-last-then-else-that/40052/8).

Having implemented Carousel Schema and (previously) Recipe Schema on linked pages, the output shall look like one from examples on [Carousel Search Results documentation page](https://developers.google.com/search/docs/advanced/structured-data/carousel).

![Example of Recipe host carousel in Google Search Results](/images/2022/08/carousel-example-recipe.jpg)

To check, if our schema in the category page is displayed correctly, just need to put our URL through [Rich Results Test](https://search.google.com/test/rich-results).


---
## Simple implementation of PWA on a website with a Mobile First Design approach
- **URL:** https://dariusz.wieckiewicz.org/en/simple-implementation-pwa-webdev-mobile-first-design/
- **Date:** 2022-08-11
- **Tags:** PWA, WebDev, Mobile First Design, Hugo, Static Website, manifest.webmanifest, Service Workers, Favicon, Favicons, Web App

### Content

If you read my other post, you will find out that I recently [rediscovered Progressive Web Apps (PWA)](/en/rediscovering-progressive-web-apps-pwa/).

Following this lead, I decided to implement it on the websites, where our main audience browses it from mobile phones. Later I decided to implement it gradually on all of my websites, independently of whether the main audience is on mobile or desktop. As you will see, PWA is quite useful for desktop users as well.

<!--more-->

For all of the websites that I design, I am doing it with a mobile-first design approach in mind. Independently of how visitors are approaching it, it needs to look and work well in both environments (desktop, mobile and something in between).

But, Progressive Web Apps are not only about mobile-first. This implementation is adding nice functionality for desktop browsers, mostly Chromium-based like Microsoft Edge. This is why there is a word “apps” there and not just “progressive web”.

But first, let’s see how you can implement it on your website.

Believe me, it doesn’t require you "don’t know how" extensive WebDev knowledge. Everybody can do this. I did this on my static sites that are generating using [Hugo](https://gohugo.io) but the approach is universal for everybody.

Implementation is divided in 4 sections covering **graphics files** needed, **code** that is pasted in `<head>`, **service worker** file and the JSON **manifest**. 

Don't worry if you don't have experience with service workers for PWA (`sw.js`), **it doesn't matter**. Same with JSON manifest. All are presented as simple as possible.

**Further,** depending on your needs, you can extend the functionality into real PWA scope, but not necessarily you need to!

---

## Before you start

Along with adding PWA, you may want to ￼read the first post about [Simplified way of adding a favicon to the website](/en/simplified-way-of-adding-favicon-to-website/) as some elements, starting from basic graphic files and manifest, are described there and reused in PWA approach.

## Graphic files

Firstly, you will need to have your logo fitted into a square. One file 192x192 and the other 512x512, and saved in the `.png` file.

> If you prepared these files already based on adding them at the favicon implementation, you know that layer is as per dimensions specified above, but the image is smaller, roughly 88% and centred. All of them have a solid background, without any transparency, because transparent elements will be filled with black colour by default and all can look poor.

Some operating systems are using rounded icons. You will find that your logo in rounded format, even that is shrunk initially to 88% will still doesn't look nice there.

**You will need a so-called "maskable" icon.**

For this purpose, head to [Maskable Web App](https://maskable.app/editor) and load your icon (or logo) there. Specify colour for your background and use padding slider shrink in such a way, that will look nice inside the circle.

Rename them accordingly. In my instance, I will have `favicon-192.png`, `maskable_favicon-192.png`, `favicon-512.png` and `maskable_favicon-512.png`.

## The manifest

In the manifest file (`manifest.webmanifest`) we will use our graphic files from the previous step and then fill some text in.

```json
{
  "lang": "en",
  "short_name": "My PWA",
  "name": "My Super Duper Fancy PWA",
  "description": "The description of My My Super Duper Fancy PWA",
  "icons": [
    {
      "src": "/favicon-192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "/maskable_favicon-192.png",
      "type": "image/png",
      "sizes": "192x192",
      "purpose": "maskable"
    },
    {
      "src": "/favicon-512.png",
      "type": "image/png",
      "sizes": "512x512"
    },
    {
      "src": "/maskable_favicon-512.png",
      "type": "image/png",
      "sizes": "512x512",
      "purpose": "maskable"
    }
  ],
  "start_url": "/?utm_source=pwa",
  "scope": "/",
  "background_color": "#ffffff",
  "theme_color": "#ffffff",
  "display": "standalone",
  "shortcuts": [
    {
       "name": "Shortcut 1",
       "description": "Shortcut to important page in my PWA",
       "url": "/shortcut1/?utm_source=pwa",
       "icons": [
        {
          "src": "/favicon-192.png",
          "type": "image/png",
          "sizes": "192x192"
        },
        {
          "src": "/maskable_favicon-192.png",
          "type": "image/png",
          "sizes": "192x192",
          "purpose": "maskable"
        }
       ]
    },
    {
      "name": "Shortcut 2",
      "description": "Shortcut to another important page in my PWA",
      "url": "/shortcut2/?utm_source=pwa",
      "icons": [
       {
         "src": "/favicon-192.png",
         "type": "image/png",
         "sizes": "192x192"
       },
       {
         "src": "/maskable_favicon-192.png",
         "type": "image/png",
         "sizes": "192x192",
         "purpose": "maskable"
       }
      ]
    }
 ]
}
```

Let's go through the file now.

- **lang** - you specify the main language of your manifest file
- **short_name** - the name that will be displayed under the icon of your PWA when added to the Home Screen on a mobile device or when installed on a desktop.
- **name** - here you describe a longer, more descriptive name. If your name is short enough, you can omit the `short_name` parameter.
- **description** - a description of your app or website. Typically followed what's described in `<meta name="description" content="`.
- **icons** - here we specify our icons. Have a look at that maskable icon that got the additional parameter `"purpose": "maskable"`.
- **start_url** - this is the URL that is used when we start our PWA from a shortcut. The `/` mean that it's showing the homepage and `?utm_source=pwa` [^1] is added to report back to analytics, how the website was accessed.
- **scope** - Scope is a part of the address that the PWA is limited to. If for example, you will specify that starting the app is subfolder `/app/` then the PWA will not be able to go outside that and show you what's in the root folder `/`.
- **background_color** and **theme_color** are a bit of customisation to match you website. The background refers to the general colour of your website background, typically specified in CSS for the `<body>` element, where `theme_color` refers mostly to the colour of the browser navigation bar etc.

[^1]: In my initial post and screenshots I referred to `?source=pwa` which I later changed to `?utm_source=pwa` to work better with [Google Analytics in my minimal approach](/en/minimal-google-analytics-4-snippet/).

You may have this already specified in your head during web development like:

```html
<meta name="theme-color" content="#ffffff">
```

If you using the Light and Dark mode of your website, it may be like that:

```html
<meta name="theme-color" content="#FEFAF8" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#010507" media="(prefers-color-scheme: dark)">
```

Sadly, on manifest we cannot specify different colours for light and dark mode but don't worry, we will overwrite this, as we will serve our website in full-screen experience later.

- **display** - this potion is responsible for displaying the app in different modes. By default, it will display like a website open in the browser with all browser controls and address bar. We would like it in full screen, so we will specify the **standalone** option. This will bring the website full screen but preserve the top bar of the window, on desktop, or time, battery and wifi icons, on mobile.

There is also an option called **fullscreen** but is mostly reserver for use with real apps that go full screen. This is not working on all systems and is limited to the maximum value (fallback) of **standalone**.

Also, as you will notice, in Safari on iOS this option will not bring your PWA full screen, as Apple is using the value in `<head>` for this purpose which will be covered further.

- **shortcuts** - is an optional element to add handy shortcuts to some important part of your website, for example, for `/contact/` for or `/shop/`. They only appear when the app is installed (on desktop) or added to Home Screen (mobile, Android mostly).

Remember, that for links, they need to be in the `scope` specified. For tracking use purpose, add to them `?utm_source=pwa`, so you will know from what source the user visit that part of your website.

We saving our manifest in a root directory of our website along with graphic files.

## The code in the head

In the `<head>` of our website we need to load the manifest that we created.

```html
<link rel="manifest" href="/manifest.webmanifest">
```

As mentioned at the manifest stage, for Apple devices, the display parameter is not always respected so we need to add the following:

```html
<meta name="mobile-web-app-capable" content="yes">
```

This will force us to put our PWA, when launched from the icon, into a full-screen experience.

> Other web browsers, like Firefox, may need that as well.

Another option is specific for Apple devices that add Launch Icon Title (if not respected through manifest), similar to short_name`.

```html
<meta name="apple-mobile-web-app-title" content="My PWA">
```

Than:

```html
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
```

This will direct the appearance of the Status Bar. Its very similar to `theme_colur` but more for iOS/iPadOS.

Available options are:
- **default** - which is white background with black text (and symbols)
- **black** - black background with white text (and symbols)
- **black-translucent** - transparent background with white text and symbols.

There is no real option (for now) to set a specific value for light and dark mode, hence **black-translucent** is something that you may look at if you got implemented `prefers-color-scheme` on your website.

---

The last thing to add to your `<head>` is a call for Service Worker. This is an essential part of every PWA, but don't worry, we will not use it. Even that, we still need it, hence add the below as well:

```html
<script>
    if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('/sw.js');
    };
</script>
```

{{% ads-in-article %}}

### The code in the head - Summary

Our entry in `<head>` will look as follow:

```html
<link rel="manifest" href="/manifest.webmanifest">

<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="My PWA">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script>
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js');
};
</script>
```

## The Service Worker

> "Service workers are a fundamental part of a PWA. They enable fast loading (regardless of the network), offline access, push notifications, and other capabilities."
> 
> [web.dev > Learn > Learn PWA!](https://web.dev/learn/pwa/service-workers/)

The service workers in PWA have a wide range of use. It can add the ability for you to make your PWA work (by serving static content from memory - cache) even if you are offline.

Because I will not go into the depth of SW here, as this can be a new (and long) post, let's just add a dummy one that will be a base for further development if needed.

```js
self.addEventListener("fetch", event => {

});
```

This file (`sw.js`) needs to be saved in the root directory along with others.

> The service worker file, even if that is empty, still will serve its purpose by prompting for App installation in Chromium-based browser and on Android.

---

**We did the hard bit, so let's see how this is working.**

Here is an example based on implementation on [Yummy Recipes UK](https://yummyrecipes.uk) website.

## Verification and The Result

By loading our website in a Chromium-based browser and opening DevTools (right-click on the background of the loaded website and click Inspect) we can see in the **Application** tab how the manifest is declared and icons used.

[![PWA of Yummy Recipes UK - DevTools - Manifest](/images/2022/08/pwa_yummy_recipes_devtools_manifest.jpg)](/images/2022/08/pwa_yummy_recipes_devtools_manifest.jpg)

You can also verify how maskable icons will look by ticking **Show only the minimum safe area for maskable icons**. In our example, these will be the ones on the right side, and you will see, how poorly they would look if we will not specify separate files (on the left).

[![PWA of Yummy Recipes UK - DevTools - Manifest - Icons section with ticked maskable option](/images/2022/08/pwa_yummy_recipes_devtools_manifest_icons_maskable.jpg)](/images/2022/08/pwa_yummy_recipes_devtools_manifest_icons_maskable.jpg)

By selecting **Service Workers** from the left side of the menu you can see that our simple `sw.js` file is loaded and working as expected.

[![PWA of Yummy Recipes UK - DevTools - Service Workers](/images/2022/08/pwa_yummy_recipes_devtools_service_workers.jpg)](/images/2022/08/pwa_yummy_recipes_devtools_service_workers.jpg)

Despite the that this solution is very simple and a service worker is a simply dummy file, a Chromium-based browser will see, that we implement PWA, and ask us if we want to install it in our system in the address bar (**App Available**).

[![PWA of Yummy Recipes UK on Microsoft Edge displaying that App is Available in address bar](/images/2022/08/pwa_yummy_recipes_microsoft_edge_app_available_address_bar.png)](/images/2022/08/pwa_yummy_recipes_microsoft_edge_app_available_address_bar.png)

We can also do that by clicking on a specific button for adding apps.

[![PWA of Yummy Recipes in Microsoft Edge displaying information when trying to install the app](/images/2022/08/pwa_yummy_recipes_microsoft_edge_app_installation_notification.jpg)](/images/2022/08/pwa_yummy_recipes_microsoft_edge_app_installation_notification.jpg)

---

Similarly to the above, where the browser will suggest adding the app to our system, we will be prompted to do that when browsing from Android.

Here how this will look like.

[![PWA of Yummy Recipes on Android with information in Google Chrome about possibility to add to Home Screen](/images/2022/08/pwa_yummy_recipes_android_chrome_add_to_homescreen.jpg)](/images/2022/08/pwa_yummy_recipes_android_chrome_add_to_homescreen.jpg)

As I am not using any Android device, I did my test using [LabmdaTest.com](https://www.lambdatest.com).

> Real-Time Testing > Browser Testing > Android, Samsung, Galaxy S20, Google Chrome.

---

On iOS and iPadOS we will not have such prompts. We need to use Share Sheet to add our app to Home Screen.

[![Adding PWA to Home Screen in iOS from Share Sheet](/images/2022/08/ios_add_pwa_to_home_screen_sharesheet.jpg)](/images/2022/08/ios_add_pwa_to_home_screen_sharesheet.jpg)

[![Adding PWA of Yummy Recipes to Home Screen in iOS](/images/2022/08/ios_add_pwa_to_home_screen.jpg)](/images/2022/08/ios_add_pwa_to_home_screen.jpg)

Once we launch our website, it will be brought nicely with a full-screen experience.

[![PWA of Yummy Recipes in full screen on iOS](/images/2022/08/yummy_recipes_up_full_screen_pwa_ios.jpg)](/images/2022/08/yummy_recipes_up_full_screen_pwa_ios.jpg)

---

In such simple way, we got implemented PWA into our website.

Without any external services, this can be implemented anywhere and developers with specific knowledge can use the full potential of service workers to push this even further.

What you may notice, some apps that are natively distributed through Google Play or Apple App Store are just a cover for PWA that is running in the background.

## Optimising Resources

**There is one more thing before you finish.**

Once we have all worked nicely, we shall do one more thing to make this solution even better.

You need to remember that the manifest file will be loaded along with the website. Icons specified there also will be downloaded in the background.

We need to remember to optimise these resources.

Where most hosting companies will compress text, the graphic can be served as they are.

It's always good to optimise the icons that we generated as you will see that you may reduce their size dramatically.

It's better to serve 8kB favicon in 512x512 resolution than 60kB prior, especially when you will not see the difference on screen.

To do that, use one of the below websites:
- [Compressor.io – optimize and compress JPEG photos and PNG images](https://compressor.io)
- [Optimizilla – Online Image Сompressor](https://imagecompressor.com)
- [Squoosh – ultimate image optimizer](https://squoosh.app)


---
## Simplified way of adding a favicon to the website
- **URL:** https://dariusz.wieckiewicz.org/en/simplified-way-of-adding-favicon-to-website/
- **Date:** 2022-08-11
- **Tags:** Favicon, Favicons, Evil Martians, six files, favicon.ico, PWA, WebDev, manifest.webmanifest

### Content

If you are not a first time on my website you already know, that I like simplifying things and using a minimal approach with a complex solution. Overall, if something complex can be done that same, but simple, why not try?

This time I want to cover Favicon during website design.

> "A favicon is a browser icon that represents a brand or website. Most often seen next to a web page’s title in browser tabs, favicons can also be found in address bars, bookmark lists, search results pages, toolbars, browser history, and other places across the web."
>
> [What is a favicon? @ blog.hubspot.com](https://blog.hubspot.com/website/what-is-a-favicon)

I don't want to reinvent the wheel, as there is already a perfect solution for that, well written and documented by [Andrey  Sitnik from Evil Martian](https://twitter.com/sitnikcode).

<!--more-->

He has created a great article, which was recently updated, on [How to add Favicon by using only 6 files](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs).

His article is your holly grail of the minimalistic approach to a favicon for every web developer. I am not planning to duplicate what is there but pick only a couple of bits that I will later need in my other post for [Simple implementation of PWA on a website with Mobile First Design approach](/en/simple-implementation-pwa-webdev-mobile-first-design/).

Having a rightly implemented favicon solution on your website is giving you an opportunity to extend it and use it in other useful solutions.

---

## Six files that fit most needs

This is the leading part of the minimalistic approach for favicon implementation.

You need in reality:
- One `.ico` file (with 48x48, 32x32 and 16x16 layout)
- Four `.png` files with your graphic in different dimensions (144x144, 180x180, 192x192 and 512x512)
- One `manifest.webmanifest` file

Apart from that, just a couple of lines of code pasted in a `<head>` and you are ready to go.

You can use various graphic software to make this file. How to use GIMP or Inkscape is widely described in [referred article](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs).

So, grab GIMP (preferably), follow the steps and prepare your `.ico` and `.png` files to be ready for the next step.

> I have added reference to 48x48 following refreshed Google Search Central Documentation that states "[Your favicon must be a multiple of 48px square, for example: 48x48px, 96x96px, 144x144px and so on.](https://developers.google.com/search/docs/appearance/favicon-in-search#guidelines)"

---

A couple of bits of advice from myself, that I learned when I prepared files for [implementation of PWA into my website](/en/simple-implementation-pwa-webdev-mobile-first-design/).

Do not go with transparency in your icons. It may look good in some instances, but this may not always be the case with the light and dark mode approach. Pick your background colour and stick with it. Typically will be white-ish or to match your website background colour.

The icons are square. Your logo not always is, but always matches it to the wider dimension.

On `favicon.ico` shrink it to the maximum width of 48 pixels (layer 48x48), 32 pixels (layer 32x32) and 16 pixels (layer 16x16). Make sure layers are squares.

On your `.png` files do not shrink your icons to the edges of the layers, go a bit further. I recommend shrinking your logo to a maximum of 88% of the width of the image layer and then centre it horizontally and vertically.

> In the 512x512 layer filled with your background fill the image with 450 pixels in the biggest dimension (roughly 88%).

This will allow the icon to be more universal with some software instead of trimming it on the edges.

> For the PWA approach you will need an icon that is "maskable". In that case, the image is reduced even further to the layer to fit nicely in rounded icon layouts. I will cover this in my PWA post.

## The Head

Different browsers "read" websites differently.

Some of the (outdated) guides advise you to just put your `favicon.ico` into the root folder of the website and you are all done.

**That's not always the best approach.**

It's not always only browsers that are using these files but also search engines, this is why we adding this as following (inside `<head>`):

```html
  <link rel="icon" href="/favicon-144.png" type="image/png">
  <link rel="icon" href="/favicon.ico" sizes="any">
  <link rel="apple-touch-icon" href="/apple-touch-icon.png">
  
  <link rel="manifest" href="/manifest.webmanifest">
```

We refer here to two out of four `.png` files, where `apple-touch-icon.png` is 180x180 in dimensions.

We serving a link to our `favicon.ico` and a `manifest.webmanifest` file that will cover on next step.

{{% ads-in-article %}}

## Web app manifest

Despite how its called, we not creating **a web app** but adding favicon to our website. 

> " Web Application Manifest... provides information about a web application in a JSON text file, necessary for the web app to be downloaded and be presented to the user similarly to a native app"
> .
> [Web app manifests @ developer.mozilla.com](https://developer.mozilla.org/en-US/docs/Web/Manifest)

Don't be scared with word JSON. You don't need to be an expert in that to get used to its layout.

This file will contain the following:

```json
{
  "icons": [
    { 
      "src": "/favicon-192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "/favicon-512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ]
}
```

As you see, we referring here to the other two out of four graphics files that we prepared.

---

These five files (1x `.ico`, 4x `.png`) plus one manifest, all saved in the root directory of our website, will serve multiple purposes for multiple browsers, search engines, operating systems and devices (Apple and Android).

And just like that, you got your favicon on the website sorted out.

---

Please, take your time and read the full [Evil Martian article about How to Favicon in 2022](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs).


---
## Rediscovering Progressive Web Apps (PWA)
- **URL:** https://dariusz.wieckiewicz.org/en/rediscovering-progressive-web-apps-pwa/
- **Date:** 2022-08-11
- **Tags:** PWA, Progressive Web Apps, Home Screen, iOS, Android, Google Chrome, Microsoft Edge, Mobile First Design, WebDev

### Content


Over the last years, I forget about something called Progressive Web Apps (PWA) until one day I **added to my Home Screen** a bookmark to [Homebridge](https://homebridge.io), and, believe me, or not, I do not add bookmarks that way very often.

When I added this bookmark to my Home Screen on iOS I noticed, that it looks unusual. The icon was like a native app. When I click on the icon it didn't open inside Safari like other bookmarks but it run on full screen like a normal native app. 

Of course, it was still Safari in the background but highly limited to the scope of that single website, that it feels like a native. It certainly can be confused with an app.

<!--more-->

{{% gallery %}}
[![Homebridge PWA icon on Home Screen (iOS)](/images/2022/08/homebridge_icon_on_home_screen_ios.jpg)](/images/2022/08/homebridge_icon_on_home_screen_ios.jpg)
[![Homebridge PWA on Full Screen (iOS)](/images/2022/08/homebridge_pwa_full_screen_ios.jpg)](/images/2022/08/homebridge_pwa_full_screen_ios.jpg)
[![Homebridge PWA on iOS App Switcher](/images/2022/08/homebridge_pwa_app_switcher_ios.jpg)](/images/2022/08/homebridge_pwa_app_switcher_ios.jpg)
{{% /gallery %}}

---

Recently the timeline on the Twitter app start annoying me to such an extent, that I found out that the website serves me with better, more relevant and not repeatable content.

Without resigning from Twitter App due to integrated Share Sheet functionality, I just added a bookmark to my Home Screen.

[![Twitter App icon side-by-side with Twitter PWA icon](/images/2022/08/twitter_app_side_by_side_with_twitter_pwa.jpg)](/images/2022/08/twitter_app_side_by_side_with_twitter_pwa.jpg)

To my surprise, the bookmark looks exactly like an icon of an app. It also behaves like an app. When you click on it you got a full-screen experience.

{{% gallery %}}
[![Twitter App – Home – iOS](/images/2022/08/twitter_app_home_ios.jpg)](/images/2022/08/twitter_app_home_ios.jpg)
[![Twitter App – Home - Settings – iOS](/images/2022/08/twitter_app_home_settings_ios.jpg)](/images/2022/08/twitter_app_home_settings_ios.jpg)
[![Twitter App – App in App Switcher - iOS](/images/2022/08/twitter_app_app_switcher_ios.jpg)](/images/2022/08/twitter_app_app_switcher_ios.jpg)
{{% /gallery %}}

As the website is highly mobile friendly, all looks great.

{{% gallery %}}
[![Twitter PWA - Home - iOS](/images/2022/08/twitter_pwa_home_ios.jpg)](/images/2022/08/twitter_pwa_home_ios.jpg)
[![Twitter PWA - Home - Settings - iOS](/images/2022/08/twitter_pwa_home_settings_ios.jpg)](/images/2022/08/twitter_pwa_home_settings_ios.jpg)
[![Twitter PWA - App in App Switcher - iOS](/images/2022/08/twitter_pwa_app_switcher_ios.jpg)](/images/2022/08/twitter_pwa_app_switcher_ios.jpg)
{{% /gallery %}}

To my surprise, I got a bit more options available in the left-side menu than in an app. Whoever prepared the mobile version of its website did a great job. They even think, in their design approach, about people who will be using only this method of accessing their platform.

In a bookmark, you may feel like in a normal app. You got even handy Display settings where you can customise Font Size, Colour and Background. From the menu you can even turn on the Data saver and access other settings that are not available in an app, or are, but hidden to such an extent, that they are hard to find.

From just a single screenshot, would you be able to see a difference? I doubt.

I have customised font size, so I see the difference now, but it's not as clear as you think.

{{% gallery %}}
[![Twitter App starting on iOS](/images/2022/08/twitter_app_starting.jpg)](/images/2022/08/twitter_app_starting.jpg)
[![Twitter PWA starting on iOS](/images/2022/08/twitter_pwa_starting.jpg)](/images/2022/08/twitter_pwa_starting.jpg)
{{% /gallery %}}

Oh yes, you will see the difference on launch. You will be greeted with a full-screen Twitter logo as in an app. On the web version, it will be a blue logo on white, when the app got its way around.

{{% gallery %}}
[![Twitter PWA loading a feed](/images/2022/08/twitter_pwa_loading_feed.jpg)](/images/2022/08/twitter_pwa_loading_feed.jpg)
[![Twitter PWA displaying Something went wrong where there is no internet](/images/2022/08/twitter_pwa_no_internet.jpg)](/images/2022/08/twitter_pwa_no_internet.jpg)
{{% /gallery %}}

Before you will see your "refreshed" timeline, the app is serving you with what was the last time preserved in a cache. On a web version (PWA), you will see a spinning wheel (even on a fast connection) as you need to be authenticated first in the background and then your timeline needs to load and refresh. When you are offline you will simply see a **Something went wrong** message.

Despite that, I have been using this way of accessing Twitter for some time and I like it. I like it to such an extent that I decided to rediscover again a Progressive Web App approach – the thing that I thought was long forgotten (how much wrong I was!).

---

{{% ads-in-article %}}

After Twitter, I decided to see what else can be done that way.

On daily basis, I am accessing [Hugo Discourse](https://discourse.gohugo.io). I am doing that mostly through the browser, however recently I found out, that there is an app for that called [Discourse Hub](https://apps.apple.com/app/discourse-hub/id1173672076).

It's great that there is an app where you can add multiple Discourse-based forums to access, but when accessing just one, this requires you "one step" too much. You need to open an app and click from the list of which Discourse you want to access.

On bookmark in Safari, I just going and I am there.

Same way as with Twitter, and as an alternative to the Discourse Hub app, I added a bookmark to my Home Screen.

{{% gallery %}}
[![Hugo Discourse forum as PWA on full screen in iOS](/images/2022/08/discourse_hugo_pwa_full_screen_ios.jpg)](/images/2022/08/discourse_hugo_pwa_full_screen_ios.jpg)
[![Hugo Discourse forum as PWA on App Switcher in iOS](/images/2022/08/discourse_hugo_pwa_app_switcher_ios.jpg)](/images/2022/08/discourse_hugo_pwa_app_switcher_ios.jpg)
{{% /gallery %}}

To my surprise, this discourse is a Progressive Web App as well nicely opening on full screen and limiting navigations to just forward and backward buttons on the bottom (which are not working perfectly).

The icon (with black fill around the hexagon logo) is a bit that could be improved, but an overall good mobile experience.

---

I got some websites the majority of users (over 80%) accessing it from the desktop but got as well others, where close to 100% of users are on mobile.

When your website is ready for mobile, why not go a step further and not do a [Simple implementation of PWA on a website with Mobile First Design approach](/en/simple-implementation-pwa-webdev-mobile-first-design/).


---
## Apple Service Experience - To Infinity and Beyond
- **URL:** https://dariusz.wieckiewicz.org/en/apple-service-experience-to-infinity-and-beyond/
- **Date:** 2022-08-10
- **Tags:** Apple Watch, Watch, Apple, Series 6, Series 8, Battery, Battery Health, Battery Service, Battery Replacement, Apple Service, Apple Support, Apple Support Experience, Apple Service Experience

### Content

Not so far ago I wrote down about how my [Apple Watch didn’t last as long as I expected](/en/my-apple-watch-didnt-last-as-long-as-expected/).

I recalled my Apple Watch 4th generation that had been with me for two years before I changed to the newest model at the time. The S6 didn’t do that well.

<!--more-->

At the time I contacted Apple Support to see what are my options. Through the chat, we run some remote watch diagnostics but I haven't got further with battery replacement at the time. I was still thinking about a possible upgrade instead.

I have been looking into rumours on what we could expect in September but as close as we get, it hasn't been too “exciting” to wait and upgrade to S8.

The battery on my S6 starts been annoying to such an extent that I decided that I will pass the S8 this year (also due to cost-cutting as everything is crazy expensive right now) and will replace the battery on mine to give myself at least one more year.

This could cost me £82.44, including all postage, but still way cheaper than a new Watch.

> Apple recently updated their service page and, right now, when you fill their form it gives you an estimate of £75 for battery replacement for my type of watch.[^1]

[![An estimate of Battery Service in UK for Apple Watch Series 6](/images/2022/08/apple_watch_battery_service_cost_estimate_UK.png)](/images/2022/08/apple_watch_battery_service_cost_estimate_UK.png)

[^1]: [support.apple.com/en-gb/watch/repair](https://support.apple.com/en-gb/watch/repair)

I decided to give it a green light.

Instead of booking a service over the website, I decided to have one more chat to see if there is any option to replace my battery as I wait. The vision of being without a watch for up to 10 days wasn’t great, hence would like to check what else was available.

During the chat, I have been advised that this model is only done when posted. As a first option, I could arrange, over a chat, a box to be sent to me and in which it will go back for repair or, as a second option, make an appointment at Apple Store where a store will send it for me.

I decided on the first option, as this will be much quicker and more convenient.

Before the box has been arranged for me, the person on the other end would like to do a once again diagnostic procedure.

We went through that.

Through the process of arranging repair (battery replacement), I was advised that I need to unpair my watch to allow the system to generate things on their end (later I could pair back and restore from backup). Doing that support generate a service case, arranged box to be posted and job to be done.

In the meantime, I asked how much I need to pay now. 

To my surprise have been advised that they will send a box at their expense and once the watch will arrive, they will verify its condition, will check if is not water damaged etc, and then will let me know how much I will need to pay.

It sounds fine to me.

Box arrived in next day (Friday) through UPS.

I used a watch over the weekend and send it back on Monday morning using provided box and UPS shipping label.

Just on the next day (Tuesday) I received confirmation that my watch arrived and is subject to diagnostics.

All sound fine. 

![A header of an email from apple stating that they will start the repair now](/images/2022/08/apple_well_start_the_repair_now.png)

One thing was a bit odd, that email stated that “We’ll start your repair now.”

Hmm…

I thought that before they will proceed, they will send me a quote or invoice to pay, but not.

Unsure why, but not so far later I received an email that my replacement product will ship soon.

![A header of an email from apple stating that they will send me a replacement](/images/2022/08/apple_our_technicians_have_completed_diagnostics_email.png)

> “Our technicians have completed their diagnostics and will send you a replacement product. We’ll let you know when the replacement product is on its way.”

Still no request for payment. I started thinking that after a close look up, service found an issue, or even potentially a cause of that in my particular model, that the battery didn’t last as long as it was designed. 

I haven’t heard about any recalls related to battery recently, hence all been a bit strange.

At the end of the day, after just less than 12 hours in service I got another email stating:

![A header of an email from apple stating that my replacement is on its way](/images/2022/08/apple_watch_on_its_way.png)

> “Your repair request is complete and we're sending you a replacement product. You should receive it in about two business days.”

Wow!

{{% ads-in-article %}}

I have been prepared to pay for my new battery replacement. Overall, for this product, I haven’t got Apple Care purchased (like for others that I have) and it was far over the statutory 12 months warranty.

I don’t complain. In the end, I will get a full working watch. A replacement, probably refurbished, but still, without a fault in battery.

I think the person in the initial chat thought that there may be some external issue with a watch, possible crack and water damage, but no. I care for my Apple products. They are expensive and they deserve decent care, a decent case and a decent screen protector.

My watch hasn’t been any different. There was no scratch on it, even a single one, as all the time was protected by a full silicone body. Apart from the only scratch on Digital Crown, which was protruding outside a case, without battery issue, I could think about selling it in prestige condition.

Even, if due to this nonsense of Brexit they would decide to replace my watch instead replacing the battery (delay in parts), I would expect that I will be still charged for it.

It’s not the first time that I used Apple Service. They always going a step forward in serving customers, especially if they care (customers) about their own devices. Their products are expensive, but sales experience in many cases exceeds customer expectations.  

You paying extra, so when you need support, you are receiving a bit extra.

It’s not like with other brands, where I would be advised to just buy a new one as repair will cost way more than a new watch.

This is Apple and their approach is way better, better to infinity and beyond!

---

My replacement Apple Watch was despatched on the same day as my watch landed with them. Thanks to this unexpected express service I have just been without a watch for three days, even though I initially planned this to be a bit longer.

With the current economic crisis, unintentional saving on the cost of repair is highly appreciated and you cannot expect anything more!

The new watch, independently if refurbished or new (will not complain about that), comes in condition, as you would expect buying it new from the store. Overall refurbished experience directly with Apple is something that I would highly recommend to everybody. I purchased my [MacBook Air M1](/en/leap-forward-apple-silicon/) in such condition, and when arrived I would not be able to tell the difference between the new unit and this one.

Summarising my experience – another satisfied customer who will stay with the brand a bit longer!


---
## Measuring internet speed directly from the OpenWrt router
- **URL:** https://dariusz.wieckiewicz.org/en/measuring-internet-speed-directly-from-the-openwrt-router/
- **Date:** 2022-07-29
- **Tags:** OpenWrt, iperf3, speed test, internet speed, download, upload

### Content

Have you ever struggled to measure the true speed of your internet?

Each router is different, and additionally, WiFi wireless networks come in different standards, on different frequencies and offering different speeds depending on external factors.

If our computer has a card that only supports 2.4GHz at a speed of 54Mbps, we can have 100, 200 or more Mbps, and we will not go faster than 54Mbps.

Some 2.4GHz networks can even offer 300Mbps. In the case of 5GHz and speeds go up significantly. This does not mean that we are always able to achieve the offered speed.

If we have 3 devices that actively use the WiFi network, the network capacity, i.e. the maximum speeds we can achieve, is also divided by three.

Therefore, to properly measure the internet speed, you would need to connect directly, preferably by cable, to the router and be the only user for whom the entire bandwidth would be available.

If you have a router with OpenWrt software, you can measure the connection speed directly from the router, bypassing all users.

<!--more-->

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

This test is much more reliable because it involves direct communication between our device and our Internet service provider.

> Ignoring the limitations of international connections, the method described below can give us the closest result to reality.

The best way to check the network speed is by using **iperf3**, which we install on our router with the following command:

```bash
apk update
apk add iperf3
```

It is the `iperf3` tool that is most often used to check the speed in a local network between one computer and another.

We run the server on one of them and the client from which the measurement is performed on the other.

The same method can be used to check your internet speed.

However, we will not be setting up a server on the other side of the world. For this purpose, we will use publicly available servers for this purpose ([Public iPerf3 servers](https://github.com/R0GGER/public-iperf3-servers)).

## Command

Here is my command to check download speed (Download):

```bash
iperf3 -c iperf.par2.as49434.net -4 -R -p 9223 -t 20
```

Here is my command to check upload speed:

```bash
iperf3 -c iperf.par2.as49434.net -4 -p 9223 -t 20
```

## Command description

By default, when we run **iperf3** it tests the upload speed. By adding the `-R` parameter we can reverse the testing method from upload to download.

Using the `-c` command we run the program in client mode, and the address `iperf.par2.as49434.net` is our server.

> You can choose the server from [Public iPerf3 servers](https://github.com/R0GGER/public-iperf3-servers)

If our internet supports only IPv4 by default, then we specify it with the parameter `-4`. In the case of IPv6 it will be similarly `-6`.

Each of the [servers on the list](https://github.com/R0GGER/public-iperf3-servers) can work on a different port. Some servers offer a range of ports. To specify the port, we use the `-p` parameter. In the above example, the port is `9223`

The `-t` parameter specifies how long the speed measurement should take. The default is 10 seconds, but I usually prefer to extend it to 20 seconds, hence `-t 20`.

{{% ads-in-article %}}

## Results

Each server offers different bandwidth, so it's worth trying a few during testing.

Sometimes we may encounter a response that the server is too busy (Busy), or that our attempt has been blocked (Connection refused). In such cases, we should try another server.

In my case, with a 200Mbps download speed (Download) I got:

[![Result - Download speed measurement using iperf3 directly on the OpenWrt router](OpenWrt_SpeedTest_iperf3_download.png)](OpenWrt_SpeedTest_iperf3_download.png)

Whereas at 20Mbps upload speed (Upload):

[![Result - Upload speed measurement using iperf3 directly on the OpenWrt router](OpenWrt_SpeedTest_iperf3_upload.png)](OpenWrt_SpeedTest_iperf3_upload.png)

Sounds good.

I say "sounds" because if I compare these results, for example with the test on [speed.cloudflare.com](https://speed.cloudflare.com), I can see fluctuations and differences, depending on what connection method I use and how many active users I have in the network.

---
To make testing easier, it is worth creating a file on the router that we can run without having to remember the entire iperf3 command.

```bash
echo "iperf3 -c iperf.par2.as49434.net -4 -R -p 9223 -t 20" > speedtest4
chmod +x speedtest4
```

To run:

```bash
./speedtest4
```

Regards.


---
## Optimising CPU usage on OpenWrt router
- **URL:** https://dariusz.wieckiewicz.org/en/optimising-cpu-usage-on-openwrt-router/
- **Date:** 2022-07-28
- **Tags:** OpenWrt, irqbalance, multicore, Linksys WRT3200ACM, Linksys WRT32x, Linksys MR8300, Askey RT4230W REV6, RAC2V1K, Spectrum RAC2V1K, RAC2V1K OpenWrt, procesor, Optimization, Packet Steering, proc, interrupts

### Content

My OpenWrt adventures began with the ASUS RT-AC56U router. It was a fairly good, cheap router with a dual-core Broadcom BCM4708A0 processor clocked at 800MHz. It also had 128MB of flash memory and 256MB of RAM.

Appetite grows with eating, as the saying goes.

While I didn't complain about the processor, I quickly ran out of space for more of these applications. So I decided to replace it with a Linksys WRT3200ACM, which I later changed to a Linksys WRT32x.

WRT3200ACM (WRT32x) is a very solid machine, we still use this type of router at work. While I was pleased with its performance, the WiFi network did not work out very well.

The signal strength left much to be desired, and cooperation with other routers or access points was not without problems. All because of the wireless chip from Marvell used in it.

Additionally, the lack of support for DFS channels in WiFi in the 5GHz frequency further limited its use. Also, forget about WPA3 encryption introduced by default in the OpenWrt 21.02 series (WPA3 can be turned on, but WiFi and the entire router quickly stop working).

In my search for a better router, I came across the Linksys MR8300. It had 3 Qualcomm Atheros radios. One was for the 2.4GHz frequency and the other two for 5GHz, the first for channels up to 60 and the second for above 100 (with DFS support).

While the router performed well, it was clear to see that it was much slower, especially when installing software.

<!--more-->

The WRT3200ACM (WRT32x) had a dual-core 1866MHz processor, while the MR8300 had a quad-core 717MHz.

Theoretically, performance should have been similar due to the larger number of cores, but it wasn't.

While my internet speed increased from 100/10Mbps to 200/20Mbps I additionally noticed that the router started to choke, especially when it had [internet link optimization](/en/optimising-internet-connection-router-openwrt/) enabled using SQM QoS.

SQM QoS did not perform above 100Mbps and after disabling it, 200Mbps could be achieved without any problems.

Unfortunately, enabling Packet Steering in **Network > Interfaces > Global network options** did not help.

> Packet Steering allows packets to be managed using all available processors in the system, in this case cores (of which the MR8300 has four).

I was forced to disable SQM QoS until I find a solution to this problem. I suspect I will be checking this out when the stable OpenWrt 22.03 version is released, where Firewall 4 will be introduced.

However, I decided to delve deeper into the aspect of using the computing power inherent in the four cores of the Linksys MR8300.

In my searches I came across a command that shows how our processor and its cores are being used.

```bash
tail /proc/interrupts -n 100
```

This allowed me to see that the first core was working overtime while the other three were slacking off.

[![Linksys MR8300 with OpenWrt before enabling irqbalance](OpenWrt_Linksys_MR8300_pre_irqbalance.png)](OpenWrt_Linksys_MR8300_pre_irqbalance.png)

I decided to do something about it.

While browsing the official OpenWrt website I came across the [**Irqbalance**](https://openwrt.org/docs/guide-user/services/irqbalance) package.

The purpose of this package is, literally translated, "distribute interrupts across multiple logical processors (cores)". In short, distribute commands from the main core to all available ones.

> Irqbalance is a Linux daemon that distributes interrupts over multiple logical CPUs. This may result in improved overall performance and even reduced power consumption.

This package is not available by default in the system and its installation does not automatically enable it. This is dictated by the fact that in the case of devices up to two cores, the performance increase is minimal or causes its deterioration.

In the case of the Linksys MR8300, which has four cores, it is worth trying.

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

I updated the packages and installed **irqbalance**

```bash
apk update
apk add irqbalance
```

If you wish, you can also install the LuCI web interface by adding `luci-app-irqbalance`.

By editing the configuration file, I enabled its automatic start
```bash
nano /etc/config/irqbalance
```

```
 option enabled '1'
```

Then I started it manually
```bash
/etc/init.d/irqbalance start
```

{{% ads-in-article %}}

After a while it was obvious that the 3 lazy cores had started working for bread.

```bash
tail /proc/interrupts -n 100
```

[![Linksys MR8300 with OpenWrt after enabling irqbalance](OpenWrt_Linksys_MR8300_post_irqbalance.png)](OpenWrt_Linksys_MR8300_post_irqbalance.png)

After performing several tests, including downloading files from torrents (see [how to add a torrent client to a router with OpenWrt](/en/adding-torrent-client-router-openwrt/)), which in the initial stage always caused the router to slow down, I saw a slight improvement.

> Load Average	1.44, 0.83, 0.50

It's not great, but it's always better than nothing.

I still had to forget about SQM QoS, but at least I can see that the router's CPU is being utilized to a higher extent than before the change.

The ideal would be to have a Linksys WRT3200ACM (WRT32x) processor and a MR8300 wireless network card.

If you are interested in using OpenWrt for more advanced purposes, then it is worth considering creating a router using Raspberry Pi 4 and separate WiFi points.

If only the [Askey RT4230W REV6 / RAC2V1K](https://openwrt.org/inbox/toh/askey/rt4230w_rev6) (not SAC2V1K) were available to play around with on this side of the globe, then we might have an affordable **powerful** alternative to the WRT3200ACM (WRT32x) or MR8300, which is supposed to be officially supported in OpenWrt 22.03.

> I took the plunge and bought from the US via eBay UK **Askey RT4230W REV6 / RAC2V1K**. I flashed OpenWrt without having to open the case and everything works beautifully.

Regards.


---
## Revisiting YummyRecipes.uk after 3 months (a Hugo based website)
- **URL:** https://dariusz.wieckiewicz.org/en/revisiting-yummyrecipes-uk-after-3-months/
- **Date:** 2022-07-23
- **Tags:** Yummy Recipes, Yummy Recipes UK, Hugo, Google Search, Google Discover, Google Search Console, Performance, WebDev, WebPerf, ahrefs, Facebook Insights, Instagram Insights

### Content

Just today, on the 23rd of July [Yummy Recipes UK](https://yummyrecipes.uk) is celebrating the third month from the lunch of the website. We (me, from the development side, and my friend, from the content) didn’t see what was coming.

At the lunch the ambitions were high, but also reality brings us down a bit, as we saw plenty of cooking websites around that we will need to compete with.

During the first two months social media, mainly Facebook, dominates in popularity. Over 1000 people on average viewed each recipe that we shared, whereas our website got only a portion of visits. 

<!--more-->

[![Facebook and Instagram Insights of Yummy Recipes UK over 3 months](/images/2022/07/YummyRecipes_Insight_Facebook_Instagram.png)](/images/2022/07/YummyRecipes_Insight_Facebook_Instagram.png)

> I thought that Instagram will take a greater role in shaping popularity, but Facebook showed a different story. Surprise, surprise.

[![Yummy Recipes UK initial visits chart from Google Analytics](/images/2022/07/YummyRecipes_users_first_months_Google_Analytics.png)](/images/2022/07/YummyRecipes_users_first_months_Google_Analytics.png)

From the initial hype in the number of website visits, the search (through Google) was growing slowly. The new domain hasn’t got an authority but I knew that the website was constructed well using all possible SEO aspects, so we keep concentrating on publishing regularly (every Tuesday and Friday) new content hoping to find its audience.

> We have tested a couple of variants with the first weeks, looking at the day of the week and [times to when to publish on Facebook, Instagram and Twitter](https://sproutsocial.com/insights/best-times-to-post-on-social-media/) until we settled with Tuesdays and Fridays around 10 am.

[![Yummy Recipes UK in ahrefs](/images/2022/07/YummyRecipes_ahrefs.png)](/images/2022/07/YummyRecipes_ahrefs.png)

I have been monitoring the website through various tools like **ahrefs**, but mainly **Google Search Console**. You can say whatever you want but Google is the biggest influencer if is going for the existence of your website.

Through Google Search Console I have been looking at the performance in Google Search, which was slowly growing.

Apart from search performance, Google is displaying something called Discover.

Google Discover is for me one of the most mysterious things that are there.

The main difference between Search and Discover is the fact that search appearance is based on what the user is searching (typing in the search box). Discover is based on algorithms that analyse user history (tracking through it) and present what they think (their algorithm) that the user may like. Because of that, there is no golden rule on how to highlight your presence there. 

Even the best SEO techniques will not help if users are not interested in it.

You may do a lot of recommendations towards Google Discover but you may never appear there. I got [a couple of the websites](https://github.com/idarek) (that are here for years) and none of them getting any or almost any traffic through Discover.

[![First hit in Google Discover for Yummy Recipes UK](/images/2022/07/YummyRecipes_Google_Discover_first_hit.png)](/images/2022/07/YummyRecipes_Google_Discover_first_hit.png)

On Yummy Recipes I saw one day hit in there. I thought, maybe this website will use this feature. After days all goes flat again so haven’t been too optimistic. 

[![Yummy Recipes UK performance in Google Search over last 3 months](/images/2022/07/YummyRecipes_Google_Search_performance.png)](/images/2022/07/YummyRecipes_Google_Search_performance.png)

We have been concentrating further (the author of the content) on publishing regularly and the search for it has been growing steadily (the Discover remained flat). I forget about that until I saw a higher than a normal number of visits in Google Analytics (anomaly) that had been reported as Direct traffic. This happens just before we hit the second month from the lunch of the website.

It was unusual and see that one recipe was suddenly more popular and performed in search better than others. Once I looked for that anomaly in Google Search Console I found that Discover start to spike again. That was a surprise but I haven’t been too excited until I saw the growth over the following days. 

I keep my head cool and waited to see if that was permanent or just another, this time a bit longer, an anomaly.

We quickly hit over 1000 impressions in Discover from which 5% account for clicks.

It didn’t stop there.

[![Yummy Recipes first impression in Google Discover](/images/2022/07/YummyRecipes_Google_Discover_first_impressions.png)](/images/2022/07/YummyRecipes_Google_Discover_first_impressions.png)

The next step was over 2000 impressions and roughly 3% of clicks.

The website, from a couple of visits a day (more on the day when we publish more content) reached 40 new users on average.

[![Yummy Recipes visits chart in Google Analytics after hits in Google Discover](/images/2022/07/YummyRecipes_new_users_Google_Analytics_Direct_Traffic.png)](/images/2022/07/YummyRecipes_new_users_Google_Analytics_Direct_Traffic.png)

That’s how the new month (July) started for us. 

Quickly we hit the peak of slightly over 2500 impressions to drop a bit on the following day but still keep in above 1000.

Admiring what is happening we keep our heads on our shoulders.

I keep looking at the performance of the website and implementing needed changes when my friend keeps working on new recipes.

---

{{% ads-in-article %}}

The reason why we lunch Yummy Recipes UK in such form as it is was the fact, that searching for recipes is a pain in the ass (let's say this straight).

The recipe shall contain a very short introduction, ingredients and method of how to prepare it.

The majority of high-traffic recipe websites forget about it putting their whole life story before they will come back and present their "simple" recipe.

It's mostly because they not creating recipes for their readers, but fulfilling them with unnecessary content only for SEO and positioning over search engines through plenty of keywords.

**Some recipes are simple and this is how they need to be.**

We may read them on our mobile phone or ask our smart speaker or smart display to read them for us. This is why we need to concentrate on what's important for our readers first.

---

When analysing other websites with recipes I noticed that most of them lack structured data (Schema) for recipes or if it is, they are with plenty of errors or empty bits. Even so, their recipes are promoted through Google Search (more than ours).

We tried to make everything neat and follow all the requirements for structured data (we don't publish a video for guided recipes, hence here we will report a warning in the schema validator). As we noticed, Google Discover is like that and we quickly stay there for longer.

[![Yummy Recipes after 3 months – chart from Google Discover](/images/2022/07/YummyRecipes_3_months_Google_Discover.png)](/images/2022/07/YummyRecipes_3_months_Google_Discover.png)

But... (there is always "but").

It's not like, that all recipes are promoted all the time. Peaks are showing that feeding website with fresh content on a timely basis is crucial for maintaining the trend.

Let's look at that a bit more...

[![Top pages of Yummy Recipes in Google Discover](/images/2022/07/YummyRecipes_Google_Discover_Top_pages.png)](/images/2022/07/YummyRecipes_Google_Discover_Top_pages.png)

Here are some of the top pages that are promoted well through Google Discover.

[![Chart for Yummy Recipes recipe for Chinese Style BBQ Chicken in Google Discover](/images/2022/07/YummyRecipes_Chinese_Style_BBQ_Chicken_Google_Discover.png)](/images/2022/07/YummyRecipes_Chinese_Style_BBQ_Chicken_Google_Discover.png)

Most of them are peaking a couple of days after they are published, like this recipe for [Chinese Style BBQ Chicken](https://yummyrecipes.uk/chinese-style-bbq-chicken/). After a couple of days, we fed the website with new content and the past one slowly fades.

But that's not only the case. 

[![Chart for Yummy Recipes recipe for Beef Casserole (Goulash) in Google Discover](/images/2022/07/YummyRecipes_Beef_Casserole_Goulash_Google_Discover.png)](/images/2022/07/YummyRecipes_Beef_Casserole_Goulash_Google_Discover.png)

Our most surprising content was [Beef Casserole (Goulash)](https://yummyrecipes.uk/beef-casserole-goulash/). This single recipe starts with good passion in Google Discover. Through its initial peak, it drops down like the other recipes but quickly regains popularity over the following days.

[![Yummy Recipes chart in Google Analytics after first 3 months](/images/2022/07/YummyRecipes_Google_Analytics_3_months.png)](/images/2022/07/YummyRecipes_Google_Analytics_3_months.png)

And so on, three months later social media become an addition to our website and finally we start seen better traffic through Google Analytics for our website (of course we using [minimal approach](/en/minimal-google-analytics-4-snippet/)). Traffic in the range of 70-90 new users on daily basis was something that we expect (our target for now).

[![Yummy Recipes performance in Google Search Console after 3 months](/images/2022/07/YummyRecipes_Google_Search_Console_Performance.png)](/images/2022/07/YummyRecipes_Google_Search_Console_Performance.png)

Going back to Google Search Console, we noticed that mobile users are dominant on the website and they are the most important visitors on which we should concentrate. 

Good job that we designed our website with this principle – to be responsive and good look good on mobile as in desktop view.

Using Hugo as a base gives us the necessary speed. The easiest way to adopt what things we need allows us to thrive in Core Web Vitals.

[![Yummy Recipes Core Web Vitals for Mobiles after 3 months](/images/2022/07/YummyRecipes_Core_Web_Vitals_Mobile.png)](/images/2022/07/YummyRecipes_Core_Web_Vitals_Mobile.png)

Form random analysis, if I see anything below green it's a sign for me to act. Recently noticed that LCP (Large Content Paint) so quickly implemented responsive images. With Hugo build-in Image Processing and WebP support, we start to be shown in green in Mobile Core Web Vitals in Google Search Console.

---

There is a lot in front of us. 

Currently, I am just using Visual Studio Code to edit not only the layout of the website but also prepare markdown files for publishing. In future, I am planning to take from my shoulders the time-consuming part of playing with markdown files and replace it with CMS for the static site (starting with [Netlify CMS](https://www.netlifycms.org)). Will need to have a look at how this will go, but from what I see and learn, my personal decision to use Hugo over other solutions (like WordPress) was the right one.

I would never expect that in 3 months, the new website to become as popular as it's now. It was a great success for me from the development part and definitely for an author of the content, seening that it is appreciated by many.


---
## It's too hot - and - it's too late to complain about it
- **URL:** https://dariusz.wieckiewicz.org/en/its-too-hot-and-its-too-late-to-complain-about-it/
- **Date:** 2022-07-18
- **Tags:** Hot, Temperatures, Heatwave, Law, Politics, Life, Employees, Workplace, Health and Safety

### Content

An extreme heat reached the UK today. Where temperatures easily will go above 40C (in shade!), days before, people, especially the working class, start looking into employment law, health and safety and all other guidance to see what rights they have and what employers need to do in their workplace.

To disappointment, all come to one conclusion... nobody is required to do anything about that.

<!--more-->

It's too hot? That's your problem, not your employer... **that's the conclusion** when you will start reading ANY guidances, including these from HSE [(Temperature - FAQ)](https://www.hse.gov.uk/temperature/faq.htm).

Living in the 21st century you may think that this shall be regulated somehow, but like Rashi Sunak said, that he has 'no working-class friends', don't expect that anything will change for us, employees.

> Yes, we will be reminding him what he said if he will (hope not) become the next PM. For you, a bit of advice: **Don't vote tory!**

We are all privileged if we work in an office that is fitted with air conditioning. Let's remember that others are not in such luxury.

The UK is not an exotic country. Summer with rain and temperatures around 21C is a bit of a norm. What we see right now is a perfect example of **global warming**.

Don't confuse **warming** with just a temperature. The effect of global warming and climate change is that all are classed as extreme conditions (unusual).

Extreme is when we reach over 40C in shade on one day, to have a forecast of just 23C on the next day. 

This 17C drop that's an effect of climate change as a result of global warming. It causes a shock for everybody, not only humans but also plants and animals, including bees, which are for us the most important creatures in the world. We may like them or don't but without bees, there will be no life on this planet.

> When you see annually a global movement to plant flowers for bees, please participate.

Going back to the temperatures.

When nobody cared to look at the law before, now it's too late to act (for this year's heatwave).

When the low temperature is stated (not as a law requirement) as 16C for workrooms (with 13C allowed with work that involves rigorous physical effort), the legislators prevent themselves from regulating the "too hot for work" citing that some work environments, due to its nature, are hotter than others, so they cannot simply put a figure on it.

If you can put a figure as a **low** for "workrooms" then you can do the same with high temperatures. This is all as guidance and it's not a law requirement, but when that's set, the people responsible for legislation shall create them (guidances) on what to do and what to consider to mitigate the negative impact on its employees.

If it's possible to put actions for "glass works or foundries" with relevant "controls", it's also possible to do this for others.

I worked in a past in a kitchen environment in summer. As a pastry chef and a baker, I understand how difficult is to put regulation of the maximum temperature when you operate a hot oven throughout the day. 

However, that doesn't change, that employees shouldn't have guidance that gives them some leverage – a list of things to consider by the employer and implement when it's too hot. Providing air conditioning may not be straightforward, but a fan that will allow air circulation can be something that may be put into action at a very low cost.

Let's don't leave everything for employers to sort out. When there is no requirement then nobody will do anything extra, as everything extra is a cost.

Nobody, however, calculates a cost when a person will collapse at work due to heat stroke.

**The law requirements are vogue.**

I understand the difficulty of specifying maximum temperatures, but a simple approach, when the temperature rises above, let's say, 15C of the typical average temperature then actions shall be taken.

> It's also not easy to state like that, as this will require from workplace to monitor temperature throughout the day. Every day.

The crazy is also, that employers don't need to carry out risk assessments regarding temperature unless there are a "significant number of employees complaining".

HSE in its FAQ provides guidance "What instructions should I give staff wearing personal protective equipment (PPE)?"

If you read through that:
> * permit work to occur at a slower rate
> * rotate staff out of this environment on a more frequent basis
> * allow longer recovery times before permitting re-entry
> * provide facilities for PPE to be dried so that it can be worn again for re-entry
> * consider scheduling work to cooler times of the days
> * periodically revisit your risk assessment to consider if the process could be automated or if alternative systems of work/controls can be introduced
> * re-evaluate your PPE as newer PPE may be lighter and provide improved levels of protection and operator comfort

{{% ads-in-article %}}

Some of these points shall be a standard point even for employees not wearing PPE but are exposed to abnormally high temperatures as we got right now.

We have been able to adjust our work environment during covid times, but we are not able to do something with what are we experiencing right now?

We will experience this type of "events" more often unless we sort out "global warming".

> We will probably be extinct before that. With such an approach from people in high places with a high ability to make relevant decisions, we are doomed.

It's way too late to raise awareness and shout for a change when an event (already) occurs. But some people are simply too busy (see Sunak) shouting to remove EU laws and bureaucracy and replace them with (worse) UK laws and bureaucracy, to think about ordinary people, the working class, the people who are responsible for this country to move forward.

It's not about an elite of 1-2% of reach people or these lazy buggers who don't want to go to work, as the benefits system is too generous for them. It's about all working people and those whose work is essential for others (sometimes not even paid adequately), like carers.

When others are playing games during debates, the real people are dying. The crucial services are struggling and nobody is looking to help, as some people, despite that, they are long longer formally serving, hiding from the crowds.

These people shall be called cowards.

They can be rich, they can be powerful, but they are still cowards.


---
## Google Search Console hidden gem!
- **URL:** https://dariusz.wieckiewicz.org/en/google-search-console-hidden-gem/
- **Date:** 2022-07-13
- **Tags:** Google Search Console, GSC, Settings, ahrefs, Crawling, Not Found, Not Found 404, Moved permanently, Moved permanently 301, Crawl stats, By response, Report, crawl requests breakdown

### Content

It's not very often that I am finding something new in a tool that I am using constantly, every single day. Unless it's announced as a new feature, I would not expect to find something, that is like a holy grail!

<!--more-->

Google Search Console is one of my standard tools through which I am monitoring the performance of my websites.

Even if it doesn't provide as much information as [ahrefs](https://ahrefs.com) (in its free plan), it's the first place where I am looking for things to improve.

I thought that I knew all, but then I found out that I was wrong.

Before I will go to the point I will start with the question, **after setting up GSC, how often will you go into its Settings?**

That's the thing with it. If GSC is providing us with links to the features like Core Web Vitals, Performance in Search and Google Discover, through indexing aspects and enhancements, rarely anybody will know, that there is something else.

The **Settings** of each property contain parts related to ownership, users and permissions, associations with Google Analytics and the option to change the address.

Apart from this, I would not expect to find there an option called **Crawling**.

[![Crawling section in Settings of Google Search Console](/images/2022/07/Crawling_section_in_Settings_of_Google_Search_Console.png)](/images/2022/07/Crawling_section_in_Settings_of_Google_Search_Console.png)

Under **Crawl stats**, when we will **open report**, we will find something very useful.

[![Crawling stats all in Google Search Console](/images/2022/07/Crawling_stats_all_in_Google_Search_Console.png)](/images/2022/07/Crawling_stats_all_in_Google_Search_Console.png)

Apart from obvious crawl stats, the number of requests, download size and average response time, if we will scroll further down, we will find **crawl requests breakdown** grouped by various categories.

[![Crawl requests breakdown in Google Search Console](/images/2022/07/Crawl_requests_breakdown_in_Google_Search_Console.png)](/images/2022/07/Crawl_requests_breakdown_in_Google_Search_Console.png)

Typically, when I set a website, I associate Google Analytics with it, and all [404 error pages I monitor with separate tracking](/en/track-your-404-traffic-the-smart-way/).

The problem with this method is that it's tracking everything and it's up to you to decide which links are crucial and require action and which don't.

In Crawl stats of Google Search Console we can go into a group **By response** and section **Not found (404)**.

We may not find there a lot, but if it's there then it's highly likely we shall take an action as Google and visitors consider them as still important.

Under important, I meant the links that were still generating traffic. Each of these traffic landing on a 404 error page will put our visitors off the website. 

Talking about **action** I consider implementing 301 redirects to grab the power of not found URL and pass it into a different part of the website.

When I migrated one of my websites [from Wordpress to Hugo](/en/from-wordpress-lover-to-wordpress-hater/) I moved some PDF documents as well.

When for the most important documents I implemented 301 redirects to new content, there are still some links in the wild (shared across the forums or other websites) that are still generating traffic. 

WordPress in its default approach doesn't generate links to files in an easy-to-manage manner, hence controlling it without an appropriate plugin is difficult. When we move or delete one file and replace it with another, if we forget to set redirect at the time, some links spread over the internet will put people on a 404 page. This lost traffic sometimes carries a lot of linking power and is worth using it.

[![Crawling stats for Not Found (404) in Google Search Console](/images/2022/07/Crawling_stats_for_404_in_Google_Search_Console.png)](/images/2022/07/Crawling_stats_for_404_in_Google_Search_Console.png)

Google Search Console will give us visibility when the last 404 was recorded so we can act upon that.

> 2.64k of crawled Not found (404) pages is something that we shall use for our benefit, especially if that is 14% of total crawl requests over the last 3 months.

Of course, the **By response** – **OK (200)** entries will not interest us too much, but a view into **Moved permanently (301)** provides with visibility into which old links are still gaining traffic.

> Google says to keep 301 redirects in place for a year but I found out that some links in the crawl stats are quite old and still gaining a lot of attention. Removing prematurely 301 redirects may not benefit us and a strict year period shall be treated only as a guide.

Apart from **By response** in crawl requests breakdown we will find grouping **By file type** (quite useful if we want to analyse out links to PDF files), **By purpose** or **By Googlebot type** (including grouping by Smartphones and Desktop devices).

I am really surprised that people at Google hidden such a useful piece of information buried under the **Settings**, a place, that after setting the property rarely somebody will head to without just goofing around looking what other information is there. This is the way I found it there, **crazy!**

{{% ads-in-article %}}


---
## Father-Daughter challenge on 100 words
- **URL:** https://dariusz.wieckiewicz.org/en/father-daughter-challenge-on-100-words/
- **Date:** 2022-06-28
- **Tags:** father-daughter, writing challenge, challenge, competition, mini saga, story, story told in 100 words, 100 words story, Ele Fountain, Young Writers, Young Writers UK

### Content

My daughter Anna book worm. She likes to read and from time to time writes on her own. Her creations can be found on [anna.wieckiewicz.org](https://anna.wieckiewicz.org) website.

She participates in some [YoungWriters.co.uk](https://YoungWriters.co.uk) competitions and wherever there is a possibility I trying to encourage her to participate.

This time through the June newsletter I try to engage her in Ele Fountain, Writing Challenge & Giveaway.

<!--more-->

![Ele Fountain – Writing Challenge & Giveaway – YoungWriters.co.uk](/images/2022/06/Ele_Fountain_Writing_Challenge-min.jpg)

The challenge was to encourage a child to write a mini-saga (a story told in 100 words) using the story starter from Ele Fountain: 

>'I pressed the light switch, but nothing happened –\
> seconds later, the television screen went blank.’ 

To make it more challenging, I compete with her. I told her that I will write my story and she will write to her. She like that. 

Here is my story called **"A dream"**.

---

## A dream

**"I pressed the light switch, but nothing happened -**

**Seconds later, the television screen went blank."**

The glowing unicorn starts bouncing around the garden,

Would like to see it, but the curtains didn't let me.

The clock showed midnight and start talking to me in a funny voice...

Tried to listen, but couldn't hear a thing as my head was filled with music.

The music keeps growing in me and felt my feet start floating.

Sparks appeared from the corners of the room -

Bang! My body landed on a bed and my face become wet.

My dog start licking my face and said to me... Good Morning!

---

{{% ads-in-article %}}

Anna's story can be found on her website [anna.wieckiewicz.org/writing/zombie-apocalypse](https://anna.wieckiewicz.org/writing/zombie-apocalypse/), and was submitted to the competition. Hope you will like it the same as I have.



---
## Trying Parallels Desktop alternative - UTM
- **URL:** https://dariusz.wieckiewicz.org/en/parallels-desktop-alternative-utm/
- **Date:** 2022-06-26
- **Tags:** Parallels Desktop, Parallels Desktop alternative, UTM, Windows 11, Ubuntu, Ubuntu Jammy, M1, macOS, hardware virtualization, virtualization, Parallels Tools, SPICE Guest Tools, SPICE, SPICE Agent, QEMU Drivers, QEMU, QEMU Agent, spice-vdagent, Microsoft Store, Windows Update, Skip_TPM_Check_on_Dynamic_Update.cmd, Windows Insider, Insider, Windows Insider Programme, Insider Programme, VHDX, UUP dump, WhyNotWin11, Offline Insider Enroll, Offline Insider, Insider Enroll, EFI, TPM, TPM 2.0, Secure Boot, Bypass

### Content

I have been using Parallels Desktop since 2014. Initially, I purchased a full licence which I upgrade roughly every year. The upgrade was a bit necessary as related closely to the macOS updates and new functions introduced.

Over the years the business model of the company behind this software changed.

Introducing the subscription model, Standards and Pro versions put a bit of confusion. At the time I stuck with version 15 for some time until I upgraded to MacBook Air M1 in 2021. 

I was forced to move into version 17 to get the support for Apple Silicon however I found a good deal at the time (a bundle deal) so was happy with it. Once my subscription was up for renewal I was greeted with a renewal fee of £79.99!

For the last few months, I haven't been using this software often enough, so I start thinking, do I need it? Is there any alternative that offers Windows OS on macOS with an M1 chip that is finally worth considering?

<!--more-->

---

Recently [VMware announced releasing a public tech preview of their emulation software for Apple Silicon](https://blogs.vmware.com/teamfusion/2021/09/fusion-for-m1-public-tech-preview-now-available.html). Despite that software has been available (in beta stage) for free, there was a hustle in getting Windows 11, based on ARM, working on it.

No support for VHDX files and blaming Microsoft because of no official support for their operating system for Apple Silicon, doesn't look great. Despite that, there were some examples of how to install it in different ways (using [UUP dump](https://uupdump.net)), but the lack of support for post-installation tools that would normally add necessary drivers doesn't make me optimistic about it.

I sadly shelved this solution and moved on.

---

Just days before my renewal I have been thinking about it again. 

Everything is going up, and the cost of living is sky-high, even in the UK so I need to make a decision, do I use this software enough to pay for it? My answer was **no**.

I got a spare Windows laptop at home that I can use when needed, as well I got access to Windows devices at work.

**I cancelled my renewal and let the subscription run out.**

> The annoying bit was, that I was asked to pay £79.99 (contacted customer service about that as well) for renewal where if you go directly into Parallels Desktop website you been offered a price of £61.24 for a year. Not mentioning that upgrade is listed as £39.99. Crazy!

[![Buy Parallels Desktop for Mac](/images/2022/06/buy_parallels_desktop_for_mac.png)](/images/2022/06/buy_parallels_desktop_for_mac.png)

[![Upgrade To Parallels Desktop 17](/images/2022/06/upgrade_to_parallels_desktop_17.png)](/images/2022/06/upgrade_to_parallels_desktop_17.png)

Apart from Windows (I am using Windows 11 Insider Preview ARM64) I have been using Ubuntu from time to time (mostly for evaluating possible issues when building websites with [Hugo](https://gohugo.io)).

I have been looking to have at least Ubuntu and I come across [this YouTube video](https://www.youtube.com/watch?v=0AA8MgbdmmA) and [UTM software](https://mac.getutm.app).

UTM is compatible with M1 macs and allows to run not only Ubuntu but also Windows 11 Insider Preview using a similar method as used in Parallels Desktop – by using the official [Microsoft VHDX file](https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewARM64)!

The software is free and advertised as "QEMU without headache". It is based on QEMU but allows all users to have the flexibility and what's most important – simplicity.

It's like with Parallels Desktop, in which after installation of Windows 11 you need to install Parallels Tools to get necessary drivers installed across the system, so all functions are working well. With UTM (which is more with QEEMU) you are getting [SPICE Guest Tools](https://mac.getutm.app/support/) with drivers for Windows to fulfil the gap. From Ubuntu, you just install them using `sudo apt install spice-vdagent spice-webdavd` from repositories.

---

UTM is not only **free**, but you can also contribute to its development on [GitHub](https://github.com/utmapp/UTM).

It's available to [download from the official website for free](https://mac.getutm.app) or directly from [Mac App Store](https://apps.apple.com/us/app/utm-virtual-machines/id1538878817) for a minimal fee.

The Mac App Store version is the same as free (downloaded DMG file) but through a small one-time price tag you not only get automatic updates but you are showing your support to its creators.

UTM is not a direct competitor to Parallels Desktop. Behind Parallels Desktop there are a bunch of people involved and a much bigger budget. This is why, through their proprietary solutions, you can play advanced games on it, whereas on UTM (QEMU based) you may not be able due to a lack of support for 3D acceleration (like OpenGL and DirectX).

As stated on the UTM website:
> "You may be able to run older games with software rendering options, but nothing with hardware acceleration. There is experimental support for hardware OpenGL acceleration on Linux through Virgl."

I am not playing games but rather testing software in the virtual environment. Many software from top players are available natively on macOS, hence I don't need to rely on virtualised Windows machines in my daily routine. In that case, if I can get a similar experience and usability as I used to have on Parallels Desktop I am eager to try.

Also, if I found that UTM is doing its job, I am happy to pay [£8.99 for the Mac App Store version](https://apps.apple.com/us/app/utm-virtual-machines/id1538878817) to show my support for the author, same as I did with software like [Keka](https://mas.keka.io/).

> I decided to show my support to the creator of UTM and purchased it.

## Installing Windows

[![Windows 11 - UTM - Almost There](/images/2022/06/windows_11_UTM_almost_there.png)](/images/2022/06/windows_11_UTM_almost_there.png)

Having downloaded Microsoft image (VHDX) started the fun and followed with [Windows 11 Installation instruction on UTM](https://mac.getutm.app/gallery/windows-11-arm#instructions) which I finished with the installation of SPICE Guest Tools.

Installation goes smooth. There was a poor resolution at the beginning and need to used to scrolling the opposite way on my trackpad (I changed this later in UTM settings), but nothing too annoying. 

I faces an issue with lack of network connectivity, but [followed troubleshooting steps as described](https://mac.getutm.app/gallery/windows-11-arm#troubleshooting) all started working well.

There was also this thing about Windows informing that there is no internet connection due to not working `ping`, but that is mentioned in troubleshooting as well. After installing SPICE all goes back as it should.

While on Parallels Desktop, when installing from the same VHDX file I do not face this, on UTM I have been greeted with the information that `System requirements not met. Please go to Settings to learn more`.

Nothing unusual, as relates mostly to lack of TPM and Secure Boot as highlighted by [WhyNotWin11](https://github.com/rcmaehl/WhyNotWin11).

[![Windows 11 Pro from VHDX - No Product Key](/images/2022/06/windows_11_pro_from_VHDX_no_product_key.png)](/images/2022/06/windows_11_pro_from_VHDX_no_product_key.png)

When, in mentioned YouTube video, the author concentrate on getting Windows 11 for free (?!?), I have a licence already that I used on Parallel Desktop, so this time as well I used it.

[![Windows 11 from VHDX Activated](/images/2022/06/windows_11_from_VHDX_activated.png)](/images/2022/06/windows_11_from_VHDX_activated.png)

I go into **Settings > System > Activation** and I provided (through change product key) my licence.

> I noticed that Copy and Paste between environments have been working well thanks to SPICE.

The initial performance of Windows 11 wasn't something superior. Overall Windows 11 is crazy it is going about minimum requirements.

If there would be an option to get an Official ARM-based Windows 10 I would go with it, but there is none.

> BTW, Windows 11 is also not available for ARM as a final product, only through Insider Preview.

---

Interesting is that Windows 11 Insider Preview Client ARM64 does not ship with Microsoft Store (at the time of writing this article it was 22598.1, 22H2) and to get it I would "need to install x64 version" (but can I?).

Where the [instruction](https://mac.getutm.app/gallery/windows-11-arm#instructions) refers back to Parallels Desktop guide, the Parallels removed it from their website once they replace it through building into its software solution to add Microsoft Store during installation.

In my instance, the missing Store may have something to do with `System requirements not met`. Microsoft mentioned that it will make life harder for people installing Windows 11 on unsupported hardware. Where Parallels Desktop does nice work concealing its hardware and pretending that it's meeting the requirements, the UTM is not so lucky.

But there may be a bypass for that by launching PowerShell as an Administrator and typing:

```powershell
iwr -useb https://raw.githubusercontent.com/DaBigBlob/ms-store-arm64/main/allowARMv2.ps1|iex

wsreset -i
```

> Read more: [Microsoft Store on ARM64 (for UTM)](https://dabigblob.github.io/ms-store-arm64/)

{{% ads-in-article %}}

Patiently wait and the Store Experience Host installs in the background. You may have some notifications about that pop-up in the right bottom corner or some hanging-in notifications (when clicked on the clock in the right bottom corner).

---

The fact that UTM doesn't support (yet hopefully) SecureBoot or TPM is a bit of a problem, as your Windows Insider Program channel options will be limited and you will not be able to go into Dev (for example, in the current Dev channel there is ARM64 based Store available).

I am also greeted with the information that `A newer build is available in Windows Update` however I am unable to try that, as it looks like Microsoft finally start doing what was told and started blocking updates on computers where `System requirements not met`.

There are active issues open on Github regarding UEFI Secure boot ([#3102](https://github.com/utmapp/UTM/issues/3102)) and TPM module emulation ([#3082](https://github.com/utmapp/UTM/issues/3082)), so it's worth to look to see how the progress will go.

> There is an option to add Software TPM on macOS however due to sandboxing of the applications, UTM is not able to communicate with another app, which is outside its privileges.

Parallels Desktop has already sorted this out with their solution. Will see how this will go with UTM.

---

Going back to the manual update...

The download process (on my 100MB connection) and creation of the ISO file took around 10 minutes.

[![Windows 11 - Setup - TPM and Secure Boot requirements](/images/2022/06/windows_11_setup_tpm_secure_boot_not_met.png)](/images/2022/06/windows_11_setup_tpm_secure_boot_not_met.png)

Once I run `setup.exe` from extracted ISO I was greeted with a warning that `This PC doesn't currently meet Windows 11 requirements` due to lack of `TPM 2.0` and `Secure Boot`.

So I head to [AveYo repository on GitHub](https://github.com/AveYo/MediaCreationTool.bat) and downloaded, as a ZIP file, the whole repository (under the green expandable code button).

From `bypass11` folder I run `Skip_TPM_Check_on_Dynamic_Update.cmd` and I started again `setup.exe` and carry out with installation as normal.

[![Windows 11 - Setup - Ready to install](/images/2022/06/windows_11_setup_ready_to_install.png)](/images/2022/06/windows_11_setup_ready_to_install.png)

> I haven't got an option to `Keep files, settings, and apps`, just `Keep personal files only` or `Nothing`. I stuck with `Keep personal files only` this time.

[![Windows 11 - Setup - Installing Windows Server](/images/2022/06/windows_11_setup_installing_windows_server.png)](/images/2022/06/windows_11_setup_installing_windows_server.png)

What was interesting was, that when I clicked Install on the full-screen installation screen stated `Installing Windows Server` (?!?).

Patiently waited for installation to finish. It was way shorter than I expected.

After a couple of reboots have been greeted with the 22621 version installed and... poor graphics resolution due to missing SPICE.

> As you remember, we selected `Keep personal files only`.

After SPICE has been installed and the virtual system restarted, all is back to normal.

The surprise was missing a watermark on the desktop stating `System requirements not met` and getting further cumulative updates waiting for me in Windows Update.

[![Windows Insider Programme - Your PC does not met the minimum hardware requirements](/images/2022/06/windows_insider_programme_does_not_meet_the_requirements.png)](/images/2022/06/windows_insider_programme_does_not_meet_the_requirements.png)

The only information where `System requirements not met` was stated was when I went into `Windows Insider Programme` settings. It looks there that I am no longer an enrolled Insider member.

[![Windows Insider Programme - Device Enrolled Using OfflineInsiderEnroll](/images/2022/06/windows_insider_programme_enrolled_offline_insider_enroll.png)](/images/2022/06/windows_insider_programme_enrolled_offline_insider_enroll.png)

For that, I used referenced [Offline Insider Enroll tool](https://github.com/abbodi1406/offlineinsiderenroll). Using option 2, I re-joined Beta Insider.

---

Let's try installing Microsoft Store again using `wsreset.exe -i`.

This time it goes well and Microsoft Store has been successfully installed (Version 22204.1401.7.0).

> Package Microsoft.StorePurchaseApp was indeed ARM64 based but Micosoft.WindowsStore was X64 as checked through the PowerShell using `Get-AppxPackage –Name *store*`

---

At this time I have a working virtual Windows machine where I can do testing when needed. I event enrolled correctly into the Beta channel of the Windows Insider Programme and I am getting the updates through Windows Update, despite that hardware is not supported.

> After these steps I found that performance in UTM is not as experienced in Parallels Desktop. The Graphics and lack of drivers (with support for WDDM2) can be seen but as a just testing environment, it's a sufficient alternative for Parallels Desktop.

Before I shut down, I do `Disk Clean-Up` from `Administrative Tools`, to release over 18GB of waste data. When the machine shut down, in UTM reclaimed used space (Edit (virtual machine) > NVMe Drive > Reclaim Space) to get my virtual machine to use just over 10GB (and not almost 30GB).

## Installing Ubuntu

After Windows, I decided to install Ubuntu.

I downloaded `jammy-desktop-arm64.iso` image and proceeded with [installation according to provided instruction](https://mac.getutm.app/gallery/ubuntu-20-04).

Through installation, I noticed information to use Ubuntu Server for ARM, but I want to try with the standard desktop edition.

[![Ubuntu Jammy - UTM - GNU GRUB](/images/2022/06/ubunut_jammy_UTM_GNU_GRUB.png)](/images/2022/06/ubunut_jammy_UTM_GNU_GRUB.png)

Once booted from ISO I selected `Try or Install Ubuntu`.

[![Ubuntu Jammy - Live Boot - Desktop](/images/2022/06/ubunut_jammy_liveboot_desktop.png)](/images/2022/06/ubunut_jammy_liveboot_desktop.png)

After landing on the desktop I selected `Install Ubuntu 22.04 LTS` and followed the step-by-step installation.

[![Ubuntu Jammy - Live Boot - Install](/images/2022/06/ubunut_jammy_liveboot_install.png)](/images/2022/06/ubunut_jammy_liveboot_install.png)

Through the installation, I selected `Minimal installation` instead of `Normal installation`, un-ticked `Download updates while installing Ubuntu` and ticked `Install third-party software for graphics and Wi-Fi hardware and additional media formats`.

[![Ubuntu Jammy - UTM - Boot Warnings](/images/2022/06/ubunut_jammy_UTM_boot_warnings.png)](/images/2022/06/ubunut_jammy_UTM_boot_warnings.png)

After un-mounting ISO and rebooting I was welcomed with an EFI error so once again headed to [Troubleshooting](https://mac.getutm.app/gallery/ubuntu-20-04#troubleshooting). Before page load, I noticed that my Ubuntu booted nicely so I leave it.

[![Ubuntu Jammy - UTM - Desktop](/images/2022/06/ubunut_jammy_UTM_desktop.png)](/images/2022/06/ubunut_jammy_UTM_desktop.png)

> This error can be sorted through EFI settings as mentioned in Troubleshooting by going into EFI Shell (hitting Esc at the start of your virtual machine).

In the next step installed SPICE Guest Tools through the terminal.
```bash
sudo apt update
sudo apt install spice-vdagent spice-webdavd
```

Just like that, after reboot, I got a nicely working Ubuntu virtual machine.

Success!

---

At that time I was ready to remove Parallels Desktop (which I did).

I will look forward to any good deals in future, but for now, I will stick with UTM and see if that will be enough for me.


---
## My Apple Watch didn't last as long as expected
- **URL:** https://dariusz.wieckiewicz.org/en/my-apple-watch-didnt-last-as-long-as-expected/
- **Date:** 2022-06-09
- **Tags:** Apple Watch, Watch, Apple, Series 4, Series 6, Series 7, Series 8, Trade-in, Trade-in experience, Battery, Battery Health, Battery Service, Battery Replacement, Service Recommended

### Content

I have been using Apple Watch since series 4 when my wife made me a gift and presented it to me. It was Apple Watch Nike Edition 42mm.

As a Mi Band user at the time, it was an upgrade in functions but a downgrade in battery life. However, the battery of the Series 4 hasn’t been so bad and allows me to easily last the whole day.

<!--more-->

I haven’t slept with Apple Watch (which was the case with Mi Band) so I haven’t got sleep pattern metrics as I used to. But the lack of function fades very quickly. 

I build up a habit, like with my phone, to put a watch on a charger when going to bed. Mostly, I still have some battery life for a couple of hours. If, from time to time, my active day has been longer than expected, I didn’t expect the warning of a low battery level.

After two years Apple put some extra functions (some that were enabled after the release, like ECG) and I feel that it was the right time to upgrade.

I upgraded to Apple Watch Series 6 straight away when was announced and traded fairly my Watch with Apple for a decent discount. It was a good deal.

Apple made a lot of improvements with energy management (the new chip mainly) but introduced an always-on display, which I was a bit worried will put down the life of the battery below what I used to expect. It was fine in the beginning and I managed to get a similar experience as used to have with Series 4. 

Going towards the first year and the announcement of Series 7 I start feeling that the battery is not as it used to be. It still lasts me a day, but when I started putting it into the charger in the evening it was already in the red. 

> Battery health at the time was in the range of 86%.

Series 7, apart from its edge-to-edge display, didn’t convince me to upgrade, hence decided to hold on like before and upgrade when Series 8 will be announced.

One morning, the first week of June 2022 I was greater with a message that my battery will need a service. 

This typically happens when the battery falls below 80% of full capacity and that rule applies to all Apple devices where there is possible to measure its battery health.

> At the time the battery health was shown as 79%, so yes, that’s poor.

I could easily feel that through a very active day (without turning on any workouts), like doing some DIY works in the garden, so this information wasn’t a surprise.

I looked on the [Apple website](https://support.apple.com/watch-battery-service) and was advised that I could get a new battery for slightly over £82 (£82.44 precisely). It’s not bad overall, but is it worth it? 

Theoretically, I could get further a year or so with Series 6 but, as we don’t know what features Apple will present with Series 8 (maybe finally design change as it was expected with Series 7), investing into almost two years old Watch knowing that in 3 months or so, there will be a new one available, may not be the wise move. 

Technology going forward, especially with watches, so I would like to see what Series 8 will bring in, and due to that, I will probably like to upgrade either way. 

As I upgraded my phone last year and I expect that it will last, allow me for 2 or 3 years (iPhone 13 Pro Max), this year could be a good year (for budgeting) for Apple Watch upgrade.

Just in a matter of curiosity, as I traded with Apple my last watch, I checked how much I would get if I will go now with Series 7 (which I don’t want) trading my Series 6 at the same time.

Apple offered me £130 with is not bad. 

When you trade with Apple you just need to send the watch, nothing else. Any accessories, chargers, leads and what’s more important, bands, stay with you. 

You could theoretically get slightly better on eBay but you will need to offer a bit more than just a square piece of a small electronic device.

With Apple trade-in, if you are sure about the condition of your watch, all goes smoothly. 

Receiving a £130 trade-in value is not bad, especially since in 3 months it will be two generations behind.

{{% ads-in-article %}}

Of course, in September I may not receive this figure when trading with Series 8 but can bet it will be still worthy like it was when I traded Series 4 when I purchased Series 6.

In the meantime, I got the option of investing over £82 for a new battery or creating new habits throughout the day that will help me to go further a couple of months and upgrade to Series 8.

This means that I would need to put my watch on a charger for a short period to get a boost of energy.

I don’t like to lose any precious data that Watch is gathering but I am not too much upset about that. Overall during my martial arts training, my watch is in a bag, and after training, I manually add workout data, so I am already losing some. 

I found the right spot, just after work when changing up, to put a watch (and don’t forget about it) on a charger. 15-20 minutes later I end up with roughly over 50% battery that let me finish my most active day with it.

I am putting a lot of hope into Series 8 to see some changes that will convince me to upgrade. If not, then I will think to do a battery service and wait for next year. 

Knowing Apple, roughly every two years jumps in functionality so people are hungry for an upgrade, I will see if this year Apple will not disappoint.


---
## A "Read more" links are not bad for SEO (and a11y) if done right
- **URL:** https://dariusz.wieckiewicz.org/en/read-more-links-seo-a11y/
- **Date:** 2022-05-30
- **Tags:** seo, webdev, a11y, accessibility, readmore, read more, ahref, hugo, user experience

### Content

From time to time I see and look at some SEO articles to see what others are writing about and what's new that I need to look at. 

I have started reading an article about some SEO mistakes to avoid, and the first thing that stopped me from reading further was a point about "Read more" links.

It was stated that the severity of using the "read more" link for SEO is high and that the developer of the site should remove the use of "read more" links in favour of article links (for example title as a link). 

That particular author claimed that when that has been done, the site visibility "went through the roof".

Partly I can agree with that, but removing "read more" links shall not be advised if it is done right. Here is why.

<!--more-->

If you look at my website, on the homepage with a list of articles you will see that I am using the "read more" link (CSS button) under a summary (first paragraphs) of the full article. 

Apart from that link, when you click on it, you are redirected to **continue reading** instead of the beginning of the article. 

You can click on the title of the post or the featured image as well and that will get you to the beginning of the article. 

From the SEO point of view, my first link is an "article link" as advised, but I am still in favour of using the "Read more" button in my design.

**You may ask why?**

It's because my **Read more** link is not just `<a href="/article/">Read more</a>`, it's more than that.

> I am using `<!--more-->` in my markdown to split `{{ .Summary }}` from `{{ .Content }}` rather than using automatic summary generation through Hugo.

My "Read more" link redirects you to a related part of text inside the article, allowing you to read further where you started before you click on it (id `#Read_More`).

> When you click on the title of the article or the featured image you will be pointed to the beginning instead. The read more button allows you to have a "continuous" reading experience.

Also, my link `<a href="/article/">Read more</a>` is more like `<a href="/article/">Read more about this article</a>`, however user see the only words "Read More".

That's the trick for SEO purposes, so the link will contain the full article title, but also for accessibility (a11y) and people who use screen readers.

A screen reader will not just read **Read more** but more likely **Read more about this article** (where **this article** is a title of the full article that links references to).

**Here is how I did that on my website.**

> I am using [Hugo](https://gohugo.io) for generating my website, hence some references will be oriented into this framework.

```html
<a aria-label="{{ T "ReadMore" }} {{ T "about" }} {{ .Title }}" href="{{ .RelPermalink }}#{{ replace (T "ReadMore") " " "_" }}">{{ T "ReadMore" }}<span class="sr-only"> {{ T "about" }} {{ .Title }}</span></a>
```

This will look like that:

```html
<a aria-label="Read More about Removing outdated content from the website... not only for SEO" href="https://dariusz.wieckiewicz.org/en/removing-outdated-content-website-seo/#Read_More">Read More<span class="sr-only"> about Removing outdated content from the website... not only for SEO</span></a>
```

> The `{{ T "..." }}` elements refer to translated content through Hugo `i18n`, as my website generates them in two languages. In a single language, you can just use text.

As you will see, in between the link tag (`<a href=...> ... </a>`), after stripping `<span>` there is the following text: **Read More about Removing outdated content from the website... not only for SEO**. The site however displays only **Read More**.

The `sr-only` class hides additional text that is visible by default by Screen Readers (for accessibility reasons I am using also `aria-label`).

```css
.sr-only {
  position: absolute !important;
  clip: rect(1px, 1px, 1px, 1px);
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  border: 0 !important;
  overflow: hidden;
  white-space: nowrap;
}
```

Google and search engine robots also see the link as full text (through innerText), and not only as word **Read more**.

In that case, if for your design you want to keep **read more**, then there is nothing against it. As long as you will use your article title as a link along and use a smart approach. The "read more" can get work for you, your users (user experience) and your website (SEO).

{{% ads-in-article %}}

**Simplified:**

```html
<a
aria-label="Read more about {{ .Title }}" href="{{ .RelPermalink }}">
Read more<span class="sr-only"> about {{ .Title }}</span>
</a>
```


---
## Removing outdated content from the website... not only for SEO
- **URL:** https://dariusz.wieckiewicz.org/en/removing-outdated-content-website-seo/
- **Date:** 2022-05-30
- **Tags:** seo, webdev, redirect, website, redirect301, redirect410

### Content

I have been reading for some time that one of your solutions for better SEO will be removing pages that are not performing well and just wasting a crawl time.

Redirecting them to the most relevant part (using redirect 301) or where such doesn't exist, pointing back to the homepage and advising search engines that it's gone (using redirect 410).

There is one problem with removing something from a page that you spend a lot of time creating. There is a sort of sentiment in it.

Even when I migrated from WordPress to [Hugo](https://gohugo.io) I moved all pages to a new website. I have done an initial review and did some corrections, but never looked at the test from a merit point of view.

Generally, I am against using the rule of removing content that performs poorly in search engines. Not always the case, that the content is not desired. Sometimes simply is unique and targeting the niche that shall be here for some who will need it.

With such an approach, I am creating some of my posts. To give users something that I struggle to find. You can call it niche but in reality, this is something that some people are searching for and cannot find easily. If I struggle to find a solution and I will come up with my own, I would like to share this with the world.

<!--more-->

> This was the case with [minimal analytics for Google Analytics 4](/en/minimal-google-analytics-4-snippet/). I struggle to find a solution so I have been forced to build my own and it prospers. This later allows others to extend its functionality (the functionality that I am still working on when I have time) and that's the idea.

This particular post prospers but others more specific – niche, not so well. That doesn't mean that I shall remove it.

Following some SEO "professionals" persuading you to remove them is simply stupid. You shall not do that without reading it as an end-user.

I did this for my website.

I open posts from 2008 and start reading them as a normal user will do.

Based on a reading exercise I decided that a particular post is still relevant or not. Using that approach, I found that some content of the articles has been refreshed in new posts. By tracking analytics, I noticed however that old articles performing (gaining users) are much better than new ones.

> On these old articles I always add a note and reference to the new, updated posts, to make sure that users will eventually go there. In reality, this was not always the case and users would rather drop the reading than follow further the link (which I will understand, as I am doing it exactly that same).

I decided to remove them and redirect (301) users from an old link to the new one. 

Using the 301 approach search engines will know that they shall follow the new link and doing that passing the old link ranking power to the new one.

Thanks to that I removed a couple of the articles to direct users to the most relevant post. 

By doing this exercise I may have fewer links crawled by search engines and see that fewer users will visit my website, but the engagement of the users with more relevant content will be greater and that is what I am looking for.

I am looking for users who visit my website and find what they have been looking for, not just for empty numbers in my analytics.

> I have also noticed in the past when I created an updated article on some topic. When I added it to search engines, Google has been so stubborn that it crawl but refused to index it for a long period. Independently of what I have been doing, and how good and rich the content was, Google algorithms didn't like it and refused to index it. In that matter, the exercise of removing old content and redirecting to new using 301 would probably help. Sometimes Google robots may see parts that are duplicated between contents (despite that I rarely just update content, more rather I am writing it from zero), and based on that refuse to index fresh posts, but still, there are some instances across various of my websites where I don't understand why Google is refusing a good piece of text.

At the same time, I come across some of my rich articles that I would want to keep, as I spend a lot of time researching for information and writing them, including making useful screenshots and graphics.

These articles are referring to some old solutions, software or companies that are no longer in use or no longer on the market. Keeping it would be good for archives purposes, but overall is not good for users who don't want to read about something that no longer exists or is valid.

I remove them (archiving locally) altogether and redirect their links to my homepage with redirect 410 giving clear instruction to search engines that content has been removed and the link to it shall be removed from indexes as soon as possible.

> Never use 410 redirect if you are planning to redirect users from this link to the newest article in the future. Use redirect 302 instead (found, moved temporarily). Once you advise 410, all the ranking power of this link will slowly start degrading and regaining it will not be possible, unless there are a lot of active back-links linking to it over the internet.

In this first exercise, I removed just 16 pages from which 7 of them I redirect to the most relevant content and 9 were put with redirect 410.

Once generated my Hugo website before I got over 3200 pages in the Polish version of the website (over 500 from the English part). All of them need to be crawled and they included references to `/tag/` or `/category/` pages.

After that, I go down to just over 3000 pages with 86 paginator pages (down from 94).

After this exercise, I haven't seen a big drop in the numbers of users (if you did this right with the right redirects you shall not experience that). My refresh posts start gaining more traffic from 301 redirects and old posts start disappearing slowly from the indexes of Google and Microsoft Bing.

Finally, my fresh posts that have been excluded from the index for some time finally have been indexed and started gaining traffic.

[![Google Search Console - Crawled - Currently not indexed](/images/2022/05/Crawled-currently_not_indexed-min.png)](/images/2022/05/Crawled-currently_not_indexed-min.png)

If you are a website owner or a blogger, it's worth sitting in your visitor's shoes and looking at your website from their eyes. It will be hard to remove your thoughts, as for you they are non-replaceable, even if no longer relevant. Remember that your website is positioned based on the accuracy of your content and how it is relevant (desired) to your users. 

The times when quantity counted over quality slowly went into the past, hence worth to make sure that your website – blog – did its purpose for your users, and not only for yourself.

> Recently removed some old news articles from years back (going back to 2007) and saw that these exercises, with right redirection to the most relevant content prosper and gain more users, more visitors and what's more important, more customers to the business.

{{% ads-in-article %}}


---
## How to add Job Vacancy to Google from a static Hugo website
- **URL:** https://dariusz.wieckiewicz.org/en/how-to-add-job-vacancy-to-google-from-static-hugo-website/
- **Date:** 2022-05-10
- **Tags:** google, job, vacancy, jobposting, schema, structured data, hugo, shortcodes, markdown, search console, json, partials, archetypes

### Content

Are you advertising for job positions on your website?

Trying to hire somebody is a bit difficult these days in some industries, especially when companies looking carefully at their budgets, everything is getting more expensive so is salary expectations higher than usual.

When the good places to advertise a job vacancy are plenty around if the company decided to put it on the website, it's worth using the power of Google and getting this offer working for the company (it will not find itself without the right approach).

If you looked through Google for job offers you may see that some offers are displayed directly in search results (Jobs section) and they are not paid advertising (at least not most of them). Most of them are pulled from other sites.

The good thing is, that you can add your job vacancy to Google for free as well, you just need to inform the search engine the **right way**.

The right way to do that is with **JobPosting Schema**.

<!--more-->

The way I did it on one of my websites is by using structured data (Schema) formatted in **JSON**, Hugo **shortcodes** or using **partials**.

Thanks to the shortcodes you are setting JSON Schema once, and then reusing it through your markdown with shortcodes parameters.

> There are other formats for implementing Schema into the website which include Microdata. I prefer JSON type schema (Google also), as this is working strictly in the background and don't require adjusting your website design to it. When implemented, nothing changes for the user. The website is looking and acting the same, just Google and other search engines see the changes implemented and are using them accordingly.

The shortcodes solution is good if you advertising one or more job vacancies on a single page on your website (like `/vacancies/`)

If you split each position into multiple pages (like `/vacancies/sales-person/`, `/vacancies/cleaner/`), there is a better option for that with the use of Hugo **partials** which I will cover as well.

But firstly, let's deal with the Schema and the requirements to get our job vacancies into Google.

## JobPosting Schema

Firstly we will follow the [Google requirements for adding structured data to job postings](https://developers.google.com/search/docs/advanced/structured-data/job-posting).

> Before you start, make sure that your website is added to [Google Search Console](https://search.google.com/search-console), so you can get pages indexed quicker, and see if they are discovered and displayed in Google in the first place.

The covid pandemic has changed the way how people are hired and this introduced a new type of work environment – work from home. Before it wasn't something present very often, but right now it become the new norm. Sometimes this "flexibility" brining more productivity to the business if the "technology" and "new work-home environment" are working towards that.

Google adjusted itself creating a part of [**Standard job posting** schema](https://developers.google.com/search/docs/advanced/structured-data/job-posting#standard-job) also [**Work from home job posting**](https://developers.google.com/search/docs/advanced/structured-data/job-posting#work-from-home-example).

Let's start with the first option on which I will concentrate the most.

### Standard job posting

```html
<script type="application/ld+json">
  {
    "@context" : "https://schema.org/",
    "@type" : "JobPosting",
    "title" : "Sales Person",
    "description" : "<p>We are looking for experienced sales person who can do more.</p>",
    "identifier": {
      "@type": "PropertyValue",
      "name": "Company Limited",
      "value": "ABC123"
    },
    "datePosted" : "2022-05-10",
    "validThrough" : "2022-12-23T00:00",
    "employmentType" : "FULL_TIME",
    "hiringOrganization" : {
      "@type" : "Organization",
      "name" : "Company Limited",
      "sameAs" : "https://www.example.com",
      "logo" : "https://www.example.com/images/logo.svg"
    },
    "jobLocation": {
    "@type": "Place",
      "address": {
      "@type": "PostalAddress",
      "streetAddress": "123 Street Road",
      "addressLocality": "Leeds",
      "addressRegion": "West Yorkshire",
      "postalCode": "LS99 0XN",
      "addressCountry": "UK"
      }
    },
    "baseSalary": {
      "@type": "MonetaryAmount",
      "currency": "GBP",
      "value": {
        "@type": "QuantitativeValue",
        "value": 11.50,
        "unitText": "HOUR"
      }
    }
  }
</script>
```

Google described in [Structured data type definitions](https://developers.google.com/search/docs/advanced/structured-data/job-posting#structured-data-type-definitions) what is the meaning of each parameter and what content is acceptable.

### Work from home job posting

```html
<script type="application/ld+json">
  {
    "@context" : "https://schema.org/",
    "@type" : "JobPosting",
    "title" : "Sales Person",
    "description" : "<p>We are looking for experienced sales person who can do more.</p>",
    "identifier": {
      "@type": "PropertyValue",
      "name": "Company Limited",
      "value": "ABC123"
    },
    "datePosted" : "2022-05-10",
      "validThrough" : "2022-12-23T00:00",
      "applicantLocationRequirements": {
        "@type": "Country",
        "name": "UK"
      },
      "jobLocationType": "TELECOMMUTE",
      "employmentType": "FULL_TIME",
      "hiringOrganization" : {
        "@type" : "Organization",
        "name" : "Company Limited",
        "sameAs" : "https://www.example.com",
        "logo" : "https://www.example.com/images/logo.svg"
      },
      "baseSalary": {
        "@type": "MonetaryAmount",
        "currency": "GBP",
        "value": {
          "@type": "QuantitativeValue",
          "value": 11.50,
          "unitText": "HOUR"
        }
      }
    }
</script>
```

{{% ads-in-article %}}

## Building JobPosting Schema shortcodes

Let's create a shortcode called `vacancy` by creating the file `vacancy.html` in the folder `/layouts/shortcodes/`.

This file will contain one of the above JobPosting Schema with some modifications. Before we start with modifications, let's understand how we will use this in our markdown file.

Hugo shortcodes can be called on their own

```
{{%/* vacancy */%}}
```

or with specified parameter/s like

```
{{%/* vacancy "parameter1" "parameter2" "parameter3" */%}}
```

Where `parameter1` we can later call inside using `{{ .Get 0 }}`, `parameter2` using `{{ .Get 1 }}` etc.

If our company is always the same, we can pre-fill this information in our schema as we will not need to fill them each time. Same we can do with address details and the currency. In that case, we will limit the number of parameters in our shortcode.

Here is an example of **The Example Company**

```
<script type="application/ld+json">
  {
    "@context" : "https://schema.org/",
    "@type" : "JobPosting",
    "title" : "{{ .Get 0 }}",
    "description" : "{{ .Get 1 }}",
    "identifier": {
      "@type": "PropertyValue",
      "name": "Example Company Limited",
      "value": {{ .Get 2 | jsonify | safeJS }}
    },
    "datePosted" : "{{ .Get 3 }}",
    "validThrough" : "{{ .Get 4 }}T00:00",
    "employmentType" : "{{ .Get 5 }}",
    "hiringOrganization" : {
      "@type" : "Organization",
      "name" : "Example Company Limited",
      "sameAs" : "https://www.example.com",
      "logo" : "https://www.example.com/images/logo.svg"
    },
    "jobLocation": {
    "@type": "Place",
      "address": {
      "@type": "PostalAddress",
      "streetAddress": "123 Street Road",
      "addressLocality": "Leeds",
      "addressRegion": "West Yorkshire",
      "postalCode": "LS99 0XN",
      "addressCountry": "UK"
      }
    },
    "baseSalary": {
      "@type": "MonetaryAmount",
      "currency": "GBP",
      "value": {
        "@type": "QuantitativeValue",
        "value": {{ .Get 6 }},
        "unitText": {{ .Get 7 | jsonify | safeJS }}
      }
    }
  }
</script>
```

In this example, the shortcode will require 8 parameters to be specified each time to work correctly.

```
{{%/* vacancy "0" "1" "2" "3" "4" "5" "6" "7" */%}}
```

Where
- `"0"` will contain Job Title;
- `"1"` will contain job description in HTML format;
- `"2"` will contain unique Job value, number or string;
- `"3"` will contain date when job become available;
- `"4"` will contain date till when job shall be displayed in Google;
- `"5"` will contain employment type, like **FULL_TIME**;
- `"6"` will contain rate, like **10.50**
- `"7"` will contain unit type of the parameter `"7"`, like per **HOUR**.

Here is an example:

```
{{%/* google-jobs-schema "Sales Person" "<p>An exciting position has become available for a full-time Sales Person. The successful candidate will work 40 hours per week with the possibility of extra hours during busy periods and holidays.</p>" "SP012022" "2022-05-10" "2022-12-23" "FULL_TIME" "10.50" "HOUR" */%}}
```

This method may not be the easiest to use, as every time you will need to fill all parameters, as in another case the shortcode will return an error. However, this gives you the flexibility to put this on whatever page you will need, as well you will be able to put this multiple times on a single page.

If you create a separate page on your website that will be designed for one job position, the other solution with archetypes and partials may be easier to use. This will also allow you nicely to integrate the job vacancy section into your website layout.

## Using Archetypes and Partials for JobPosting Schema

Let's start by creating our `schema.html` partial in the `partials` folder (or in `layouts` or our `theme`).

We will be calling our file in between `<head>` section:

```html
{{ partial "schema.html" . }}
```

Because you may have other schema incorporated into your website, so the file `schema.html` may already exist, we will need to use JobPosting Schema only when is requested (on the page that is only related to job vacancy).

Let's start with the following

```html
{{ if .Params.jobPosting }}
<script type="application/ld+json">
  {
    "@context" : "https://schema.org/",
    "@type" : "JobPosting",
    "title" : "{{ .Params.jobTitle }}",
    "description" : "{{ .Params.jobDescription }}",
    "identifier": {
      "@type": "PropertyValue",
      "name": "Example Company Limited",
      "value": {{ .Params.jobID | jsonify | safeJS }}
    },
    "datePosted" : "{{ .Params.datePosted }}",
    "validThrough" : "{{ .Params.validThrough }}T00:00",
    "employmentType" : [ {{ .Params.employmentType }} ],
    "hiringOrganization" : {
      "@type" : "Organization",
      "name" : "Example Company Limited",
      "sameAs" : "https://www.example.com",
      "logo" : "https://www.example.com/images/logo.svg"
    },
    "jobLocation": {
    "@type": "Place",
      "address": {
      "@type": "PostalAddress",
      "streetAddress": "123 Street Road",
      "addressLocality": "Leeds",
      "addressRegion": "West Yorkshire",
      "postalCode": "LS99 0XN",
      "addressCountry": "UK"
      }
    },
    "baseSalary": {
      "@type": "MonetaryAmount",
      "currency": "GBP",
      "value": {
        "@type": "QuantitativeValue",
        "value": {{ .Params.jobRate }},
        "unitText": {{ .Params.jobRateUnit | jsonify | safeJS }}
      }
    }
  }
</script>
{{ end }}
```

This will be called only for a page, where the markdown file contains the `jobPosting` parameter set for `true`.

Let's start by creating our `vacancies` archetype in the `/archetypes/` folder and fill it with some basic information:

```markdown
---
title: "{{ replace .Name "-" " " | title }}"
url: '/.../'
description: ''

jobPosting: true
jobTitle: "Job Title"
jobDescription: "Put your job description here in HTML format"
jobID: JOBID001
datePosted: 2022-05-10
validThrough: 2022-12-23
employmentType: 
 - FULL_TIME
 - TEMPORARY
jobRate: 10.50
jobRateUnit: HOUR

---

Put the content of your markdown file

```

As you will see, the parameters in the archetypes file match with parameters that are later filled in the schema file.

Using the following command we will be able to use this template to create job vacancies, for example:

```
hugo new vacancies/sales-person.md
```

The parameter `jobPosting` will invoke the relevant part from our `schema.html` file on the page with job advertise.

## Removing JobPosting from Google

As mentioned on the Google page in the [Remove a job posting](https://developers.google.com/search/docs/advanced/structured-data/job-posting#remove-job-postings) section, we can do this using the following:

> _Ensure the `validThrough` property is populated and in the past._

In that case, we just need to change the date to which the job is valid.

> _Remove the page entirely (so that requesting it returns a 404 or 410 status code)._

Removing a page together is fine, but I would not want my website to return a 404. Each removed page shall have 301 redirects. This is important for the good positioning of our website and SEO.

> _Remove JobPosting structured data from the page._

If we don't want to remove the page from our website but we just need to remove it from Google Job posting, the simplest way will be to change the `jobPosting` into `false`.

Once that is done, remember to request re-indexing of your job post URL in Search Console, so Google will be prompted about the change quicker, and don't relay until Google bots will discover the change.

## Testing JobPosting Schema

Every schema, once put in place shall be checked for validity. Sometimes we may miss something, and here the [Rich Result Test](https://search.google.com/test/rich-results) page comes in handy.

---

The above is just one of the examples of how to implement Schema into your website (in that instance JobPosting) and use shortcodes or partials, depending on how our website is designed.


---
## Email in your own domain with Cloudflare (and Gmail)
- **URL:** https://dariusz.wieckiewicz.org/en/cloudflare-email-in-your-own-domain/
- **Date:** 2022-04-30
- **Tags:** Internet, DNS, Domain, MX record, SPF record, Cloudflare, Email, Email Routing, Gmail

### Content

If you have your own domain and you are unable to receive and send emails from this address because it involves additional costs, Cloudflare has prepared the perfect solution for you.

[Email Routing](https://developers.cloudflare.com/email-routing/) (email forwarding) is a free service worth considering.

> To use this option, our domain must be managed on Cloudflare's DNS servers. If we have MX (mail) records for another service, we will need to delete and replace them.

Email Routing involves setting an email address in the domain from which each email received will be forwarded to another mailbox.

If your business email address is on a Gmail domain, why not start using email on your own domain. You will gain more prestige and professionalism, even though nothing will really change for you, because we will continue to receive mail on the mailbox that you have been using so far.

<!--more-->

Before we start playing, it's best to know the [limitations of this service](https://developers.cloudflare.com/email-routing/postmaster/#known-limitations).

## Service limitations

- The service supports [domain with linguistic characters](https://en.wikipedia.org/wiki/Internationalized_Domain_Name), the so-called tails (ąściź in the Polish language), but does not support address prefix with these characters;
- If mail sent to an address in the domain is not delivered to the delegated mailbox (for various reasons), the sender is not notified about it in the form of a non-delivery report;
- In the free version, the email address can only be in the main domain. Using email forwarding in a sub-domain (sub-domain) requires upgrading to a higher, paid package;
- If you are used to using Gmail's email address combinations (i.e. address+label@example.com) or the variance of email addresses (email.address@example.com is the same as emailaddress@example.com), in this service, each address is treated separately and will not work as by default in Google mail (this is to change in the future);
- Some service providers with strict DMARC policies may cause problems with delivery of the email address from the service to the target mailbox;
- The service does not offer the option of composing a new message or replying from an address in the domain. **But are you sure? We'll see later in this post where we'll try setting an email address as an alias in Gmail**.

## Service setting

After logging in to our panel in Cloudflare and adding our domain (I will not go into this aspect here), you will see the **Email** option on the left.

[![Cloudflare - Email Routings - Get Started](Email_Routing_Get_started.png)](Email_Routing_Get_started.png)

By clicking the **Get started** button we will start setting our addresses.

[![Cloudflare - Email Routing - Get Started](cloudflare_email_routing_get_started.png)](cloudflare_email_routing_get_started.png)

First, we must select our domain alias and then specify where the mail should be forwarded.

After clicking the **Create and continue** button, we will proceed to the verification stage of our destination address.

[![Cloudflare - Email Routing Verification](cloudflare_email_routing_verification.png)](cloudflare_email_routing_verification.png)

We will receive an email from Cloudflare to our email address, in which we will have to click the **Verify email address** button.

> We can do this from any device. At this stage, we won't have to log in to Cloudflare, so you can set it up on your computer and confirm it on your tablet or mobile phone.

In the last stage, add DNS records responsible for mail handling (MX and one TXT).

> If our domain was already set up in Cloudflare (or we transferred it from another service provider along with their entries), at this stage we will be informed that we already have MX records and they cause a conflict. You should remove them and add the ones recommended by Cloudflare.

[![Cloudflare - Email DNS records](cloudflare_email_dns_records.png)](cloudflare_email_dns_records.png)

Once this has been done, returning to the **Email** section on the left side of the menu, we will receive confirmation: **Routing status: Enabled**.

Here's what it looks like on my domain.

[![Cloudflare - Email Routing Enabled](Email_Routing_enabled.png)](Email_Routing_enabled.png)

> In the **Routes** tab we can see our set alias address, add additional ones and check which email addresses are approved to receive emails.
>
> With the first alias, we confirmed our email address at this stage. For each subsequent one, we need to add it in the **Destination addresses** section before setting an alias pointing to it.

## Check the configuration

At this stage, we need to send an email address from another email address that we have set in Cloudflare. If the e-mail has arrived, everything works as it should and we can proceed with further configuration if we need it.

## Statistics

Oprócz samego przekierowywania poczty, usługa **Email Routing** oferuje na stronie głównej przejrzyste statystyki oraz dziennik (log) pokazujące co i kiedy zostało wysłane do nas.

{{% gallery %}}
[![Cloudflare Email Routing Summary](cloudflare_email_routing_summary.png)](cloudflare_email_routing_summary.png)
[![Cloudflare Email Activity Log](cloudflare_activity_log.png)](cloudflare_activity_log.png)
{{% /gallery %}}

## Spam and other junk mail

Forwarding emails through Cloudflare does not interfere with the type of messages we receive. On the side of our e-mail address, we should take care of appropriate filtering of junk messages, because Cloudflare does not affect this.

Cloudflare will reject messages that do not pass the default verification and are very likely spam. You can read more about it in the [Spam and abusive traffic](https://developers.cloudflare.com/email-routing/postmaster/#spam-and-abusive-traffic) section.

## Secure DNS settings

If everything is working as it should, the last step is to secure our email-related DNS entries so that we don't accidentally mess them up.

[![Cloudflare - Lock DNS Records](cloudflare_lock_dns_records.png)](cloudflare_lock_dns_records.png)

To do this, go to the **Settings** tab in **Email Routing** and click **Lock DNS records**

{{% ads-in-article %}}

## Sending and replying from a domain (Gmail)

Even though Cloudflare officially does not offer the option of replying or composing a new message from our e-mail address in the domain, it does not mean that it is not possible. Gmail has the option to set our address as an alias. Let's see if it works.

First, we need to set a **one-time password for the application** from the Google Account level.

1. Go to [Google Account](https://myaccount.google.com);
2. Go to the [Security](https://myaccount.google.com/security) section (Security);
3. In the Signing in to Google section, select [App passwords](https://myaccount.google.com/apppasswords). We confirm the transition to this section by entering our account password;
4. From the Select app list, select **Mail** and from the Select device list, select Other - Custom name. Enter any name and press the Generate button;

We return to Google Mail (Gmail).

5. Go to Mail Settings > See all settings;
6. Select the Accounts tab and in the Send mail as item, click Add another email address;
7. In the Email address field, enter the one you set on the Cloudflare side and click Next Step;

> At this stage, let's make sure that our e-mail address was treated as an alias (Checked box **Treat as an alias**)

8. In the SMTP server field, change route1.mx.cloudflare.net to **smtp.gmail.com** and leave port 587;
9. In the username field, enter our Gmail address (login@gmail.com);
10. In the Password field, enter the one generated at the beginning (not our account password).

When we press the Add account button, Google will send an email with a verification code to our Alias. When the message arrives, enter the received code and confirm.

This way, we will be able to write a new message and reply from our alias. **Even though Cloudflare doesn't support it**, Gmail will do it for us.

---

In the same section in the mail settings where we added our alias, we can select the default mail behavior (When replying to a message) by selecting the Reply from the same address to which the message was sent (Reply from the same address to which the message was sent).

Thanks to this, we will not have to switch between Gmail and the alias address every time.

---

And so, in the series **"why it's impossible, if is possible"**, we have set the possibility of receiving, replying and sending mail from our alias set from DNS and Cloudflare.

---

This type of solution is, in a way, an alternative to domain e-mail for people who want to use Gmail but do not want to invest in Google Workspace.

Regards.


---
## A "little" side project – New Hugo based website – YummyRecipes.uk
- **URL:** https://dariusz.wieckiewicz.org/en/yummyrecipes-uk/
- **Date:** 2022-04-23
- **Tags:** Yummy Recipes, Yummy Recipes UK, Hugo, Netlify, SSG

### Content

Designing a website is not a thing that I am doing for a living. My day job is giving me the security needed, and everything else is a development of myself – to see what I can do and extend my skills. If at some point these "little" skills can change into something bigger, that’s great.

> See my [LinkedIn profile](https://linkedin.com/in/wieckiewicz/) if you want to get in touch.

When I made websites, I discover new ways of doing the same things – **improvement**. I am not doing things (writing websites) in the same way, that’s the main thing. A new website is a new approach. I am reusing well-working elements, but still, it's like making everything from scratch, and I like it.

With every new creation, I discovered ways how to improve projects that I have already live, **and with this one there was no exception**.

<!--more-->

## Yummy Recipes UK

Here comes [**Yummy Recipes UK**](https://yummyrecipes.uk)!

Today I announce a website, that **wasn’t planned**. It was more like something where I saw a potential (a **potential** in somebody to make something **creative**, and in myself, to make something **new**).

Through the challenge of creating this website, I want to see what I can achieve using the latest knowledge. The goal in building this website was that it will position itself in a niche of the Internet (will see how this will go in the near **future**).

I saw a **potential** in the other person, who got ideas and just need somebody to say, that they are good at what they doing. With a little help, they can be better and their work can be recognised by a wider audience, not only friends and family.

**The internet needs good things**. Too many websites are losing ground to the **competition** who are just **stealing** from each other or **repeating** the same things over and over.

I have been inspired a bit by [Smitten Kitchen](https://smittenkitchen.com). Don't know what the background behind this site is, but for some time the number of recipes dropped significantly (**burnout?**). I know, that if somebody got **"that thing"**, they will find its audience, at least they shall **try**.

This is why I pushed my friend and together we created [Yummy Recipes](https://yummyrecipes.uk), a nut-free cooking and baking site.

---

I hate creating a website, where I don’t have content to base my work on. It's really hard to create something without **inspiration**.

Some people approached me in the past and asked me to create a website for them. They have been passing only the bare minimum source of information or even none.

Question – **"could you make me a website?"** – is just the beginning, are you ready for hard work?.

Their expectations are high – to create something **marvellous**. But when web developers and I don't have anything to base work on, it will not work at all. Creating a website is a mutual exercise – always.

It’s like asking somebody to write a book for them (a writer asking a person who can type), telling what’s all about, who are main characters, and then living everything to figure out for "key presser". If you, the "key presser", are not a writer, then that's crazy. The words are not coming from the thin air (ok, they may, sometimes), but the story needs to be created. Creating a website it's like making a book cover based on the content. You need to have the content first.

With this project, **we started with content**.

Once content starts building up, I start to see how this project can move forward.

Brainstorm excessive was in name, logo and domain for a website. Once that’s been accomplished, I could start the work and the website start making its shape.

There is a point in this mutual exercise, at which the **initial** content stops and website development begins. 

It’s never just hitting publish button to start our existence on the internet. There are SEO aspects, schema and rich results, sitemap, RSS feeds and what's the most important **user experience** with it. 

You may have the best content possible, but the poor user experience with your website and people will not be coming back. You need to connect all to work nicely and that needs to be considered before the project goes live.

Once you are at 90% of your project, all have their shapes and working nicely. Going live prematurely at that stage got serious consequences that will be hard to fix post-live (**time-consuming**). You need to be ready to "hit" on your audience and promote yourself in search engines. Small issues may not be spotted before going live (_like components alignment in Tesla cars_ 🤦‍♂️), but you will not put the car on the market when your engine is not working correctly.

In some companies, when web developers are dealing with less technical people or pseudo managers, who just want to **“see”** the **“finished”** product, you may be asked to push forward and fix the rest along the road (**seriously?**).

This kind of person may have a long term vision that will not achieve its intended potential because of their premature rush. Always set a target for your project, but don't rush the project if there is no need for that. To gain back, what we could have, if we would release the finished product on time, we will need to put twice as much effort (**time and money)** after. **Some losses cannot be regained!**

I saw and see every day **professional** web developers who are **bragging** about what they created. When you look at it from first sight, you may be **impressed**, but that impression **fades away** very quickly when you start experiencing some basic issues.

There are also others, who do not shout around about what they are working on and how much they earn from it. They are professionals. There is a time for promotion (at product lunch), and there is a time when we shall keep things for us or our team. I respect that.

**It's true that a website is never finished.** 

Don’t expect somebody to build a website for you and then just say goodbye to that person. The project may be initially done, but even with static sites, it requires a touch here and then.

**You will not build a bridge and leave it unmaintained, right?**

If you choosing a CMS solution (like [WordPress which I hate](/en/from-wordpress-lover-to-wordpress-hater/)), the **“touch”** may be required monthly, weekly if not daily, to make sure that all is working as expected.

Requirements from search engines (like Google) change constantly. If your website positioned itself well a year ago, don’t be surprised that today it will be pushed down in search results, when you haven't done anything about it.

This new project is **content-oriented**. If we want a website to thrive, it needs to generate new stuff, **new recipes**. Along with that, it needs to promote itself and let people read it. This is why the social strategy was discussed (planned) closely before the site goes live.

In some projects (websites), social media will not make a difference (got some of them). Different channels will make a bigger impact in reaching a wider audience. Think about it at the beginning.

Each project (website) is **unique** and has its unique users. Some thrive among desktop users, some strictly on mobiles. Some of them see users visiting it every single day (like my own), the others only on selected days (working days).

One of my commercial websites, for example, sees a clear pattern in a high number of users over the week (and working days) with really small over weekends, bank holidays and generally days off. Also, **majority** of its users use **computers** (Desktop) rather than mobiles (like 70% to 30%). Social media is also not the medium that gains traffic, it's an organic search that leads the way. They could easily close all their social profiles and will not lose too much, as long as they concentrate on positioning in Google, Bing and creating/updating the content.

The other website of my good friend, however, who offers [balloons flights in Poland](https://www.paraplan.com.pl), shows a different picture. Social media taking a greater part in gaining visitors and most of them are **mobile users** rather than desktop (like 70% on mobile and the rest are from other devices). Position over search engines can differ from time to time, but what this type of business shall look for are social media and referral traffic. These two aspects are the source of business prosperity on the Internet.

This is a short example of how different all can be.

Looking forward to seeing how this new project and its content find their place on the Internet and what pattern it takes.

{{% ads-in-article %}}

---

The website is starting with 16 delicious recipes created by Chef Celina (with a bit of editorial touch from myself), tested in a professional environment as well as at home. The initial plan (**target**) is to add at least two recipes each week. Interested to see how this will go (and if we will stump upon a **burnout** at some point?).

> Chef Celina is allergic to nuts, this is why she takes greater care in making all their recipes nut-free.

- [Visit Yummy Recipes UK official website](https://yummyrecipes.uk)
- [Like and Follow @yummyrecipes.uk on Facebook](https://www.facebook.com/yummyrecipes.uk)
- [Follow @yummyrecipes.uk on Instagram](https://www.instagram.com/yummyrecipes.uk)
- [Follow @YummyRecipesUK on Twitter](https://twitter.com/YummyRecipesUK)

## Technical aspect

Website is built with [Hugo](https://gohugo.io)[^1] and is hosted on [Netlify](https://netlify.com). The source code is hosted on GitHub.

[^1]: Hugo is the world’s fastest framework for building websites. One of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again.

The layout is built from scratch with HTML, CSS and minimal JavaScript. Content is stored in Markdown files with a bit of `header` required by Hugo.

It contains [Search](https://yummyrecipes.uk/search/), which is done in the user browser and not on the server, using `index.json` generated when the site is deployed.

Contact form is done through Netlify Forms. 

It offers automatic Dark Mode and friendly printing for desired recipes. Any similar recipes are presented in the **"related"** section. If you would like something, you can easily share it on desired social media, or by e-mail using handy share icons in the post footer.

A massive thing was put into Rich Results, Schema for Recipes and OpenGraph.

Visitors are counted through my [minimal Google Analytics 4 snippet](/en/minimal-google-analytics-4-snippet/). Apart from that nothing else is tracked. In its current form, all content is available for free, without ads but with copyright rights incorporated. 

Private users are free to use them (print) for easy, hustle free cooking and baking.

If you want to be always up to date, add its [RSS feed](https://yummyrecipes.uk/index.xml) to your Feed Reader (like Feedly).


---
## Traditional Polish Easter Lemon Babka (Bundt Cake)
- **URL:** https://dariusz.wieckiewicz.org/en/traditional-polish-easter-lemon-babka-bundt-cake/
- **Date:** 2022-04-17
- **Tags:** Babka, Bundt Cake, Polish Bundt Cake, Polish Babka, Easter Cake, Easter Babka, Easter Bundt Cake, Babka cytrynowa, Lemon Babka, Lemon Bundt Cake

### Content

> Difficulty: **Low**\
> Preparation Time: **15 minutes**\
> Baking time: **35 minutes, 170C with fan**

Recipe for 22cm (8.6-inch) bundt cake tin.

<!--more-->

## Ingredients

- 200g of plain flour
- 150g demerara sugar
- 200g unsalted butter
- 4 large eggs
- 1 lemon
- 1 tbsp of baking powder
- 200g icing sugar, for decoration
- 50g unsalted butter, for greasing
- golden breadcrumbs

{{% ads-in-article %}}

## Method

Preheat the oven to 170C with a fan.

Separate egg yolks from egg whites. 

Soften the butter in the microwave (but do not melt fully).

Using a mixer (KitchenAid style mixer preferably), mix sugar, butter and egg yolks until all is well combined.

Grate one lemon on a small grater or zester and squeeze the juice from it. Add all to your mixture and mix thoroughly.

Whisk egg whites to a fluffy foam. Just be the end of a pinch of salt. Add to your other mixture.

Mix flour with baking powder and add gradually to your mixture (mixing on low speed) until all is combined.

Once all is well combined, mix it further at full speed for 3-5 minutes until nice and fluffy (do not overmix).

The mixture shall have the consistency of thick greek yoghurt.

Grease well bundt cake tin and pour breadcrumbs. Rotate the tine so the breadcrumbs will stick to the greased surface of the tin. Remove any excess.

Using a spoon, put your mixture into the tin. Tap the tin onto the worktop a couple of times to settle it.

Put into the oven and bake for 35 minutes until nice and brown.

Before taking it out, check using a wooden stick that is cooked thoroughly. Add couple more minutes in the oven if required.

Once baked, cool down for 15 minutes then take it out from the tin by putting it upside down on a plate.

Leave to cool down, decorate with icing sugar.

[![Babka cytrynowa – Lemon Bundt Cake – Glazed](/images/2022/04/babka-cytrynowa-lemon-bundt-cake-glazed.jpg)](/images/2022/04/babka-cytrynowa-lemon-bundt-cake-glazed.jpg)

Mix the icing sugar with a small amount of water. Put the icing sugar into a bowl, add 1 tbsp of water and mix well. If too dry, add a bit more water. Icing sugar should have the consistency of a cream. Pour the icing around the top of the cake.

Wait until all is set.

To keep the cake moist and prevent it from drying, cover tightly with cling film.

[![Babka cytrynowa – Lemon Bundt Cake – Glazed & Decorated](/images/2022/04/babka-cytrynowa-lemon-bundt-cake-glazed-decorated.jpg)](/images/2022/04/babka-cytrynowa-lemon-bundt-cake-glazed-decorated.jpg)


---
## 10 things to do after installing/upgrading to Windows 11 (+1)
- **URL:** https://dariusz.wieckiewicz.org/en/10-things-todo-after-install-upgrade-windows-11/
- **Date:** 2022-04-16
- **Tags:** Windows 11, Windows 10, Windows Updates, Optional Updates, Microsoft Products, Microsoft, Menu Start, Microsoft Store, Driver Booster, Microsoft Account, Disk cleanup, Storage Sense, restore point

### Content

If you have updated to Windows 11 from Windows 10, the below steps will help you to clean leftovers in your system and make it close enough to the performance known from the 10th edition.

If you planning (or did) to install Windows 11 from an official ISO, make sure that you using always the latest one. At the time of writing this text, the ISO available is the 2nd since the system has been presented to the world (64v1).

<!--more-->

## Move menu Start back to the left side
Unless you like your icons in center, you can move them back to the left edge, like it always been by right-clicking on the bottom menu bar and selecting the **Taskbar settings**.

[![Windows 11 – Right Click on menu bar to get Taskbar settings](win11-Taskbar-settings.png)](win11-Taskbar-settings.png)

> Alternatively **Start** > **Settings** > **Personalization** > **Taskbar**

[![Windows 11 – Taskbar settings from Personalization menu](win11-Taskbar-behaviour.png)](win11-Taskbar-behaviour.png)

When you will scroll down the window, you will find **Taskbar behaviour** section, and there, when expanded, you will have the option **Taskbar alignment** set to **Center** (by default). Just switch it to **Left**.

> I don't understand the whole idea of centring it. Microsoft trying to do something like Dock in macOS, but in that case, we still got clock and icons on the right side, so the whole concept missing the point (as a macOS user). I understand that when you press the **new** menu **Start** it's shown nicely centred, but overall, it is not what is expected/desired by users (_in my opinion_).

## Run Windows Updates
If you installed windows 11 from scratch, there will be no surprise for you, that you will have Windows Updates waiting for you.

If you just updated from Windows 10, they may be installed through the process, but still, there will be some Optional Updates worth checking.

[![Windows Updates in Windows 11](win11-waiting-windows-updates.png)](win11-waiting-windows-updates.png)

Head to **Start** > **Settings** and select **Windows Update** from left side of the window. If something is waiting to be downloaded, hit the blue **Download now** button to start downloading and installing them straight away.

[![Windows 11 – Windows Updates paused](win11-windows-updates-paused.png)](win11-windows-updates-paused.png)

> Depend on the Windows version you have installed, your updates may be paused at start. Click the blue **Resume updates** button to start searching for what is available.

[![Windows 11 – Windows Updates – Checking for updates](win11-checking-for-updates.png)](win11-checking-for-updates.png)

If you don't see any updates waiting for you, you can always recheck that, but click the blue **Check for updates** button.

[![Windows 11 – Windows Updates – Downloading updates](win11-more-windows-updates.png)](win11-more-windows-updates.png)

### Turn on updates for other Microsoft Products

[![Windows 11 – Windows Updates – Advanced options](win11-windows-updates-advanced-options.png)](win11-windows-updates-advanced-options.png)

For this you need to head to **Advanced options** (in the Windows updates section) and tick (turn on) the option **Receive updates for other Microsoft products**.

[![Windows 11 – Receive updates for other Microsoft products](win11-Receive-updates-for-other-Microsoft-products.png)](win11-Receive-updates-for-other-Microsoft-products.png)

Once that is done, head back to the **Windows Update** section and click the blue **Check for updates** button to see if there is anything extra available.

### Install Optional updates
When you are in **Advanced options**, find it in the **Additional options** section and go into it.

[![Windows 11 – Windows Updates – Optional updates](win11-optional-updates.png)](win11-optional-updates.png)

If there are any available, you will be able to select them and install through. Typically they are related to computer hardware when the current system contains drivers in older versions than those provided by Microsoft.

> Sometimes to get the latest version of them, it's better to use the manufacturer's website to update the software and drivers.

## Update Microsoft Store (itself) and Apps

Windows 11 is delivered with a bunch of preinstalled apps that will not get updated straight away when you install or update your system. Same as Microsoft Store, the place from where you install the apps, may require an update.

[![Windows 11 – Search for Microsoft Store in menu Start](win11-microsoft-store-from-the-list.png)](win11-microsoft-store-from-the-list.png)

Head to **Start** > Click **All apps** from the right top corner, and find **Microsoft Store** on the list.

{{% gallery %}}
[![Windows 11 – Microsoft Store – pointing Library](win11-microsoft-store-pointing-library.png)](win11-microsoft-store-pointing-library.png)
[![Windows 11 – Microsoft Store – Library](win11-microsoft-store-library.png)](win11-microsoft-store-library.png)
{{% /gallery %}}

Click on **Library** located on the left bottom side of the window, then hit the blue **Get updates** button.

[![Windows 11 – Microsoft Store – Library – Get updates - Updating](win11-microsoft-store-updating.png)](win11-microsoft-store-updating.png)

Once the search is complete they will start downloading and updating. If not, you can always force it by clicking the **Update all** button.

## Update your drivers

You can do this directly from your computer manufacturer (for example HP and Lenovo have handy tools that will scan your system to see what's missing and what can be updated) or run Driver Updater.

If your computer manufacturer offering you BIOS/UEFI update, do this in the first place.

Alternatively, use [IObit Driver Booster Free](https://www.iobit.com/en/driver-booster.php).

> If you decide to use this software. Install it, run, update what is offered for free and on the first or next system reboot remove it and all apps that may be installed with it. No need to keep the app when all is up-to-date. Leave the rest to get delivered through Windows Updates.

## Restore handy icons in the menu Start

The new menu Start in Windows 11 is **poor**. Missing plenty of handy options by default, not mentioning, that when you upgrade from Windows 10, all of your pinned tiles and apps are no longer there, where they shall be.

Windows 10 have handy icons for some system folders (on the left side), that is not present in Windows 11.

[![Windows 11 – Personalization of menu Start – Folders](win11-personalization-start.png)](win11-personalization-start.png)

To restore them (or turn on what you need) go to menu **Start** > **Personalization** > select **Start** and head to **Folders** section.

[![Windows 11 – Personalization of menu Start – Ticked folders](win11-personalization-start-ticked.png)](win11-personalization-start-ticked.png)

Tick whatever you think is useful for you. I got turned on **Settings**, **File explorer**, **Downloads** and **Personal folder**.

[![Windows 11 – menu Start with Folders](win11-start-with-icons.png)](win11-start-with-icons.png)

Whatever you turned on, it will appear as an icon in the menu Start are the bottom of it.

## Restore handy icons on the desktop

As always (Windows 10 got that same issue), on the desktop there are only a few icons available by default. It's **Recycle Bin** and links to **Microsoft Edge**.

If you want to restore, for example, shortcut to **Computer**, head to **Settings** > **Personalization** > **Themes** > and section **Desktop icon settings**.

[![Windows 11 – Desktop Icon Settings](win11-desktop-icons.png)](win11-desktop-icons.png)

In the new window, you will be able to turn on (tick) whatever you need. I personally always tick **Computer** and **User's Files**.

## Change desktop icons size

Depending on what resolution your computer screen is offering, some of the icons may look too big or too small.

The quickest way to change that will be to **right click** on the desktop. From **new** context menu select **View**, and from there change icons from default **Medium** to **Large** or **Small**.

{{% ads-in-article %}}

## Log in using Microsoft Account

If you haven't done this before during setup, sign in to your Microsoft Account. This will add the ability for you to sync not only files with OneDrive but also some Windows 11 settings. Additionally, there are other benefits related to secure storage of passwords (later used in Microsoft Edge) or additional functions in Windows Defender (your only Antivirus software that you need in your system).

[![Windows 11 – Login using Microsoft Account](win11-login-microsoft-account.png)](win11-login-microsoft-account.png)

To do that, head to **Start** > **Settings** > **Accounts**.

[![Windows 11 – Login using Microsoft Account – Personal](win11-login-microsoft-account-sign-in-personal.png)](win11-login-microsoft-account-sign-in-personal.png)

If you use your personal **Microsoft Account** click **Your info** and follow the link **Sign in with a Microsoft account instead**.

{{% gallery %}}
[![Windows 11 – Login using Microsoft Account – Work or School](win11-login-microsoft-account-sign-in-work2.png)](win11-login-microsoft-account-sign-in-work2.png)
[![Windows 11 – Login using Microsoft Account – Access Work or School](win11-access-work-or-school.png)](win11-access-work-or-school.png)
{{% /gallery %}}

If your account is provided through your work or school (with other benefits), use **Access work or school** and from there click the blue **Connect** button.

## Clean your hard drive from updates leftovers

If you installed Windows 11 from fresh and you did Windows Updates, or if you just updated from Windows 10, you will notice that your free space on your hard drive shrinks a bit. Run Disk Cleanup (as administrator) to free your space. 

[![Windows 11 – Menu Start – search for Disk cleanup](win11-Search-disk-cleanup.png)](win11-Search-disk-cleanup.png)

Click **Start** and in the top field **Type here to search** type **Disk cleanup**.

Do not rush on just click it from the list on the left. Select option **Run as administrator** from the main part of the window.

[![Windows 11 – Disk Cleanup for C](win11-cleanmgr.png)](win11-cleanmgr.png)

You can easily tick everything there. Under the list, you will see how much space you will be free. It may be hundreds of megabytes or even a couple of gigabytes.

Confirm everything by clicking the **Ok** button.

[![Windows 11 – Disk Cleanup - Are you sure you want to permanently delete these files](win11-cleanmgrconfirm.png)](win11-cleanmgrconfirm.png)

There will be some last confirmatory questions, that you know what you are doing, by clicking the **Delete Files** button.

[![Windows 11 – Disk Cleanup – Progress bar](win11-cleanmgr-progress.png)](win11-cleanmgr-progress.png)

Then we just need to wait until when process finish and the window disappear.

> If you updated from Windows 10 and not planning to go back, tick also options that allow you to revert to the previous version of the system (this will free a bit, like 20GiB or more!).

## Turn on Storage Sense

An above step is a good approach to cleaning leftover files from our hard drive. Windows 10 and 11 have a handy function to remove some of them automatically. This option is called **Storage Sense** and is turned off by default.

To enable it, head to **Settings** > **System** > **Storage** and tick (turn on) option **Storage Sense**.

[![Windows 11 – Storage Sense - Temporary Files](win11-storage-sense.png)](win11-storage-sense.png)

> Going deeper into the **Storage Sense** menu we can see what can be removed right now. It's very similar to the step mentioned above, if not "almost" that same.

**Storage** menu have also a handy section like **Cleanup recommendations** that will help us to free some of our space on our drive.

---

And last but not least...

## Remove and re-create recovery points

If all in our system working as it should, there is a good way to have a recovery point, to which we can revert changes. Our system is doing them automatically for us each time when we install something (like apps or drivers for hardware), **if this is turned on**.

This option is not easy to find, since **Control Panel** has been buried (but not yet removed - see **Win+R** and type **control**) at some past update in Windows 10.

[![Windows 11 – Menu Start – Search for Create a restore point](win11-Search-restore.png)](win11-Search-restore.png)

Let's click **Start** and type the word **restore**. 

From the results select **Create a restore point**.

[![Windows 11 – System Properties – System Restore](win11-system-restore-turned-off.png)](win11-system-restore-turned-off.png)

If your system restore is turned off (for system drive - **(C:) by default**), change this straight away by clicking the **Configure** button and changing the option there.

[![Windows 11 - System Protection for Local Disk C](win11-system-restore-configure.png)](win11-system-restore-configure.png)

Depending on how big is our hard drive, let's use a slider to set this to 1 or 2%.

After **Apply** changes and going back to the previous window let's click the **Create** button, put a name of this point (whatever we want) and click **Create**.

[![Windows 11 – Turn on system protection](win11-creating-restore-point.png)](win11-creating-restore-point.png)

If we have our restore points **turned on** already, click on the **Configure** button and let **Delete** all what's been set already. 

Heading back, we will **Create** a new recovery point.

---

At this stage, we are ready to go and set and use our computer and Windows 11 as we intend. Hope from now on, your experience with a new system will be much more pleasant, unless you decided to install it on **unsupported hardware**. If you did so, expect the unexpected (don't blame the system, not fully).

Windows 10 is planned to end its life on 14th October 2025. If your hardware is not supported, stick with it, it's still a really good system. Till that time you are more likely to update your equipment and from there, your experience with Windows 11 will start more pleasantly.


---
## A very Minimal Google Analytics 4 Snippet
- **URL:** https://dariusz.wieckiewicz.org/en/minimal-google-analytics-4-snippet/
- **Date:** 2022-04-02
- **Tags:** Google Analytics, google analytics property, google analytics snippet, Universal Analytics, Google Analytics 4, google analytics 4 snippet, Google Analytics 4 code, google analytics 4 code snippet, minimal analytics, minimal analytics 4, minimal google analytics 4 snippet, minimal google analytics snippet, tracking, netlify, gtag, Global site tag, proxy URL, Redirect 200, page view, site search, scroll, file download, measurement protocol, engagement

### Content

When Google announced that they would force us to move away from Universal Analytics to Google Analytics 4, I wasn’t happy. The official tracking code is notoriously bloated — weighing in at around 171kB in some instances—and is frequently blocked by various ad-blockers. Given the lack of lightweight alternatives, I wasn't looking forward to compromising my site's performance.

I started searching for a solution, but finding nothing that met my needs, I decided to take a "hit-and-miss" approach and build my own. What began as a simple snippet has now evolved into a highly refined, professional-grade tool. With the release of version **1.11 (the "Gold Master")**, the script is more robust than ever, while remaining incredibly lean.

## The Evolution of the Script

While the primary purpose remains tracking essential metrics like page views (`page_view`), session starts (`session_start`), and returning users (`first_visit`), each iteration has added powerful capabilities:

* **Version 1.06 - 1.07:** Introduced site search detection (`view_search_results`) and search query capturing (`search_term`).
* **Version 1.09:** Added scroll tracking (`scroll`), firing an event when a visitor reaches 90% of the page depth.
* **Version 1.10:** Implemented file download tracking for specified extensions and any links containing the `download` attribute.
* **Version 1.11.2 (The "Gold Master Patch"):** This latest milestone marks a thorough stability and hardening cycle. It introduces native **UTM persistence** to resolve attribution gaps, precise **Average Engagement Time** via the browser's Visibility API, and zero-overhead **Outbound Link Tracking**. Following deep peer-review tracking loops, v1.11.2 introduces type-safe DOM guards to fully immunise the script against private browsing crashes, adds case-insensitive search parameters, and relies on strict event capturing to ensure link tracking fires reliably even on sites wrapped in aggressive web frameworks.

By moving to a dedicated GitHub repository, I’ve also implemented a modern **Event Delegation** model and **Storage Safety Checks** to ensure the script runs flawlessly even in strict private browsing modes.

<!--more-->

## Minimal Analytics 4 - the code

> Version 1.11.2 (from 17/06/2026)

```html
<script>
(function(){const c={tid:"G-XXXXXXXXXX",timeout:18e5,ext:["pdf","xls","xlsx","doc","docx","txt","rtf","csv","exe","key","pps","ppt","pptx","7z","pkg","rar","gz","zip","avi","mov","mp4","mpe","mpeg","wmv","mid","midi","mp3","wav","wma"],searchKeys:["q","s","search","query","keyword"]},F=!1,C=Math.floor(Math.random()*1e9)+1,p=Date.now();let g=p,n=!1,a=!1,r=!1,s=!1;const e=function(){try{return localStorage.setItem("t","t"),localStorage.removeItem("t"),localStorage}catch{return{getItem:()=>null,setItem:()=>null,removeItem:()=>null}}}(),t=document,u=document.documentElement,O=document.body,i=document.location,f=screen,l=navigator||{},x=()=>Math.floor(Math.random()*1e9)+1,m=()=>Math.floor(Date.now()/1e3),z=()=>x()+"."+m(),j=encodeURIComponent,k=()=>{let t=e.getItem("cid_v4");return t||(t=z(),e.setItem("cid_v4",t)),t},E=e=>{let t=[];for(let n in e)e.hasOwnProperty(n)&&e[n]!==0[0]&&t.push(j(n)+"="+j(e[n]));return t.join("&")},w=i.search,h=new URLSearchParams(w),d=e=>h.get("utm_"+e),v=[...h.keys()].find(e=>c.searchKeys.includes(e.toLowerCase())),_=v?h.get(v):0[0],y=!!_,A=()=>n?"scroll":a?"file_download":r?"user_engagement":s?"click":y?"view_search_results":"page_view",S=()=>n?"90":0[0],M=()=>!y||n||a||r||s?0[0]:_;function o(o,u,h,v){const z=Date.now()-g;g=Date.now();const L=e.getItem("cid_v4"),N=()=>L?0[0]:n||a||r||s?0[0]:"1",y=m(),D=e.getItem("_ga_last")||0;let b=e.getItem("_ga_sid"),j=e.getItem("_ga_sct")||0,_=!1;(!b||y-D>c.timeout/1e3)&&(_=!0,b=y,j=Number(j)+1,e.setItem("_ga_sid",b),e.setItem("_ga_sct",j),e.setItem("_ga_hits","0")),e.setItem("_ga_last",y);const O=Number(e.getItem("_ga_hits")||0)+1;e.setItem("_ga_hits",O);const x=d("source"),R=d("medium"),P=d("campaign");_&&(x?(e.setItem("_ga_utm_source",x),e.setItem("_ga_utm_medium",R||""),e.setItem("_ga_utm_campaign",P||"")):(e.removeItem("_ga_utm_source"),e.removeItem("_ga_utm_medium"),e.removeItem("_ga_utm_campaign")));const H="https://www.google-analytics.com/g/collect",I=E({v:"2",tid:c.tid,_p:C,sr:f.width+"x"+f.height,ul:l.language?l.language.toLowerCase():0[0],cid:k(),_fv:N(),dl:i.origin+i.pathname+w,dt:t.title||0[0],dr:t.referrer||0[0],seg:O>1||Date.now()-p>1e4?"1":0[0],"epn.percent_scrolled":S(),"ep.search_term":M(),"ep.file_extension":o||0[0],"ep.file_name":u||0[0],"ep.link_text":h||0[0],"ep.link_url":v||0[0],_s:O,sid:b,sct:j,_ss:_?"1":0[0],en:A(),_et:z,cs:e.getItem("_ga_utm_source")||0[0],cm:e.getItem("_ga_utm_medium")||0[0],cn:e.getItem("_ga_utm_campaign")||0[0],"ep.outbound":s?"true":0[0],_dbg:F?1:0[0]}),T=H+"?"+I;if(l.sendBeacon)l.sendBeacon(T);else{let e=new XMLHttpRequest;e.open("POST",T,!0),e.send()}}o();function T(){const e=(u.scrollHeight||O.scrollHeight)-u.clientHeight;return e>0?(u.scrollTop||O.scrollTop)/e*100:0}t.addEventListener("scroll",b,{passive:!0});function b(){const e=T();if(e<90)return;n=!0,o(),t.removeEventListener("scroll",b),n=!1}t.addEventListener("click",function(e){if(!(e.target instanceof Element))return;const t=e.target.closest("a");if(t&&t.getAttribute("href")){const r=t.getAttribute("href"),l=r.split(/[?#]/)[0],e=l.substring(l.lastIndexOf("/")+1),n=e.lastIndexOf("."),d=n!==-1?e.substring(n+1).toLowerCase():"",h=n!==-1?e.substring(0,n):e,u=t.textContent?t.textContent.trim().substring(0,100):"";t.hasAttribute("download")||c.ext.includes(d)?(a=!0,o(d||0[0],h||0[0],u,r.replace(i.origin,"")),a=!1):t.hostname&&t.hostname!==i.hostname&&(s=!0,o(0[0],0[0],u,r),s=!1)}},!0),t.addEventListener("visibilitychange",function(){t.visibilityState==="hidden"&&(r=!0,o(),r=!1)})})()
</script>
```

[See the full, unminified code and official GitHub Repository](https://github.com/idarek/minimal-analytics-4).

> Official Google Analytics 4, Global Site Tag (gtag.js) = 171kB\
> Snippet (current version, minified) around 3kB (without script tag).

The snippet sends **page views**, **site searches**, **scrolls**, **file downloads**, and **outbound clicks** directly to Google Analytics 4 (via the `/g/collect` endpoint). To ensure session integrity and prevent duplicate entries, the script now primarily utilises `localStorage` with a built-in **Storage Safety Check**. This ensures that even if a user has strict privacy settings or is using an Incognito/Private window, the script fails gracefully rather than crashing.

By using this approach, you bypass the need to load the official, heavy library, ensuring your website's loading speed remains uncompromised.

> If you still require the official script (and are willing to risk it being blocked by ad-blockers), you can implement it using the JavaScript delay approach described in my article: [Google Universal Analytics property is shutting down. Here is what you need to know.](/en/google-universal-analytics-shutdown/).

### Site Search Tracking
The "Control Centre" configuration at the top of the script exposes a dedicated `searchKeys` array. This allows you to easily scale your custom search parameters out-of-the-box without altering downstream extraction functions. Just remember to verify that these keys match your active configurations within your Google Analytics Data Stream dashboard.

The snippet automatically identifies on-site searches by monitoring URL parameters such as `q`, `s`, `search`, `query`, and `keyword`. When a search is detected, the script sends a `view_search_results` event instead of a standard `page_view`, capturing the `search_term` as an event parameter.

> Unlike Universal Analytics, which automatically stripped search queries from URLs, Google Analytics 4 requires these to be sent as specific event parameters. This script handles that extraction for you.

The "Control Centre" configuration at the top of the script allows you to easily add custom search parameters. Just remember to ensure these parameters are also configured within your Google Analytics Data Stream settings.

### Engagement and Scroll Tracking
In previous versions, the script fired at the start of a page load and then ceased interaction. Since version **1.11**, the script has become much more "intelligent" regarding user engagement:

1.  **Scrolls:** A passive listener monitors page depth. Once a visitor scrolls to or below 90%, it fires a `scroll` event and then removes the listener to save resources.
2.  **Average Engagement Time:** The script now calculates the exact time spent on a page between events. This provides an accurate `_et` (engagement time) parameter, allowing GA4 to report truthful "Average Engagement Time" metrics.
3.  **The Exit Ping:** Using the Visibility API, the script sends a final "ping" when a user closes the tab or navigates away, ensuring that even "single-page" visits record their final seconds of activity.

### Modernised Click Tracking (Downloads & Outbound)
Version **1.11** introduces a major performance upgrade: **Event Delegation**. Instead of looping through every link on the page when it loads (which was the case in v1.10), the script now places a single "Smart Listener" on the entire document.

* **File Downloads:** If a user clicks a link to a file matching your specified extensions (such as PDF, ZIP, or DOCX) or any link with a `download` attribute, a `file_download` event is triggered. The script now aggressively strips complex URL suffixes—like query strings (`?token=123`) or hash fragments (`#page=2`)—before evaluating the file extension, ensuring hidden downloads are never missed.
* **Outbound Links:** For the first time, the script now tracks when a user clicks a link that takes them away from your domain... By utilizing **Capture Phase** event listeners rather than traditional bubbling, these events intercept clicks on their downward journey, guaranteeing tracking fires accurately even if your templates rely on third-party libraries that invoke `event.stopPropagation()`.

## Minimal Analytics 4 — The Setup

To begin, set up your Google Analytics 4 property and create a Web Stream. Within the **Enhanced Measurement** settings, ensure that **Page views**, **Scrolls**, **Site search**, and **File downloads** are enabled. 

Next, head over to the **[Minimal Analytics 4 GitHub repository](https://github.com/idarek/minimal-analytics-4)** and copy the latest version of the script (`minimal-analytics-4.js`). Paste this into the `<head>` of your website, ideally immediately after the `<title>` tag. 

At the very top of the script, you will find the **Control Centre** (the config object). Replace `G-XXXXXXXXXX` with your actual Measurement ID from your GA4 Web Stream, and you are ready to go.

> **Note:** For the best performance in production, I recommend using the minified version (`.min.js`) found in the repository's [Releases section](https://github.com/idarek/minimal-analytics-4/releases).

### Beating the Ad-Blockers
Despite this snippet weighing a tonne less than the official Google script, it is still liable to be blocked by various ad-blockers because it sends data to `google-analytics.com`. 

However, **there is a solution for that**. If your hosting provider (such as Netlify or Cloudflare) allows you to set "200 Redirects" or rewrites, you can mask the tracking request so it appears to stay within your own domain. I have described this masking solution in detail below.

{{% ads-in-article %}}

## Minimal Analytics 4 — Masking (Hiding) Requests

My site is hosted on [Netlify](https://www.netlify.com), which allows me to use a `_redirects` file to set up a proxy URL using a **200 (OK)** status code. 

> A **200** code indicates that the request has been processed successfully. In this context, it acts as a "silent" rewrite on the server side.

My specific redirect rule is as follows:

```
/g/collect  https://www.google-analytics.com/g/collect  200
```

I then update the tracking script by replacing the default Google URL found inside the `a()` function:

```
https://www.google-analytics.com/g/collect
```

With my own proxied address:

```
https://dariusz.wieckiewicz.org/g/collect
```

### How it Works
Because the tracking request is now made to your own domain rather than a third-party URL, it effectively bypasses the standard filters used by most ad-blockers. On the server side (Netlify’s Edge CDN in my case), the request is transparently mapped back to the official Google endpoint. It carries the entire payload—everything following the `?` in the URL—directly to Google's servers without the visitor's browser ever "speaking" to Google directly.

> For those seeking a more sophisticated setup, there is an option to pass the payload through an advanced redirect. You can find more information in my post: [Masking (hiding) Google Analytics 4 code](/en/google-universal-analytics-shutdown/#masking-hiding-google-analytics-4-code).

> It is important to note that this solution has its limitations. I have outlined the potential pitfalls in another article: [Prevent Google Analytics from being blocked by ad-blockers – The Downside](/en/prevent-google-analytics-being-blocked-adblocker/#the-downside).

--- 

JavaScript is not my primary language, nor is it something I use every day. I originally used the [Minimal Analytics](https://gist.github.com/DavidKuennen/443121e692175d6fc145e1efb0284ec9) snippet by [David Künnen](https://github.com/DavidKuennen) as a guide to building my own version, and it has served me exceptionally well.

I consider myself a perpetual learner in the world of JavaScript, adding new features as I go. Fortunately, the community has been incredibly supportive. Developers with far greater experience have often picked up my work, offering optimisations and expanded functionality that have been vital to the script's evolution.

This code is, and will always be, free and open-source. You are welcome to use it as a "base" for your own development. I genuinely appreciate any feedback or contributions from those with deeper JavaScript expertise who can help refine the project further at its new home on GitHub.

> [James Hill](https://github.com/jahilldev) has also used his expertise to offer a high-quality alternative: [minimal Google Analytics 4 using TypeScript](https://github.com/jahilldev/minimal-analytics/tree/main/packages/ga4#readme). It is certainly worth exploring if you prefer a TypeScript-based approach.

---

{{% ads-in-article %}}

If you are more technically minded and want to understand the "engine" under the bonnet, this technical specification breaks down exactly how the data is structured and sent.

## Minimal Analytics 4 — Technical Specification

The script communicates with Google Analytics 4 using the Measurement Protocol (Version 2). Data is transmitted via a `POST` or `GET` request to the official Google endpoint: `https://www.google-analytics.com/g/collect`.

> **Note:** Because this URL is a primary target for ad-blockers and privacy extensions (often resulting in 40% or more of traffic going unrecorded), I highly recommend the **masking solution** described earlier in this article.

### The Payload Structure
Every event sent by the script contains a serialised `data` payload. Here is a breakdown of the parameters included in version **1.11**:

* **`v=2`**: Measurement Protocol Version (Required for GA4).
* **`tid=G-XXXXXXXXXX`**: Your unique Measurement ID or Stream ID.
* **`_p=123456789`**: A randomly generated Page ID. Unlike previous versions, this is now fresh per page load but stays consistent for all events (scrolls/clicks) occurring on that specific page.
* **`sr=1920x1080`**: Screen Resolution reported in **logical pixels** to ensure accuracy across high-DPI (Retina) displays.
* **`ul=en-gb`**: The visiting user's browser language.
* **`cid=123456789.987654321`**: Client ID. A persistent, randomly generated ID stored in `localStorage` used to distinguish new visitors from returning ones.
* **`_fv=1`**: First Visit flag. Sent only when the script cannot find an existing Client ID in the browser's storage. In v1.11.2, this flag is structurally isolated; it is fully protected against local tracking environments, guaranteeing it never leaks onto subsequent interactions (like scrolls, file hits, or exit pings) during anonymous private browsing sessions.
* **`dl`, `dt`, `dr`**: Document Location (URL), Title, and Referrer (the source of the traffic).
* **`sid=1648993317`**: Session ID. Generated from a Unix timestamp and stored in `localStorage` to persist across multiple tabs and windows.
* **`sct=1`**: Session Count. Tracks how many times a user has visited your site across different sessions.
* **`seg=1`**: Engaged Session flag. In v1.11, this is set to "1" only if the user stays for more than 10 seconds or interacts with the page, providing a truthful **Bounce Rate**.
* **`_et=1500`**: Engagement Time in milliseconds. This tells GA4 exactly how long the user was active on the page before the current event was triggered.
* **`_s=1`**: Hit Counter. Increments with every request (page view, scroll, click) within a single session.
* **`en=...`**: The Event Name. This could be `page_view`, `scroll`, `view_search_results`, `file_download`, or the new `click` (for outbound links).
* **`ep.search_term`**: The actual search keyword query extracted from the URL. This logic is case-insensitive (safely capturing `?Search=` or `?q=`) and strictly gated to ensure it accompanies `view_search_results` hits alone, ensuring search terms never bleed into subsequent page interaction states.
* **`cs`, `cm`, `cn`**: Campaign Source, Medium, and Name. These parameters persist UTM data throughout the session, ensuring your marketing attribution remains accurate.
* **`ep.outbound=true`**: A custom parameter sent during the `click` event to identify external link clicks.
* **`_ss=1`**: Session Start flag. Sent only with the first hit of a new session.
* **`_dbg=1`**: Debug flag. When enabled in the script, this allows you to see hits in real-time within the GA4 "DebugView" console.

### Data Transmission
One of the most significant improvements in version **1.11** is how the script sends data. We now use a "best of both worlds" approach:

1.  **`nav.sendBeacon`**: If the browser supports it, we use this method. It is the most reliable way to send data because it allows the browser to finish the transmission even if the user closes the tab immediately after a click.
2.  **`XMLHttpRequest`**: We use this as a fallback for older browsers to ensure no data is lost.

### Storage & Privacy
In v1.11, we migrated all session data from `sessionStorage` to `localStorage`. This allows the script to "see" a session across different browser tabs — something the official GA4 script does, which was missing in earlier versions. Furthermore, we implemented a **Storage Safety Check** (a `try/catch` wrapper) to ensure the script doesn't crash if a user has disabled third-party storage or is using a strict "Incognito" mode.

I hope this version provides a reliable, robust solution for your tracking needs for years to come, just as David Künnen’s original script did for Universal Analytics.

{{% ads-in-article %}}

## Privacy and Other Considerations

This snippet, unlike the original Google script, does not constantly "phone home" or track every mouse movement. However, version **1.11** is significantly more capable than its predecessors. While earlier versions ceased all interaction immediately after page load, the new architecture maintains a passive presence to ensure your data is as accurate as possible.

### Passive Interaction
In previous versions (v1.10 and below), it was impossible to see how long a user spent on a page. I am pleased to say that with version **1.11**, this has changed. The script now remains active in a "passive" state to handle three specific tasks:

1.  **Scroll Detection:** It waits for the 90% scroll threshold, reports it, and then disconnects that specific listener.
2. **Smart Link Tracking:** Using a single, hardened capturing listener via event delegation, it handles clicks on file downloads or external outbound links seamlessly.
3.  **Engagement Timing:** It calculates the time spent on the page and sends an "Exit Ping" via the Visibility API when a user closes the tab or navigates away.

### Accurate Engagement (No more "Assumed" Engagement)
In earlier versions, the script automatically assumed a user was "engaged" the moment the page loaded. In version **1.11**, I have implemented a much more honest approach. The script now follows GA4's official logic: a session is only marked as "engaged" (`seg=1`) if the user stays on the page for more than 10 seconds or performs an interaction (like a scroll or a click). 

This means your **Bounce Rate** in Google Analytics will finally be accurate, showing you the percentage of users who truly interacted with your content.

### The Disclaimer
As David Künnen mentioned in his [Minimal Analytics for UA](https://minimalanalytics.com):
> _"You should not use this if you want to use advanced features like tracking AdWords."_

The same remains true here. This script is a specialised tool for those who value site performance and privacy. If you require advanced Google signals, cross-device remarketing, or deep Google Ads integration, the official (bloated) script is still your only option.

### Bot Filtering
Because spam bots rarely execute JavaScript, they will not trigger this snippet. This ensures that the majority of your tracking data comes from real, human users. By implementing accurate engagement timing in this latest version, we have added an extra layer of protection against "ghost" traffic that might skew your data.

## To Delay or Not to Delay?

In previous versions of this article, I suggested that you could implement a "JavaScript Delay" (waiting for a cursor movement, keypress, or scroll before firing the script), as described in my post: [Implementing JavaScript Delay for Cookie Consent Banner](/en/implementing-js-delay-for-cookie-consent-banner/).

However, with the release of version **1.11**, my recommendation has changed. **I now recommend against using a separate JavaScript delay for this snippet.**

### Why v1.11 Should Run Immediately
Because version 1.11 now includes its own sophisticated engagement tracking, a manual delay will actually compromise your data accuracy:

1.  **Broken Engagement Timers:** The script now calculates the exact `_et` (Engagement Time) from the moment the page starts loading. If you delay the script load, that "start" point is lost, and your time-on-page metrics will be significantly under-reported.
2.  **Inaccurate Engagement Flags:** We have built logic into v1.11 to automatically determine if a session is "engaged" (`seg=1`) based on time and interaction. A separate JS delay interferes with this "honest" measurement.
3.  **The Exit Ping:** For the "Exit Ping" to work via the Visibility API, the script needs to be loaded and "listening" from the beginning.

By allowing the script to run immediately, you get the best of both worlds: a tiny, high-performance script that doesn't bloat your site, but one that is "smart" enough to manage its own engagement logic without needing a manual delay.

### The Purpose of Minimal Analytics
Our goal remains the same: to measure how many people visit our website and which content is most popular, without the overhead of official tracking libraries. This is the ideal approach for web enthusiasts, bloggers, and small business owners who value performance.

### A Note on Privacy (GDPR)
Finally, remember that despite our tracking being simplified and lightweight, it is still tracking. Depending on your jurisdiction and your visitors' location, you must consider a relevant privacy policy and consent banner. This is especially pertinent given the ongoing discussions within the EU regarding the legality of Google Analytics and GDPR compliance. While this script is "minimal", you should always ensure your implementation aligns with your local legal requirements.

{{% ads-in-article %}}

## Community, Comments, and Improvements

Do you have thoughts on this minimal analytics snippet or a suggestion for a future update? While this project began its life on Gist, it has now moved to a dedicated home on GitHub.

### How to Get Involved
The goal of keeping this script public is to foster collaborative development. If you have JavaScript expertise and want to help refine the code further, I would love to hear from you:

* **GitHub Discussions:** For general questions, sharing your own implementation, or just saying hello, I have enabled the [Discussions section](https://github.com/idarek/minimal-analytics-4/discussions) on the repository. This is the best place for community chat.
* **GitHub Issues:** If you have found a bug or have a specific feature request, please [open an Issue](https://github.com/idarek/minimal-analytics-4/issues). This helps me track technical tasks more efficiently.

### A Note on Development
I am a perpetual learner when it comes to JavaScript. While version **1.11** is a significant leap forward, I am well aware that there is always room for optimisation. If you request a feature, please understand that it might not appear overnight — I often need to learn the underlying logic before I can implement it safely.

If you know how to achieve a specific result, please don't just ask — **share your knowledge.** Let’s work together to make this the best lightweight tracking tool available. 

In the world of open-source, there is no room for those who only complain without offering feedback. We are all learning, and the best results come when we work with one another rather than against each other.

### Final Thanks
A huge thank you to everyone who has offered a kind word, starred the project, or shared my work with others. Your support is what keeps this project moving forward.

**Check out the latest code here:** 👉 [idarek/minimal-analytics-4](https://github.com/idarek/minimal-analytics-4)

---

## Credits & Further Reading

This project would not have been possible without the deep-dive research and technical documentation provided by the following experts. If you want to explore the inner workings of the GA4 Measurement Protocol yourself, I highly recommend these resources:

### Technical References
* **David Vallejo (Thyngster):** A vital source for understanding the protocol. Check out his [Google Analytics 4 Measurement Protocol Cheatsheet](https://www.thyngster.com/ga4-measurement-protocol-cheatsheet/) and his initial analysis of [version 2 of the protocol](https://www.thyngster.com/app-web-google-analytics-measurement-protocol-version-2).
* **Optimize Smart:** For a clear, high-level guide on [Understanding the GA4 Measurement Protocol](https://www.optimizesmart.com/what-is-measurement-protocol-in-google-analytics-4-ga4/).
* **Analytics Debugger:** Their [GA4MP technical documentation](https://ga4mp.dev/) is an incredible resource for understanding [Campaigns](https://ga4mp.dev/#/campaigns), [Tracking Parameters](https://ga4mp.dev/#/tracking), and [Protocol Options](https://ga4mp.dev/#/options).

### Open Source Inspiration
* **David Künnen:** Whose original [Minimal Analytics for UA](https://minimalanalytics.com) inspired the entire "lite tracking" movement.
* **GA4MP Library:** For those looking for a more robust JS library, the [ga4mp GitHub repository](https://github.com/analytics-debugger/ga4mp) is a fantastic piece of engineering.

---

**Final Thought:** Implementing Minimal Analytics 4 is about taking back control of your site’s performance without flying blind. Whether you are a blogger, a small business owner, or a performance enthusiast, I hope this script helps you focus on what really matters: your content and your users.

**Happy tracking!**


---
## Blocking Ads in Safari on iOS, iPadOS and macOS
- **URL:** https://dariusz.wieckiewicz.org/en/blocking-ads-safari-ios-ipados-macos/
- **Date:** 2022-03-27
- **Tags:** Mac, AdSense, Google AdSense, AppStore, Content Blockers, Firefox Focus, Safari, DuckDuckGo, DuckDuckGo Privacy Essentials, iOS, iPad, iPhone, Safari, Adblock Plus

### Content

We are living in a world, where everybody is trying to commercialise almost everything. If selling products and services does not bring desired income and users have had already too many subscriptions to pay for another one, there's comes Ads.

Nobody likes Ads. They can ruin the reading experience on the website, cause our computer to choke due to excessive use of resources, or put your device or ourselves at risk due to privacy matters.

I used to use, back in 2020 ads, that display dynamically on my site, through Google AdSense. This does not even bring the return of the costs, that I put into it. What's more annoying, using Google Ads has a huge negative impact on my website performance. Ironically, my site has been penalised by Google in their ranking, due to using their solution!

Once I migrated to Hugo and start using Netlify in their free plan, I reduced costs significantly, and because of that, I decided to banish Ads altogether. My site doesn't have millions of visitors per month, hence it does not cost me a lot to maintain it. At the time, when I will be somehow noticed, I will gain a decent number of visitors, can imagine that I will be facing other opportunities to gain profit, and hopefully this will not be from Ads.

When I appreciate Ads system like [EthicalAds, Privacy-preserving Ad Network](https://www.ethicalads.io) or [BuySellAds](https://www.buysellads.com), there are still Ad systems that cause me a headache. If they annoy me, they annoy others as well.

On my devices, I am using Safari as my default browser. You may say what you like about it, but definitely, it's not the new Internet Explorer.

I am using a dual approach. To preserve my privacy and to remove annoyances from the websites that I visit every day. Here is how I am doing that on my devices.

<!--more-->

## iOS (iPhone) and iPadOS (iPad)

On these devices I am using **Firefox Focus** *(free)* and **Adblock Plus** *(free)*.

> Firefox Focus is a standalone internet browser, but I am using only its integration with the safari which allows me to block trackers and maintain my privacy.

### Firefox Focus

[![Firefox Focus AppStore iOS](firefox_focus_appstore_ios.png)](firefox_focus_appstore_ios.png)

1. [Download **Firefox Focus** from **AppStore**](https://apps.apple.com/app/firefox-focus-privacy-browser/id1055677337)

2. When the app is downloaded, open it and follow through initial setup/tutorial.

[![Firefox Focus iOS - Ready](firefox_focus_ios_ready.png)](firefox_focus_ios_ready.png)

As we will not use Firefox Focus as a browser, we can close it and go back to Home Screen on our device.

3. Head to device **Settings** and section **Safari**

4. In **General** section go to **Extensions** and in section **Allow there content blockers** tick (turn on) **Firefox Focus**. And that's all.

### AdBlock Plus

[![Adblock Plus Appstore iOS](adblock_plus_appstore_ios.png)](adblock_plus_appstore_ios.png)

1. [Download **Adblock Plus for Safari (ABP)** from **AppStore**](https://apps.apple.com/app/adblock-plus-for-safari-abp/id1028871868)

2. When the app is downloaded, open it and follow through initial setup/tutorial.

{{% gallery %}}
[![Adblock Plus iOS - 1st Step](adblock_plus_ios_1st_steps.png)](adblock_plus_ios_1st_steps.png)
[![Adblock Plus iOS - Ready](adblock_plus_ios_ready.png)](adblock_plus_ios_ready.png)
{{% /gallery %}}

Apart from part **Block ads** that need to be turned on (ticked), we don't need to do anything else.

3. Head to device **Settings** and section **Safari**

4. In **General** section go to **Extensions** and in section **Allow there content blockers** tick (turn on) **Adblock Plus**. And that's all.

[![Safari iOS Extensions Firefox Focus Adblock Plus](safari_ios_extensions_firefox_focus_adblock_plus.png)](safari_ios_extensions_firefox_focus_adblock_plus.png)

This is how it all will look.

Now you can browse as you typically do in Safari. In the background, Firefox Focus and AdBlock Plus will do what it is intended to.

{{% ads-in-article %}}

## macOS (Mac computers)

As **Firefox Focus** is not available for Mac computers (shame!), as an alternative I am using **DuckDuckGo Privacy Essentials** extension *(free)* along with **Adblock Plus**.

> Ironically, DuckDuckGo is available on mobile devices as a standalone web browser with its privacy functions, same as Firefox Focus, however, it's not possible to use its functionality as an extension to Safari (shame!).

### DuckDuckGo Privacy Essentials

[![DuckDuckGo AppStore macOS](duckduckgo_appstore_macos.png)](duckduckgo_appstore_macos.png)

1. [Download **DuckDuckGo Privacy Essentials** from **AppStore**](https://apps.apple.com/us/app/duckduckgo-privacy-essentials/id1482920575?mt=12)

2. When the app is downloaded, open it and follow through initial setup/tutorial.

{{% gallery %}}
[![DuckDuckGo macOS 1st Step](duckduckgo_macos_1st_step.png)](duckduckgo_macos_1st_step.png)
[![DuckDuckGo macOS 2nd Step](duckduckgo_macos_2nd_step.png)](duckduckgo_macos_2nd_step.png)
{{% /gallery %}}

Through the tutorial, you will be asked to **Launch Safari Preferences** and on the **Extensions** tab to enable (tick) **Privacy Dashboard** and **Privacy Protection**.

After that's done, your setup is ready.

> What's important, using the DuckDuckGo extension on Mac doesn't change our search engine in the browser, or how the address bar is behaving when using it to search the web. Read here, [how to change the default search engine in the Internet browser](/en/how-to-change-default-search-engine-internet-browser/).

### Adblock Plus for Safari ABP

[![Adblock Plus AppStore macOS](adblock_plus_appstore_macos.png)](adblock_plus_appstore_macos.png)

1. [Download **Adblock Plus** from **AppStore**](https://apps.apple.com/app/adblock-plus-for-safari-abp/id1432731683?mt=12)

2. When the app is downloaded, open it and follow through initial setup/tutorial.

[![Safari macOS Extensions Adblock Plus DuckDuckGo](safari_macos_extensions_adblock_plus_duckduckgo.png)](safari_macos_extensions_adblock_plus_duckduckgo.png)

During **one step** setup, you will be asked to **Launch Safari Preferences** and on the **Extensions** tab to enable (tick) **ABP** and **ABP Control Panel**.

[![Adblock Plus - Ready](adblock_plus_ready_macos.png)](adblock_plus_ready_macos.png)

After that's done, your setup is ready.

**Happy browsing!**

> In a similar way, we can add [Lockdown - Firewall on iPhone (and macOS)](/en/firewall-iphone-ipad-mac-lockdown-privacy/).


---
## Improving website performance by loading fonts the smart way
- **URL:** https://dariusz.wieckiewicz.org/en/improving-website-performance-loading-fonts/
- **Date:** 2022-03-23
- **Tags:** WebDev, WebPerf, website performance, Google Fonts, CLS, Cumulative Layout Shift, Core Web Vitals, Google Search, performance, PageSpeed Insight, WOFF, WOFF2, The Web Open Font Format, optimizeLegibility

### Content

My site, until recently, was using a [system font stack](https://systemfontstack.com), mostly because I would like to have the lightest website possible.

My featured images, heavily optimized, still account for large LCP (Largest Contentful Paint) and adding custom fonts, in the most common way, can increase the overall weight of the website.

I am happy with my site, but on others, I need to use specified fonts to get the right visual experience across all user devices. In that case, I need to load additional fonts to accomplish that.

The fonts not only add weight to the website but also can hurt CLS (Cumulative Layout Shift) if loaded incorrectly. As CLS is part of essential Core Web Vitals, its poor score can drop a website significantly in Google Search results.

Ironically, Google, on their [Google Fonts](https://fonts.google.com) website provides information (code) on how to implement the desired font in our website. The problem is, that their solution will have a huge negative impact on your website.

Not only they are loaded from an external source, but the speed of loading of your website and external fonts can also vary and cause, ironically, CLS, that Google will penalise you on.

A widely recommended method is to self-host your fonts (even these from Google). This, in most cases, may improve an impact on CLS, but not always. There are plenty of factors in how these fonts are delivered. If our hosting is poor and we are not using CDN (Content Delivery Network) then we can see worse results than loading fonts directly as Google advised.

**Self-hosting fonts are the right approach**, but it requires a couple of tweaks before it will work well for us in matters of web performance.

Let's start with, how to load them correctly.

<!--more-->

## Self-Hosted fonts

Your website will require a font in WOFF2 format (The Web Open Font Format, a compressed file format created specifically for web fonts). With the current state of web browsers, you can forget about WOFF support (and any other formats). WOFF2 is the format that is used by all modern browsers currently on the market.

If you fancy Google Fonts then you will be happy to head to [google webfonts helper](https://gwfh.mranftl.com/fonts) to find your desired font **and download** the required files, along with the code, showing you how to implement them on your website.

This website is a real golden nugget. We will use files provided by them, but will **not use their code**, at least not in full. Additionally, we will do some tweaks to work better for us.

Let's start with the most popular serif font **‌Merriweather**.

Because I write in Polish as well, by default, I am **selecting charsets** *latin-ext* (only) and **styles** as it suits us.

> Default styles that I would recomment, which are most common used on websites are **regular (400)**, **italic (400i)**, **700 (bod)** and, less commonly used, **700italic (bold italic)**.

In the third point, we will get our **CSS code**, for Modern Browsers, to copy. Before we copy it, we will *customize the folder prefix* as it suits us (in my example it's just `/fonts/`.

I will show here only an example for **regular (400)**.

```
/* merriweather-regular - latin-ext */
@font-face {
  font-display: swap; 
  font-family: 'Merriweather';
  font-style: normal;
  font-weight: 400;
  src: url('/fonts/merriweather-v30-latin-ext-regular.woff2') format('woff2');
}
```

The code needs to be pasted into our CSS-style file.

As the last point, we will download our files.

Once downloaded and unpacked we will have something like that:

```
/fonts/merriweather-v30-latin-ext-700.woff2
/fonts/merriweather-v30-latin-ext-700italic.woff2
/fonts/merriweather-v30-latin-ext-italic.woff2
/fonts/merriweather-v30-latin-ext-regular.woff2
```

{{% ads-in-article %}}

## The Tweaks

Before we will go a little further, let's see what **the important** difference is between this code and one provided by Google Fonts for the same font.
```
<style>
@import url('https://fonts.googleapis.com/css2?family=Merriweather:ital,wght@0,400;0,700;1,400;1,700&family=Roboto:ital,wght@0,400;0,700;1,400&display=swap');
</style>
```
---

When you put Google Fonts code into your `style.css` it will import the following (showing only a part): 
```
/* latin */
@font-face {
  font-family: 'Merriweather';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/merriweather/v30/merriweather-v30-latin-ext-regular.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
```

> Google is importing all other charsets that you may not necessarily need!

If you will use this code before your font will load and swap the style on your website (`font-display: swap;`), the text will be presented with the locally available font (can be split second).

Depending on your internet speed, the time between displaying the local alternative font (Merriweather is not available by default in any operating system) and Merriweather will likely cause a move on your website. This move will account for CLS and hurt your website.

### Text rendering

To ensure your text looks crisp and readable, you can use the **font-variant-ligatures** property. While some older guides suggest the non-standard **text-rendering: optimizeLegibility**, it can often cause performance issues on long pages.

Using standard CSS properties is a safer and more performant way to achieve the same goal:

```css
body {
  /* Enables standard ligatures (like 'fi', 'fl') */
  font-variant-ligatures: common-ligatures;
  /* Ensures proper spacing between characters */
  font-kerning: normal;
  /* Standard way to help with font smoothing on macOS/iOS */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
```

### Eliminating CLS with Font Metric Overrides

One of the biggest issues with `font-display: swap` is that the custom font often has different dimensions than the fallback system font, causing a layout shift. Modern CSS allows us to use `size-adjust` to match the fallback font's size to our custom font.

Tools like the [Capsize framework](https://seek-oss.github.io/capsize/) or [Fontaine](https://github.com/unjs/fontaine) can help you calculate these exact values.

### Variable Fonts: The Future

If your chosen font is available as a **Variable Font**, you should use it. Instead of loading multiple files for different weights, you load one file that can dynamically render any weight from 100 to 900. This significantly reduces HTTP requests and total payload.

---

In such a way, our code in our CSS file will look as follows (using Merriweather as an example):

```
/* merriweather-regular - latin-ext */
@font-face {
  font-display: swap; 
  font-family: 'Merriweather';
  font-style: normal;
  font-weight: 400;
  src: url('/fonts/merriweather-v30-latin-ext_latin-regular.woff2') format('woff2');
}
```

### Preloading fonts

Adding fonts to our website through CSS is not enough for web page speed purposes. Some fonts need to be downloaded before the content is displayed. To do that we need to preload the font at the start.

From the four styles we selected (400, 400i, 700 and 700i), we will preload only this that are most likely been used, which are **regular**, **italic** and **bold** (400, 400i, 700).

We need to paste the below code into our `<head>` just after the CSS file is loaded.

```
<link rel="preload" href="{{ absURL "" }}fonts/merriweather-v30-latin-ext-regular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="{{ absURL "" }}fonts/merriweather-v30-latin-ext-italic.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="{{ absURL "" }}fonts/merriweather-v30-latin-ext-700.woff2" as="font" type="font/woff2" crossorigin>
```

### Cache the font

Depending on the environment where our website is served, it's good to specify the right approach for caching fonts. This is mostly done through [HTTP headers](https://developer.mozilla.org/en-US/docs/Glossary/HTTP_header).

My website is hosted on [Netlify](https://www.netlify.com), hence I will do that by specifying [custom headers](https://docs.netlify.com/routing/headers/) in the `_headers` file located in my static folder, which will be placed in the root folder when my site will be built using [Hugo](https://gohugo.io).

Specific to fonts, I am adding the following header that will help us deal with reported errors by [PageSpeed Insight](https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect) about serving static files through a sufficient caching policy.

```
/*.woff2
  Cache-Control: public, max-age=31536000, immutable
```

---

If we follow everything mentioned above, we shall see a huge improvement when running our website through [PageSpeed Insight](https://pagespeed.web.dev), especially with CSL.

That's however depend, how fast is our hosting and if we using CDN or not.

[![PageSpeed Metrics example](/images/2022/03/pagespeed_metrics_example-min.png)](/images/2022/03/pagespeed_metrics_example-min.png)

Just recently, when I decided to add to my website, where I used to use [system font stack](https://systemfontstack.com) a Roboto font as a first, with all the above **teaks** my PageSpeed still reported a score of 100.


---
## Google Universal Analytics property is shutting down. Here is what you need to know.
- **URL:** https://dariusz.wieckiewicz.org/en/google-universal-analytics-shutdown/
- **Date:** 2022-03-17
- **Tags:** google analytics, Universal Analytics, Google Analytics 4, tracking, netlify, minimal analytics, google analytics property, gtag, Global site tag

### Content

On the 16th of March 2022 [Google announced its plans for a shutdown of Universal Analytics property](https://support.google.com/analytics/answer/11583528) and replace it fully with Goole Analytics 4 (v4) that been in the market since late 2020.

Google like to kill off their services. Luckily, this is not about shutting down Google Analytics but only the method, how analytics data are collected from websites. If you have been using Google Analytics for some time, then it's more likely that you have been using Universal Analytics. You will know that by looking at your tracking code that will carry `UA-` on front of the numbers.

Analytics in its 4th version (UA is 3rd) has been developed for some time, but it wasn't adopted as quick as Google could expect (or want), this is why they forcing a change by shutting down one in favour of another.

<!--more-->

The first problem is, that UA is not compatible with GAv4. You cannot (not yet, and I would not expect that this will be possible) migrate your current traffic, visits etc. into GAv4. GAv4 is using a different method of gathering traffic and this is why if you want to use it, you will need to start collecting data from scratch (yes, I know, total nonsense!).

If you, as a web owner (but not only), need to migrate to GAv4, then the best time would be the last day of the year 2022 or the first day of the next one (2023).

Luckily Universal Analytics is shutting down on 1st July 2023 so you can carry on using your current solution and gather data for 2022 uninterrupted, and from the new year switch to Google Analytics 4. Thanks to that, if you need to analyse past year data, you will not need to jiggle between two analytics at the time.

The second problem is your website performance. People-oriented in improving web performance (like me) know, that Google Analytics tracking script can be easily blocked by AdBlockers (like I covered in my post [Prevent Google Analytics from being blocked by AdBlocker](/en/prevent-google-analytics-being-blocked-adblocker/)), but also the script itself weight a bit and loading it (remember, Google own script) degrading website performance in PageSpeed Insight (also Google own solution). Mainly affected are crucial Core Web Vitals that are necessary for a good positioning over Google Search results!

Because of that, people have been using Minimal Google Analytics Snippet as a solution. According to [minimalanalycs.com](https://minimalanalytics.com) website, the Google Tag Manager + Analytics can weigh 73kB (mine weights 93kB!) where the snippet weights only 1.5kB. It looks small but this is a big difference if it's going about web performance.

Both, the Google Analytics script and Minimal Analytics are vulnerable to blocking by AdBlockers.

If we need to resign from Minimal Analytics, as currently there is no minimal solution for Google Analytics 4 (yet), you will be forced to load Google's script and risking in performance impact. The new script is a monster that adds at least 171kB (!) to your website and that can cause a huge impact on performance.

I hope, that somebody will manage to sort our minimal version of the new solution before the end of the year (will be monitoring this for my benefit), however, if not, before rushing into the implementation of a new solution into your website, let's do this the smart way - the way [Smashing Magazine](https://www.smashingmagazine.com) do on their website, as I explained it in post [Implementing JavaScript Delay for Cookie Consent Banner](/en/implementing-js-delay-for-cookie-consent-banner/).

Let's then delay Google Analytics JavaScript until real user interaction happens on the website, together with marking-up (hiding) Google tracking script in a smart way (which I will cover below), so AdBlockers will not be blocking it, giving us much more accurate data for our analysis.

Before we move any further, there is another issue that you need to remember about closing Universal Analytics property.

You can delay your migration until 1st July 2023 (which I strongly discourage). After this period your UA will stop collecting data and you will have only 6 months left, under which you will be able to access its records (not mentioning that you will have half data in the old property at the time and half in the new that you will need to use). As there is not possible to just migrate them to a new solution you need to remember to [export it](https://support.google.com/analytics/answer/11583528#export) before they disappear for good. Let's plan and be ready for 2023 to start with the new solution using a smart approach.

Here is how we will do that.

## Smashing Magazine approach

Before I start, let's see how Smashing Magazine is calling their analytics script:
```html
<script class=js-additional importance=low data-delay=https://www.google-analytics.com/analytics.js defer></script>
```

> If I am not wrong, they still using Universal Analytics and they will need to implement GAv4 as well (unless they will [migrate somewhere else](https://plausible.io)).

As I mentioned in my [previous post regarding JavaScript Delay](/en/implementing-js-delay-for-cookie-consent-banner/#javascript-delay), they making the above script invalid (for HTML) by removing `src` part from it. Without it, the script will not load. After that they use another JavaScript that will run JavaScript Delay, which, when required, will replace the word `data-delay` with `src` and the above `<script>` will become valid again and run what is required.

> Let's ignore `class=js-additional` and `importance=low` for now.

The last thing is `defer` which will try to load (and fail by default) script after a page is loaded.

Now it's time for delayer.

## JavaScript Delay

We will be using following code (ideally as a last part before closing `</body>`):
```html
<script>
const autoLoadDuration = 5; //In Seconds
const eventList = ["keydown", "mousemove", "wheel", "touchmove", "touchstart", "touchend"];

const autoLoadTimeout = setTimeout(runScripts, autoLoadDuration * 1000);

eventList.forEach(function(event) {
    window.addEventListener(event, triggerScripts, { passive: true })
});

function triggerScripts() {
    runScripts();
    clearTimeout(autoLoadTimeout);
    eventList.forEach(function(event) {
         window.removeEventListener(event, triggerScripts, { passive: true });
    });
}

function runScripts() {
    document.querySelectorAll("script[data-delay]").forEach(function(scriptTag) {
        const delaySrc = scriptTag.getAttribute("data-delay");
        if (delaySrc) {
            scriptTag.setAttribute("src", delaySrc);
            scriptTag.removeAttribute("data-delay");
            if (scriptTag.hasAttribute("async")) {
                scriptTag.setAttribute("async", ""); // Re-apply async if it was present
            } else if (scriptTag.hasAttribute("defer")) {
                scriptTag.setAttribute("defer", ""); // Re-apply defer if async was NOT present
            } else {
                // Default to defer if neither async nor defer were initially present
                scriptTag.setAttribute("defer", "");
            }
        }
    });
}
</script>
```

This script will wait for user interaction by pressing the key, moving a mouse or touching the screen. This is the real interaction of the real user, not the machine that is "just" testing performance or crawling the page.

After that interaction, it will fire up all delayed scripts. In our example, it will fire up Google Analytics.

The problem with trying to run an external script from `google-analytics.com` is that this will be blocked by most AdBlockers.

It will work for some users, but you can easily see, that you will be missing like 30% of visits if not more.

Following [plausible.io approach to fighting with AdBlockers](https://plausible.io/docs/proxy/guides/netlify#troubleshooting) we will be doing some magic here.

## Google Analytics 4 code (Global site tag - gtag.js)

Before we will do the magic, let's see how the new tracking code looks.

```html
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-FD38MN17VB"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-FD38MN17VB');
</script>
```

Independently if it runs from `google-analytics.com` or `googletagmanager.com` it will still be picked and blocked by AdBlockers.

## Masking (hiding) Google Analytics 4 code

To hide the code from our script we will be pretending that we will be calling our script locally, and using `redirect` rule `200` we will be doing the rest in the background.

As I am using Netlify as my hosting provider, I will be putting my redirect into `_redirects` file as follow:

```
/collect/js   https://www.googletagmanager.com/gtag/js   200
```

According to [Netlify redirect options with Query parameters](https://docs.netlify.com/routing/redirects/redirect-options/#query-parameters):
> "(...) our service automatically passes on all query string parameters to destination paths for redirects with 200, (...)"

We can make redirects as simple as possible.

{{% ads-in-article %}}

If we want however to pick query parameter and pass further, we can do this in such a way

```
/collect/js id=:id  https://www.googletagmanager.com/gtag/js?id=:id  200
```

The way, how this can be implemented strictly depend on what your hosting provider is offering.

My modified code with implemented redirect rule will looks as follow:
```html
<script async src="/collect/js?id=G-FD38MN17VB"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-FD38MN17VB');
</script>
```

If I implement delay (along with defer), it will be:
```html
<script data-delay="/collect/js?id=G-FD38MN17VB"></script>
<script data-delay="/js/big-g-2nd-part.js"></script>
```

> The `defer` attribute is added by default unless it is already specified in `<script>`. If `async` is present, `async` is retained.

The second part of the code, just:
```javascript
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-FD38MN17VB');
```

I put it into `/js/` folder at the root of my website, into a file called `big-g-2nd-part.js` that will fire up after the first. The naming of the file is up to you, but don't call it `analytics.js` as this can be easily blocked.

And like that, theoretically, we will have this heavy (171kB) analytics script fired up after the page is loaded (after Google PageSpeed Insight robots will stop rendering it). And that is working as expected.

**What is not working** is the masking idea. When calling GTAG script through, when loaded it will still call `google-analytics.com/collect`, and that will be picked up by AdBlockers and blocked. 

I will be evaluating how to bypass that, but not sure if that will be possible without hosting the analytics script locally. For now, the below code will be sufficient.

```html
<script data-delay="https://www.googletagmanager.com/gtag/js?id=G-FD38MN17VB"></script>
<script data-delay="/js/big-g-2nd-part.js"></script>
```

I am not using self-hosted analytics code, which Google can penalise for, but it would potentially save my website from an unnecessary drop in performance. If I want to future proof it against picking up by AdBlockers however I will need to assess the risk. Big players are doing it, so maybe this Google threatening finger is only for show.

> Using marking of the calls to google analytics can have a [downside, like I explained in my other post](/en/prevent-google-analytics-being-blocked-adblocker/#the-downside).

Fingers crossed, that somebody will provide for us Minimal Analytics for v4, like [David Künnen](https://twitter.com/kunnendavid) provided for us for v3 (Universal Analytics).

> Based on David's Minimal Analytics code and a couple of websites explaining Google Analytics 4 measurement protocol I managed to create mine [A very Minimal Google Analytics 4 Snippet](/en/minimal-google-analytics-4-snippet/).


---
## Implementing JavaScript Delay for Cookie Consent Banner
- **URL:** https://dariusz.wieckiewicz.org/en/implementing-js-delay-for-cookie-consent-banner/
- **Date:** 2022-03-15
- **Tags:** JavaScript, JavaScript Delay, javascript banner, javascript cookie consent banner, Cookie Consent Banner, cookie consent javascript, cookie banner js, EU Cookie Law, CLS, Cumulative Layout Shift, Core Web Vitals, Google Search, performance, PageSpeed Insight, Developer Tools, minimal analytic', google analytics

### Content

Over some time I have been looking for ideal Cookie Consent Banner implementation on my websites. The main goal was to make sure it's not causing CLS (Cumulative Layout Shift) resulting in poor Core Web Vitals (and downgrading website in Google Search).

I found the solution that worked for me for some time. 

Together with other optimisation works I managed to achieve my goal, however, from time to time I saw a spike in [PageSpeed Insight](https://pagespeed.web.dev) for some pages and I couldn't figure out what else I could do to make sure that Cookie Banner (Bar) is not causing CLS.

<!--more-->

> I know, that [Cookie consent banners are utter nonsense](/en/cookie-consent-banners-are-utter-nonsense/) as I said on my website, however, there are places (commercial application) when going into court for breaching such nonsense like EU Cookie Law can cost a lot. In that case, you like it or not, you need to use it.

On one day I looked into a source code of [Smashing Magazine](https://smashingmagazine.com) (my number one website for web development news). They made a lot of optimisation works on their end and they understand "a fight" with web metrics and poor core Web Vitals firsthand from their [case study](https://www.smashingmagazine.com/2021/12/core-web-vitals-case-study-smashing-magazine/).

I admire their persistence in that matter and so I looked into their implementation of the cookie banner. I found that they are using, new to me, the approach of delaying (do not mix with deferring) of JavaScripts until "actual" user interaction with their website (and not when the site is finishing loading). This approach is used not only for what I have been looking for but also for other scripts.

Because my cookie bar solution is a good base to start, I decided to go a step forward and implement their approach to improve it even further and here's how it goes.

Before I start, I will recall my solution.

## Cookie Consent Banner (Cookie Bar)

My cookie bar is a combination of HTML file with simple code, JavaScript with the execution and CSS for styling.

Let's start with HTML
```HTML
<div id="CookieBanner" class="cookie-banner js-cookie-banner">
  <p>
    This site use 🍪cookies. Read more in <a href="/cookies-policy/">Cookies Policy</a>.
  </p>
  <button class="cookie-btn">Ok!</button>
</div>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="cookie.js" async></script>
```

Depending on how your website is built, you may put it all in the footer, incorporate style with yours. As I am using [Hugo](https://gohugo.io), I am calling it through partial. As I will not cover Hugo here, I will just work on the basics.

Adding some basic styling to it:
```CSS
#CookieBanner { display: none; }

.cookie-banner {
  position: fixed;
  right: 0;
  bottom: 0;
  min-width: 100%;
  background: white;
  color: black;
  text-align: center;
}

.cookie-banner p {
	font-size: 1rem;
	padding: 1rem 0.5rem 0.375rem 0.5rem;
}

.cookie-banner a {
	color: black;
}

.cookie-btn {
	background: red;
	border: 0;
	color: white;
	padding: 0.375rem 2rem;
	font-size: 1rem;
	margin-bottom: 1rem;
	border-radius: 0.5rem;
	cursor: pointer;
}
```

Of course, you will modify this and adjust to responsive layout using `@media` query. Possibilities are limitless but don't overdo it, especially with fonts. Keep it simple and stick to [system font stack](https://systemfontstack.com). It's just a cookie banner, not a decoration for your website.

As you will see, by default, the banned is hidden by `display: none;`. Here is a little magic that happens with JavaScript.

```JavaScript
if (localStorage.getItem("cookieBannerDisplayed")) {
  document.querySelector('.js-cookie-banner').remove();
} else {
  
  document.getElementById("CookieBanner").style.display = "block";

function dismiss() {
      document.querySelector('.js-cookie-banner').remove();
      localStorage.setItem("cookieBannerDisplayed", "true");
}

  const buttonElement = document.querySelector('.cookie-btn');
  if (buttonElement) {
      buttonElement.addEventListener('click', dismiss);
  }
}
```

In short.

When you visit my (other) website and you never clicked on the cookie banner, you will be presented with it. That is the part where style is changing from `display: none;` to `display: block`.

When you click **Ok** button (`.cookie-btn`), your answer will be stored in `localStorge` of your browser. Next time you will visit that website, the cookie banner will be hidden straight away as there will be an element in your browser `localStorage` called `cookieBannerDisplayed` with the value `true`.

> The above code is available on my [Github > idarek/cookies-bar](https://github.com/idarek/cookies-bar).

As you notice in the beginning, JavaScript is called via the following part:
```html
<script src="cookie.js" async></script>
```

Using the above part, the JavaScript will be loaded together with other elements of the website. Sometimes this will interfere with CLS, but unlikely it will do any harm. 

But what if we can stop loading it all together and only call it when needed "for user", not for the machine-like PageSpeed Insight.

And here is where I will be implementing JavaScript delay.

{{% ads-in-article %}}

## JavaScript Delay

The delayer will make sure, that JavaScript will be loaded when is needed. It's not only limited to Cookie Consent Banner and can be used with other scripts in a similar manner. Before you will implement it, make sure you test it well. It will not work on some JavaScript-based Lighthouse effect for images on the website but will work for Google Analytics.

JavaScript can be loaded with just `<script>` tag, with `async` parameter or `defer`. Each of them got pros and cons. The final decision is based on the importance of the script and its impact on the website.

Firstly, we will need to implement a delayer (ideally in the footer)
```html
<script>
const autoLoadDuration = 5; //In Seconds
const eventList = ["keydown", "mousemove", "wheel", "touchmove", "touchstart", "touchend"];

const autoLoadTimeout = setTimeout(runScripts, autoLoadDuration * 1000);

eventList.forEach(function(event) {
    window.addEventListener(event, triggerScripts, { passive: true })
});

function triggerScripts() {
    runScripts();
    clearTimeout(autoLoadTimeout);
    eventList.forEach(function(event) {
         window.removeEventListener(event, triggerScripts, { passive: true });
    });
}

function runScripts() {
    document.querySelectorAll("script[data-delay]").forEach(function(scriptTag) {
        const delaySrc = scriptTag.getAttribute("data-delay");
        if (delaySrc) {
            scriptTag.setAttribute("src", delaySrc);
            scriptTag.removeAttribute("data-delay");
            if (scriptTag.hasAttribute("async")) {
                scriptTag.setAttribute("async", ""); // Re-apply async if it was present
            } else if (scriptTag.hasAttribute("defer")) {
                scriptTag.setAttribute("defer", ""); // Re-apply defer if async was NOT present
            } else {
                // Default to defer if neither async nor defer were initially present
                scriptTag.setAttribute("defer", "");
            }
        }
    });
}
</script>
```

This short script will wait for user interaction by pressing the key, moving a mouse or touching the screen. This is the real interaction of the real user, not the machine that is "just" testing performance.

After that interaction, it will fire up all delayed scripts.

Now we need to decide which are they.

For this matter we changing the part responsible for loading our JavaScript as follow:
```html
<script data-delay="cookie.js"></script>
```

You will see that `src` has been replaced with `data-delay` making `<script>` invalid for HTML validators. As in HTML there is no such parameter as `data-delay`, and `src` is required, the script will simply not load. And that is what we want.

Now our delayer implemented earlier will do its magic. When it will detect real user interaction, it will fire up the script by changing `data-delay` word (this can be any other word by the way) to `scr` making the `<script>` valid and working again.

And like that, after our page is loaded (when PageSpeed will output its result), our script will load.

> There is also a fail-safe implemented there if there is no user interaction at all to load delayed script after 5 seconds either way after loading script (which was delayed using `defer` to load after the page is loaded). After 5 seconds properly designed website shall already be fully loaded. The `defer` attribute is added by default unless it is already specified in `<script>`. If `async` is present, `async` is retained.

In that scenario, our Cookie Banner will not be displayed at all, independently on status in browser `localStorage`. When you move the cursor, press a key or scroll the page, it will display for us and will hunt until we click the Ok button.

You can trace delayer behaviour by inspecting a website using the build-in Developer Tools in your browser (see tab Network).

If your website is using some heavy scripts (like heavy original Google Analytics script, if you not using Minimal Analytics, or even Ads pushed this way), by delaying them, you can significantly improve your website performance, at least in the eye of Google performance robots.

---

The above part related to JavaScript Delay, in short, is based on [Delay Javascript to Boost Web Vitals Score](https://blog.speedvitals.com/delay-javascript/) by SpeedVitals. Have look at their post to get wider into that matter.



---
## Cookie consent banners are utter nonsense!
- **URL:** https://dariusz.wieckiewicz.org/en/cookie-consent-banners-are-utter-nonsense/
- **Date:** 2022-03-14
- **Tags:** Cookies, Cookie consent banners, utter nonsense, NHS website, Core Web Vitals

### Content

Do you even care when you click **Agree** on the cookie consent bar? Do you even know what that means for you or what the hell are they for? Are you just trying to get rid of them to go to the intended website without distraction?

As much as they were intended to give some knowledge to end-users, they became just a sign of frustration and pointless exercise.

<!--more-->

If you are living in the UK you used (or are still using) the NHS website to report your COVID-19 test result.

This NHS website is a great example of how cookie bar is total nonsense and the web developers who implement that shall get a medal for pissing off its users.

Without going into the aspect of what happens when we click **Accept** on cookie consent banners, or what shall happen when we don’t, as well as what are cookies after all, here is how frustrated for its users they can be.

**So, you want to report your result of the COVID-19 test**.

You are heading to [www.gov.uk/report-covid19-result](https://www.gov.uk/report-covid19-result)

[![NHS 1st Cookies Banner](/images/2022/03/nhs_1_cookies_banner-min.png)](/images/2022/03/nhs_1_cookies_banner-min.png)

The majority of people will do this on their mobile devices, so the first thing we see is a cookies consent banner on half of the website.

[![NHS 1st Cookies Banner Accepted](/images/2022/03/nhs_1_cookies_banner_accepted-min.png)](/images/2022/03/nhs_1_cookies_banner_accepted-min.png)

Let’s click **Accept** to get rid of it.

Sadly, we cannot get rid of it with just one click, as it informs you about your decision, so you need to click the Hide button to get rid of it.

**One-click too much**.

[![NHS Covid-19 Start Now](/images/2022/03/nhs_1_cookies_banner_accepted_start_now-min.png)](/images/2022/03/nhs_1_cookies_banner_accepted_start_now-min.png)

Then you are trying to do what you intended to. So you click the **Start now** button.

And what happens in the next stage? Another Cookie Consent Banner to accept before you can sign in (or not) into your NHS account.

{{% gallery %}}
[![NHS 2nd Cookies Banner](/images/2022/03/nhs_2_cookies_banner-min.png)](/images/2022/03/nhs_2_cookies_banner-min.png)
[![NHS 2nd Cookies Banner Accepted](/images/2022/03/nhs_2_cookies_banner_accepted-min.png)](/images/2022/03/nhs_2_cookies_banner_accepted-min.png)
{{% /gallery %}}

Once again you need to click **Accept** and again **Hide** to get rid of it altogether. This time the UI is inconsistent with the previous page as the **Hide** button is not the same.

Another distraction.

[![NHS 3rd Cookies Banner](/images/2022/03/nhs_3_cookies_banner-min.png)](/images/2022/03/nhs_3_cookies_banner-min.png)

You decided to sign in and what? You land on another page with another cookie content bar, once again taking half of the screen.

On the first, I may be interested in what is all about. On the second I am a little annoyed, so I am clicking accept again. For the third time, I am frustrated that I need to do this once again! At this stage, I don’t care what is that. This banner can even tell me that I won £1m and I wouldn't care. Clicking **Accept** once again. 

[![NHS 3rd Cookies Banner Accepted](/images/2022/03/nhs_3_cookies_banner_accepted-min.png)](/images/2022/03/nhs_3_cookies_banner_accepted-min.png)

Another inconsistent UI, as this time I don’t have a button to hide my consent after I click **Accept**, but I am just informed about my decision. 

The cookie bar shall simply go away, not bother you like a ghost on the website. Pathetic.

I get it, in between the first step, logging in, and on the end, reporting my result, I am passed through different servers and different domains, but seriously, the sense of the cookie consent banner losing the point.

[![My Cookie Consent Banner](/images/2022/03/my_cookie_consent_banner-min.png)](/images/2022/03/my_cookie_consent_banner-min.png)

If you visited my website for the first time you will also notice the cookie consent banner on the bottom of the page. I don’t know if I fully need it or not. As I am using analytics to track who is visiting my website, this is probably leaving some crumbs on your machine, hence probably need it. 

{{% ads-in-article %}}

I am not giving you a choice to accept that or reject, as I don’t have control over it. Take it or not, but if you want to accept it, or rather get rid of it, you need to hit this button there.

Does any of you even read my [cookie consent](/en/cookies-policy/) page? I doubt.

I wish, when all browsers will block cross-tracking cookies, that this nonsense will disappear from web development. Sadly I am full of doubt about that. 

The worse thing is that all these banners are harming users. Putting distractions and slowing down websites. You can implement a [cookie consent bar that won't have a negative impact on the core web vitals](https://github.com/idarek/cookies-bar) of your website, but will you?

The majority of websites use ready-made solutions that don’t care about your website performance.

When users stop caring about cookies, especially when web browsers like Microsoft Edge and Safari are doing their bits to protect them, I don’t see the point of having it. 

Sadly, especially on big brands' websites, earning a lot through them, they will still prefer to have it in place instead of risking being sued. 

I am removing the banner from my website and other private sites, living a link to the [cookie content page](/en/cookies-policy/). If I am getting annoyed about them, I don’t want to annoy users who are visiting my website. Overall I don’t care about cookies and don’t think you are (in a matter of consent banner, not these that can be stolen by advertising companies to target you). 

Of course, to sleep well, commercial websites that I made will still carry with this nonsense until there is industry-wide change and understanding that cookie consent banners are utter nonsense.


---
## Baileys Brownie Cake
- **URL:** https://dariusz.wieckiewicz.org/en/baileys-brownie-cake/
- **Date:** 2022-03-07
- **Tags:** Baileys, Irish Cream, Brownie, Cake, Brownie Cake, Baileys Brownie Cake, Baileys Irish Cream

### Content

My wife is a magnificent cook and recently she found herself experimenting with Brownie. From experimentation to perfection she made today a perfect Baileys Brownie Cake.

> Difficulty: **Low**\
> Preparation Time: **10 minutes**\
> Baking time: **35 minutes, 175C with fan**

<!--more-->

## Ingredients

* 285g of plain flour
* 3 tsp spoon of baking powder
* 2 tbsp spoon of cocoa powder
* 3 large eggs
* 200ml of [Bailays Irish Cream](https://en.wikipedia.org/wiki/Baileys_Irish_Cream)
* 150g of coconut oil
* 200g caster sugar
* pecan nuts (optional)

{{% ads-in-article %}}

## Method

Preheat the oven to 175C.

Put all dry ingredients into a bowl (flour, baking powder, cocoa powder and sugar). Using a spatula or wooden spoon mix firmly.

Whisk the eggs with half of Baileys.

Melt the coconut oil and allow it to cool down a little.

Put melted coconut oil, egg-Bailey's mixture and remaining Bailay's pure into a dry mix and mix firmly. Do not use a hand mixer.

The mixture shall have the consistency of toothpaste (can be slightly runnier).

If the mixture is too dry, add more Baileys.

Using a 20x25cm baking tin, line the bottom with baking parchment.

> Put a couple of pecan nuts on the bottom of the tin (optional).

Pour the mixture slowly around the tin and in the middle then spread to level it up.

Bake on the middle shelf for 35 minutes.

Before removing from the oven, check in the middle using a wooden stick, if the cake is fully baked. 

The outside shall be slightly crispy and the inside should have the consistency of a sponge.


---
## How to Change the Default Search Engine in the Internet Browser?
- **URL:** https://dariusz.wieckiewicz.org/en/how-to-change-default-search-engine-internet-browser/
- **Date:** 2022-03-04
- **Tags:** keepITshort, ITadvice, TLDR, 15seconds, LessIsMore, Microsoft Edge, Google Chrome, Mozilla Firefox, Safari, Opera

### Content

We are living in TL;DR[^1] world and I got only 15 seconds to give you an IT advice. In this series, I will try to do this. Here we go with **how to change the default search engine in the internet browser**.

<!--more-->

## Microsoft Edge (Windows, macOS)

* Click the menu button <kbd>…</kbd> and select **Settings**
* Select **Privacy, Search, and Services** from left menu
* Scroll down to **Services** section
* Click on **Address bar and search**
* From **Search engine used in the address bar** dropdown  select desired search engine.

## Google Chrome (Windows, macOS)

* Click the menu button <kbd>⋮</kbd> and select **Settings**
* Select **Search engine** from left menu
* From **Search engine used in address bar** dropdown select desired search engine.

## Mozilla Firefox (Windows, macOS)

* Click the menu button <kbd>☰</kbd> and select **Settings**
* Select **Search** from left menu
* From **Default Search Engine** dropdown select desired search engine. 

## Safari (macOS)

* From top menu select **Safari** and **Preferences...**
* Click on **Search** icon
* From **Search engine** dropdown select desired search engine.

## Opera (Windows, macOS)

* Click **Opera** logo in top-left part of the window and select **Settings** (Windows), or
* From top menu bar select **Opera** and **Preferences...** (macOS)
* Scroll down to **Search engine** section
* From **Search engine used in address bar** dropdown select desired search engine.

[^1]: Too long; didn't read

{{% ads-in-article %}}

> Screenshot icons created by Freepik - [Flaticon](https://www.flaticon.com/free-icons/search-bar)



---
## How to Test Your Internet Speed?
- **URL:** https://dariusz.wieckiewicz.org/en/how-to-test-your-internet-speed/
- **Date:** 2022-03-03
- **Tags:** keepITshort, ITadvice, TLDR, 15seconds, LessIsMore, speed, speedtest, broadbandspeed, testspeed

### Content

We are living in TL;DR[^1] world and I got only 15 seconds to give you an IT advice. In this series, I will try to do this. Here we go with **how to test your internet speed**, using just an internet browser.

<!--more-->

> For best (most accurate) results connect your device to your router using a network cable instead of WiFi (if possible). When testing over WiFi make sure you are connected to fast 5GHz WiFi (if available) over 2.4GHz, and you are close to your router.

## Fast.com (from Netflix)

* Open website [fast.com](https://fast.com) in your browser.
* Website will start measuring your **Download** speed **‌immediately**, after this is done
* Click **Show more info** to test your **Upload** speed as well.

## Speed Test (from Cloudflare)

* Open website [speed.cloudflare.com](https://speed.cloudflare.com) in your browser.
* Website will start measuring your **Download** and **Upload** speed **immediately**.

## Internet speed test (through Google, from Measurement Lab)

* Open website [google.com](https://www.google.com/search?q=internet+speed+test) and search for **speed test** (or **internet speed test**).
* On top of search results you will have an option to test your speed.
* Click blue button **Run Speed Test** to test your **Download** and **Upload** speed.

> **Important:** This feature isn’t available in some countries and regions.

## SpeedSmart.net

* Open website [speedsmart.net](https://speedsmart.net/) in your browser.
* Click big blue button **Start Speedtest** to test your **Download** and **Upload** speed.

## Speedtest.net (from Ookla)

* Open website [www.speedtest.net](https://www.speedtest.net/) in your browser.
* Click the big circled **Go** button to start testing your **Download** and **Upload** speed.

## Speedof.me

* Open website [speedof.me](https://speedof.me/) in your browser.
* Click **START TEST** button to test your **Download** and **Upload** speed.


[^1]: Too long; didn't read

{{% ads-in-article %}}

> Speed icons created by Freepik - [Flaticon](https://www.flaticon.com/free-icons/speed)


---
## How to Take a Screenshot of a Website?
- **URL:** https://dariusz.wieckiewicz.org/en/how-to-take-a-screenshot-of-a-website/
- **Date:** 2022-03-02
- **Tags:** keepITshort, ITadvice, TLDR, 15seconds, LessIsMore, Microsoft Edge, Google Chrome, Mozilla Firefox, Safari, Opera

### Content

We are living in TL;DR[^1] world and I got only 15 seconds to give you an IT advice. In this series, I will try to do this. Here we go with **how to take a screenshot of a website natively in a desktop web browser**.

<!--more-->

## Microsoft Edge (Windows, macOS)

* Click the menu button <kbd>…</kbd>, select **Web Capture**, or
* Use keyboard shortcut
  * <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>S</kbd> (Windows)
  * <kbd>Shift ⇧</kbd>+<kbd>Command (or Cmd) ⌘</kbd>+<kbd>S</kbd> (macOS), or
* Right-click on an empty part of the website, select **Web Capture** (from menu)
* Select **Capture Area** or **Capture full page**
* Save your file.

## Google Chrome (Windows, macOS)

* Click the menu button <kbd>⋮</kbd>, click **More tools**, select **Developer tools**, or
* Use keyboard shortcut
  * <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd> (Windows)
  * <kbd>Option (or Alt) ⌥</kbd>+<kbd>Command (or Cmd) ⌘</kbd>+<kbd>I</kbd> (macOS), or
* Right-click on an empty part of the website, select **Inspect** (from menu)
* Click DevTools menu button `⋮`, click **Run command**, or
* Use keyboard shortcut
  * <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> (Windows)
  * <kbd>Command (or Cmd) ⌘</kbd>+<kbd>Shift ⇧</kbd>+<kbd>P</kbd> (macOS)
* Type **screenshot**
* Select **Capture area** or **Capture full size**
* Save your file.

## Mozilla Firefox (Windows, macOS)

* Right-click on an empty part of the website, select **Take screenshot**
* Select **Save full page** or **Save visible**,
* Save your file.

## Safari (macOS)

* Right-click on an empty part of the website, select **Inspect element** (from menu)
* In **Web inspector** window (with source code) find 2nd line (typically) starting with `<html`
* Right-click on `<html`, click **Capture Screenshot**
* Save your file.

## Opera (Windows, macOS)

* Click **camera** button located in the top-right part of your browser window
* Select **Capture full screen** or **Save page as PDF**
* Save your file.

[^1]: Too long; didn't read

{{% ads-in-article %}}

> Screenshot icons created by Freepik - [Flaticon](https://www.flaticon.com/free-icons/screenshot)



---
## Does Ads on YouTube make you mad? There is a way for that.
- **URL:** https://dariusz.wieckiewicz.org/en/youtube-ads-make-you-mad-use-vinegar/
- **Date:** 2022-02-25
- **Tags:** youtube, iOS, iPadOS, macOS, Vinegar, Baking Soda, Fizzy Water Bundle, Zhenyi Tan, Apple, AppStore, Safari, extension

### Content

Do you watch YouTube a lot? Are you addicted to it, or just need it for your work?

Do the ads cause you a headache?

There is nothing better than suddenly showing an Ad in the middle of streaming from YouTube to a bigger audience (possibly on a bigger screen and using bigger, much louder audio equipment). This may ruin a lot and put distraction in time when you need people to concentrate on presented material (either video or just audio).

This may annoy you and others to the extent that you will think to pay this £11.99 per month for YouTube Premium only to get rid of this annoyance.

But what if I will tell you there is a better (and cheaper) way?

<!--more-->

I need to warn you at the beginning. There is one thing that you need to have and another that you need to change in your daily workflow with YouTube.

The first thing is, you need to have an Apple device. Either iPhone, iPad or Mac to get this working. Sorry Android users, there may be a solution for you as well in Play Store, but as I am bonded to Apple devices will not be covering that here.

Second thing is, that you will need (_optional_) to **resign from using the official YouTube app** on your device and start using YouTube via default, Apple internet browser – Safari.

> Before you stop reading further, let me explain to you why this is a good solution, and that over a short time this may not be such an inconvenience as you may first think! I am not using YouTube app since 1st December 2021 and believe me, I am more than happy when I am watching YouTube right now.
> 
> And **yes**! By doing this (what is explained below) you not giving creators, the ability to earn money from Ads. If you think it's worth supporting any of them, there are other ways to do that, not only through Ads.

Resignation from the YouTube app is _optional_ but **highly recommended**.

It's recommended mostly because each time you click on a YouTube link (like sent to you in email or message), the app will "hijack" this request, and instead of opening it in a browser, it will open in the app automatically.

You will still be able to use YouTube like before. You will be able to log in to your Google account, have access to all your watch history, saved items, add likes, comments even share it further.

---

If you are reading further, I assume that you got an Apple device and you are willing to give it a go (including dumping the YouTube app).

> Let me inform you, that this solution **is not free**. It will cost you **£1.79** (up to a maximum of £2.49) **once**! No need to pay £11.99 or anything else monthly. This money is not paid to me. I am not getting a penny from that. You are supporting the original developer of it.

## Vinegar

![Vinegar Icon](vinegar_icon.png)

Let me introduce you to [Vinegar](https://apps.apple.com/app/vinegar-tube-cleaner/id1591303229) app made by [Zhenyi Tan](https://twitter.com/zhenyitan), the owner of the website [Zhenyi Tan And a Dinosaur](https://andadinosaur.com).

A bit of technical stuff. The idea of the app is to replace build in YouTube video player with a native video player based on HTML5 `<video>` tag.

If you watched before any of the [Apple Events](https://www.apple.com/uk/apple-events/) you may visually remember how they are played on the website. 

Pure `<video>` tag with a source link to a video.

Vinegar app is doing exactly that same but with YouTube website. It is replacing "their" player with a native one, giving you a similar interface to other websites that display videos in that way.

![Vinegar screenshot](vinegar_andadinosaur_com.png "Source: andadinosaur.com/launch-vinegar")

What you gain thanks to that is the lack of advertisements that are pushed in various points during watching. As the player is streaming the required video to us, it is difficult to interrupt it without doing an additional job on the YouTube server side. Currently, it's not easy for them to fight that, but don't be surprised if in future this will change.

![YouTube website with Vinegar Extension](youtube_c5SeQaESZAE_vinegar_1.png)

This is how it will look if you will open [this video](https://www.youtube.com/watch?v=c5SeQaESZAE) in Safari (screen from Mac).

Notice native controls on the bottom of the video and a new menu hovering above it where you can change the quality or switch into Audio only.

![YouTube website with Vinegar Extension - Toolbar Open](youtube_c5SeQaESZAE_vinegar_2.png)

If you switch to audio-only, you will turn off video from your screen leaving sound running.

This will allow you to stream audio-only.

If you open this video in Safari on your iPhone, you can leave it on, lock the screen and the sound will still be flowing in the background.

> If you would like to listen to something that is on YouTube only when you are travelling in your car, and you have Apple CarPlay available, this will give you another option to enjoy a YouTube Audio-only experience that the standard App will not offer.

Not only will you save your data on streaming audio-only, which is crucial if you are using a data plan, but you will also gain control on your lock screen.

![YouTube via Safari on Lock Screen iPhone](youtube_controls_on_lock_screen.jpg)

You can also leave Safari open and go into different apps and sound will still be playing in the background!

Next to the arrow button (top left) that will make your video go full screen, you can click on picture-in-picture and your video will keep playing, hovering on top of other things that you may be doing in the meantime.

![Youtube Pictire-in-Picture Safari](youtube_pip_akashi.png)

And this is why it's crucial when you click on the above YouTube video link, you will **not have** YouTube App installed, as in another case the app will take control over.

Now you know why it was crucial to remove the YouTube app.

How about your YouTube experience in Browser then?

{{% gallery %}}
[![YouTube in App](youtube_in_app.png)](youtube_in_app.png)
[![Youtube over Safari](youtube_over_safari.png)](youtube_over_safari.png)
{{% /gallery %}}

Here is how YouTube will look in your app on iPhone (left) and the same device through Safari (right).

Of course, you will notice firstly an Ad in the app, which was blocked by AdBlocker that I am using in Safari.

The app has a handy toolbar on the far bottom. Additionally offers an option to send push notifications when new content is released on the subscribed channel.

In Safari you got extra space eaten by the Safari address bar (that will hide when you will scroll the page) and the bottom bar sometimes will be there (like in the App), sometimes not when you scroll (bug in YouTube website design?).

Also, the app is presented in a handy shortcut in your iPhone/iPad Home Screen, where to enter YouTube via Safari, you need to head to Safari itself first and then go to YouTube bookmark.

Two steps, for some, will be one too many.

![Safari - Add to Home Screen](safari_add_to_homescreen.jpg)

Luckily Safari is offering the ability to send a shortcut to our selected website into our device Home Screen. The icon will not look as pretty as a native App (this can be fixed with Apple Shortcut - not described here), but instead of two clicks, you will have a single, similar to when you open a native App.

There is another small "downside" of using YouTube over Safari. As I mentioned in the beginning, you will "need to change your daily workflow with YouTube" and this is why.

If somebody will send you a link to a YouTube video (over Messagener or another app), on iOS/iPad OS devices it will open in the preview window by default (not a full Safari).

The Vinegar app is an extension to Safari and extensions are not working in preview so you will see, that you will be presented with the website and their original player (with Ads).

To move from the preview window (depending on the app) you may need to use the Share Sheet menu (this square with an arrow pointing up) to **Open in Safari** or you will be presented with a Safari icon in the right bottom corner that will transfer you to **the right Safari app**. 

Normally, when you will have your YouTube App installed it will redirect you (as I mentioned – "hijack"), and open it in the app. You will have limited ability to control this. If you got your app removed, then there are more options available.

This is the new "workflow" to which you will need to "retrain" your brain. It's not easy, especially if you use an app for a long time, but if you are annoyed with Ads, over a short time you will understand the benefit of it – the lack of Ads, and this will drastically improve your experience with this website.

But, if a YouTube website can be modified like that, why not go a step further and use it on other websites that offer videos (mostly with Ads)?

{{% ads-in-article %}}

## Baking Soda

The author of the Vinegar app created an additional app used for that purpose. It's called [Baking Soda]((https://apps.apple.com/app/baking-soda-tube-cleaner/id1601151613). Yes, I know, the naming of the apps by Zhenyi Tan is unique.

This app has the same purpose as Vinegar for YouTube. It is replacing video players wherever possible (apart from YouTube itself) to the native using the `<video>` tag.

The app costs similarly to Vinegar – £1.79 but you can purchase both of them in a bundle [Vinegar + Baking Soda](https://apps.apple.com/app-bundle/fizzy-water-bundle/id1601247237) for £2.49 (one-time purchase).

But that's not all.

## Multiple devices and Family Sharing

Vinegar and Baking Soda is also available for Mac computers. If you purchase it on one of your devices, you can install them in Safari on your Mac for free as the app (extension really) is made as a universal app.

Additionally, if you created a Family group across your Apple ID (I got myself, my wife and two kids) you can share these apps with them for free. They can install them from your purchases without the need to pay for them again.

Family Sharing allows you to share this app with up to six family members. When you think about that, the price that you paid is a real bargain (especially if you know that between 15-30% of its price is an Apple fee).

---

Have I convinced you or are you still hesitating?

I think it's worth at least trying. If you decide to go with £1.79 for a single app or £2.49 for a bundle, it's cheaper than YouTube Premium.

Of course, you can try YouTube Premium for free for a month before you will need to pay, so you can compare. Even though, I still think it's worth giving Vinegar a chance.

If you don't know if you need Vinegar only or both apps, you can purchase Vinegar right now and add Baking Soda later for £0.70 extra as an upgrade (which will give you a bundle price of £2.49).

---

## A warning about fake apps

The author put a lot of effort into its app (extension) and is constantly maintaining it. His commitment justified the fact that the app is not free. 

Since he released it, a couple of shifty developers stole part of the code of his app and released their app for free in the AppStore with shady privacy practices. Be aware of that. If you want to be sure, that the app is not doing anything else apart from what it was intended to do, always choose it from the right source.

## Links

* [**Vinegar** in AppStore](https://apps.apple.com/app/vinegar-tube-cleaner/id1591303229)
* [**Baking Soda** in AppStore](https://apps.apple.com/app/baking-soda-tube-cleaner/id1601151613)
* [Vinegar & Baking Soda Bundle in AppStore](https://apps.apple.com/app-bundle/fizzy-water-bundle/id1601247237) called **Fizzy Water Bundle**.

Fizzy Water... yes, another interesting name :)


---
## Prevent Google Analytics from being blocked by AdBlocker
- **URL:** https://dariusz.wieckiewicz.org/en/prevent-google-analytics-being-blocked-adblocker/
- **Date:** 2022-02-23
- **Tags:** google analytics, adblock plus, duckduckgo, tracking, privacy, hugo, netlify, minimal analytics, plausible analytics, trackers

### Content

You may say what you want about Google Analytics, especially about how "they" are, apart from displaying data for you, using data gathered for "their" business purpose (forget about privacy). If you are a website owner and you are looking for a reasonable tracking method for your visitors, this is the solution that you will pick in the first place.

The problem with Google Analytics is that their tracking script weights a lot and that is slowing down your website.

<!--more-->

> Referred below code is based on Universal Analytics that will become obsolete by Google on 1st July 2023. Read [A very Minimal Google Analytics 4 Snippet](/en/minimal-google-analytics-4-snippet/) to use a similar approach with Google Analytics 4.

To solve this problem, but maintain basic use of your analytics, you can replace Google's tracking method with a snippet, a portion of it, that will do exactly what you need. This snipped is called [Minimal Google Analytics](https://minimalanalytics.com/) and was prepared by [DavidKuennen](https://gist.github.com/DavidKuennen) and published in unminified form on [GitHub Gist](https://gist.github.com/DavidKuennen/443121e692175d6fc145e1efb0284ec9).

Thanks to replacing Google tracking code, which weighs 73kB, we go down to just 1.5kB with the snipped provided.

If you are concerned about site speed and your Core Web Vitals metrics, replacing an externally called tracking script with minimal analytics is the first thing that you shall do.

All "my" websites are currently using this snipped and I am getting all the analytics that I need from it.

Once visitors visit a page, the snipped sending a signal via `/collect` URL to Google Analytics with specified tracking code `UA-XXXXXXXXX-X`. Simple as that.

When I compared statistics from 2021 for my websites to what I got in 2020 I noticed a huge drop in traffic across all sites.

Despite huge improvement in page speeds thanks to [Hugo](https://gohugo.io/) and a lot of SEO aspects implemented through the year, I couldn't figure out what was going on.

Recently, I noticed that this snippet was not reporting my visits to my website.

I thought that something was not right.

If my visit is not recorded (and I don't have any exclusions for that on the Google Analytics side), how many visits am I losing every day?

I excluded fault in snipped on its own, as it is working well.

This makes me think. Something is blocking my snipped and preventing me from reporting visits back to Google Analytics.

Then I looked at what changed on my side.

I am using AdBlocker (AdBlock Plus particularly) along with the DuckDuckGo browser extension.

When dependent on the blocking list, AdBlock did not block Google Analytics by default, the DuckDuckGo extension is doing it out of the box to protect our privacy. I understand that I do, but still, I want to know who is visiting my website, and I want data to be accurate.

Analysing various blogs I noticed that over the years many people reported similar behaviour, that a significant percentage of visitors blocked Google Analytics by default.

It's like Marko Saric in his post mentioned that [13% of my website visitors block Google Analytics](https://markosaric.com/google-analytics-blocking/), there is nothing more than agree.

This percentage is growing more and more.

On one of "my" websites with significant traffic, I saw a drop of 12.43% in the number of users in 2021 compared to 2020 and a 51.06% drop in the number of pages visited in the same period.

I want to do something with that.

I even looked and started a short trial of [Plausible Analytics](https://plausible.io), a simple and privacy-friendly Google Analytics alternative.

There was one issue with it, sorry! I didn't want to pay for it, especially on private websites that do not generate profit and traffic that is not worth adding extra cost to it.

As Plausible [mentioned](https://plausible.io/docs/proxy/introduction), they are not - yet - blocked by AdBlockers, like Google Analytics is by default.

> We're not blocked to the same extent as Google Analytics (neither Firefox nor Safari blocks Plausible) but we're blocked by some block list maintainers who have taken the stance that they want to block every tracking script and don't want to have the responsibility to judge what's good and what's bad.

The situation is fluid and they know, that at some point their solution will land on a block list, despite their efforts to change the word giving a real privacy-oriented alternative to what Google is offering.

> We're not blocked to the same extent as Google Analytics (neither Firefox nor Safari blocks Plausible) but we're blocked by some block list maintainers who have taken the stance that they want to block every tracking script and don't want to have the responsibility to judge what's good and what's bad**.

The problem is like Plausible mentioned, some eager people want to block everything, despite that they - Plausible - want to change the tracking industry for the better.

They knew that at some point they will need to fight with AdBlockers and they are ready for that providing a solution for various scenarios.

The way how AdBlockers are working, apart from the keyword-based approach, is that they analyse external links on our website. If they see a reference on my website to external `google-analytics.com`, they will block it. This is what the DuckDuckGo extension (and browser) is doing by default.

AdBlockers however are not blocking "things" originating from the origin domain - our website address.

You may think in that case, that you can serve Google Analytics script from your domain that will solve the problem. Not necessarily.

Google is forbidding this practice and can penalise you for doing that by blocking your account. Also, we removed the Google script by snipped, hence there is nothing else to serve from our side, as all are already.

With one exemption.

Minimal analytics snipped is sending "ping" to `www.google-analytics.com/collect` each time there is new traffic on my website.

This of course will be blocked, like in future `plausible.js` may be.

Plausible presented a solution by masking their tracking script by proxying through the originating server.

I am hosting my website on Netlify so I looked at how they did [Proxying Plausible through Netlify](https://plausible.io/docs/proxy/guides/netlify) and figured out, that I can do that same with my Minimal Analytics snipped that I am using.

I can proxy my call to `www.google-analytics.com/collect` using `_redirects` rule and pretend that I am "collecting" traffic from my domain.

No reference to `google-analytics.com`, so nothing is blocked.

So I put into my `_redirects` file the following line:

```
/collect   https://www.google-analytics.com/collect   200
```

And replaced `www.google-analytics.com/collect` with my domain. In that instance, it's `dariusz.wieckiewicz.org/collect`.

As you will see, I will still collect traffic through snippets, but theoretically, I will pinpoint to my website. In the background, behind AdBlocker's ability to trace, my `/collect` call will be redirected to Google Analytics.

Of course, it's worth replacing `/collect` (in the snippet and redirect rule) with some random string (unique per website) in case somebody will decide to add this phrase to the block list.

{{% ads-in-article %}}

## The downside

There is one significant downside of this solution.

The redirect rule that is happening in the background, far away from AdBlock eyes, happens on the hosting provider server. As I am using Netlify, it happens on the Netlify CDN side, hence this will happen on the Netlify distributed network of servers - the closes server to my location.

In that case, when I visited my website from the United Kingdom, the closest, less busy server is in Germany, hence all traffic sources will show that **Active Users** suddenly **all** come from **Germany**.

This is of course not true. If we want accurate data on that aspect, then we need to stick with the original call from snipped to `www.google-analytics.com`. In that case, we will lose up to 30% of real traffic information but will gain information from where our users are coming from.

But are data with up to 30% error worth analysing?

I made a decision, that I would like more to know how many users are visiting my website than knowing from where they come from. 

I know, that my [Polish](/) part of the website will have a majority of users coming from Poland, where the [English](/en/) part will have much more distributed users around the world.

Unless you target your website to a specific region and you need to know how many users are coming from which country, then this information is not as important. In my instance, I would rather like to know which parts of my website are most read so I can concentrate on content that I create to find what readers would like to read. The 70% accuracy is not the best source of information.

This downside is not the only issue with the above snippet. If you are using Plausible on Netlify, then you will have similar behaviour from their end when using the proxying method.

However, on Netlify there is also another thing that may interfere, which is in that instance **Asset optimization** for JavaScripts.

Plausible, as well, referring to this in [Troubleshooting](https://plausible.io/docs/proxy/guides/netlify#troubleshooting) section. Netlify CDNs can interfere with an address that we put in our JavaScript and rewrite it to match their distributed servers. To avoid that you shall disable **Asset optimization** (Bundle and Minify) for JavaScripts.

> This typically happens if in a script we will refer to just part of the URL string and not to the full domain name and string, like in my above example.

[![Netlify Asset Optimization](/images/2022/02/netlify_asset_optimization-min.png)](/images/2022/02/netlify_asset_optimization-min.png)

I am using only the Image Compression part of asset optimization as Minimal Analytics, already in the pre-minified version (and other JS served) and if I am calling CSS or JS in my Hugo website, I am already using a build-in minifier along with fingerprinting, hence pointless is to minify things twice.

If this "downside" doesn't put you out, then, despite losing accuracy in location tracking, you will see much closer to the real number of visits. But, if you need accurate data including the location of your users, and you are willing to pay for it, try [Plausible Analytics](https://plausible.io).

Netlify also offers its own, server-side, payable analytics solution, so you got an option to try.


---
## Updating Windows with PowerShell
- **URL:** https://dariusz.wieckiewicz.org/en/updating-windows-with-powershell/
- **Date:** 2022-02-18
- **Tags:** Windows 10, Windows 11, Windown Update, PowerShell, Get-WindowsUpdate, Install-WindowsUpdate, PSWindowsUpdate

### Content

Recently I came across a problem where a freshly installed Windows wouldn't download updates.

The search for updates took forever or, if they did appear, they were stuck in the download queue (Pending Download) and there was no way to convince them to download. Clicking the Download button did nothing. Even the tried and tested methods of resetting the Windows Update service didn't help.

Therefore, I started looking for another solution and that's how I came across the update method using PowerShell.

<!--more-->

## PowerShell 7.x

Before we start, it is worth installing PowerShell version 7 (minimum), as Windows has version 5.1 (!) by default, and this module likes to play tricks with this version.

[![PowerShell in Microsoft Store](microsoft_store_powershell.png)](microsoft_store_powershell.png)

We can do this [in various ways](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows), but the easiest in my opinion is to install it directly [from the Microsoft Store](https://www.microsoft.com/store/apps/9MZ1SNWT0N5D) (Microsoft Store). This way we won't have to worry about updating it manually.

We run our PowerShell in administrator mode (Run as administrator).

[![PowerShell 7 in administrator mode](pwsh_7.png)](pwsh_7.png)

## PSWindowsUpdate

To update our system, we will use a module prepared by [Michał Gajda](https://www.powershellgallery.com/profiles/MichalGajda) called **‌PSWindowsUpdate**.

This is not some little-known package. It has been downloaded over 112 million times (112,054,801 downloads and counting)!

[![Install-Module PSWindowsUpdate in PowerShell](pwsh_Install_Module_PSWindowsUpdate.png)](pwsh_Install_Module_PSWindowsUpdate.png)

To install it, we execute the following command:
```powershell
Install-Module PSWindowsUpdate
```

When asked whether to install the module from an "untrusted source", as well as others during installation, answer **Yes for All** with **A**.


[![Get-WindowsUpdate in PowerShell](pwsh_Get-WindowsUpdate.png)](pwsh_Get-WindowsUpdate.png)

Then it's time to search for updates:
```powershell
Get-WindowsUpdate
```

> After issuing the command, it may seem for a while that nothing happens. You should wait a moment until you see some response.

ps. Don't be fooled by the size of the update, because it is not always displayed correctly (like in my case 59GB, lol).

[![Install-WindowsUpdate in PowerShell](pwsh_Get-WindowsUpdate_Install-WindowsUpdate.png)](pwsh_Get-WindowsUpdate_Install-WindowsUpdate.png)

Once our updates are found, we execute the following command to install them:
```powershell
Install-WindowsUpdate
```

We also confirm with **A** that we want to perform the installation for all available updates.

Now all we have to do is sit back and wait for everything to download and install.

{{% ads-in-article %}}

## Update Management

The **PSWindowsUpdate** package is not only the above commands. It has a number of different options that can be used to, for example, remove installed updates or stop an update that we do not want.

The full list of available options can be viewed using:
```powershell
Get-Command -Module PSWindowsUpdate
```

[![Install-WindowsUpdate - Reboot required](pwsh_Install-WindowsUpdate_Reboot_required.png)](pwsh_Install-WindowsUpdate_Reboot_required.png)

When installing updates using the `Install-WindowsUpdate` command, we need to delve a bit into the information that is displayed (if any) at the very end. Sometimes, a computer restart is required, which will not be done for us, but we have to do it ourselves (decide at the end).

To make the whole process of finding updates, approving, installing and automatically starting the computer when needed, easier, we can use the following command:
```powershell
Get-WindowsUpdate -AcceptAll -Install -AutoReboot
```

If, using `Get-WindowsUpdate` we have several to choose from and we want to focus on one in particular, we can do it using the following entry:
```powershell
Get-WindowsUpdate -Install -KBArticleID 'KB5010414'
```

We change `KB5010414` accordingly to the one obtained after executing the command `Get-WindowsUpdate`.

Although in most cases the "graphical" Windows Update works as it should, it is good to have some kind of alternative.

Best regards.

---
Source: [How to install Windows 10 update using PowerShell](https://pureinfotech.com/install-windows-10-update-powershell/) by [Pureinfotech](https://pureinfotech.com)


---
## Microsoft was right. Don't update your "old" computer to Windows 11
- **URL:** https://dariusz.wieckiewicz.org/en/microsoft-was-right-dont-update-to-windows-11/
- **Date:** 2022-02-15
- **Tags:** windows 11, windows 10, without TPM, TPM 2.0, Unsupported Hardware, old processor

### Content

Each of us would like to use the computer for as long as possible, so that the money invested in it would pay off in time. Therefore, a large number of people would also like to use the latest system from Microsoft, which is Windows 11.

Microsoft has introduced a certain barrier when it comes to what equipment will be able to freely run Windows 11.

<!--more-->

In addition to TPM 2.0, one of the requirements is a compatible processor, such as at least 8th (8th) generation Intel.

When Microsoft released Windows 11 for end users, in October 2021, I immediately started testing.

At first on a virtual machine on my Mac, then I switched to it at work on a computer that is not showing its age (Lenovo e530c from 2013).

I did it according to my post: [Upgrading Windows 10 to Windows 11 without TPM 2.0 on unsupported hardware](/en/upgrading-windows-10-to-windows-11-without-tpm-2-on-unsupported-hardware/) and I described my adventures with the system at work here: [Windows 11 on Unsupported Hardware - Day by Day](/en/windows-11-on-unsupported-hardware-day-by-day/) and here: [Windows 11 on Unsupported Hardware - Day by Day, Part 2](/en/windows-11-on-unsupported-hardware-day-by-day-part-2/).

This computer is not and will not be supported by Microsoft for Windows 11. Windows 10 is the system it should remain on until it is no longer supported – October 14, 2025.

After months of intensive work with the system, I can confirm that Microsoft was right. If according to the installer your computer is not supported by Windows 11, then you should take it to heart and stick with Windows 10.

Windows 10, after a multitude of major updates, has become a really good, stable system.

Windows 11 is sluggish. This is especially noticeable on older computers.

Despite the fact that my Lenovo is slightly tweaked with fast RAM and a fast SSD drive, you can still feel in your daily work that Windows 11 is torture for it.

Microsoft's forum is crackling with complaints from users, especially those who use OneDrive and SharePoint to share files with others on a daily basis.

> [Onedrive issues on Windows 11 - Microsoft Tech Community](https://techcommunity.microsoft.com/t5/windows-11/onedrive-issues-on-windows-11/m-p/2674325)

Personally, I use OneDrive and SharePoint at work, which is why the problem bothers me every day.

Working with files in the cloud is torture. Everything opens slowly. There are lags during synchronization, problems with navigating between folders. The problem is so serious that it affects the default file browser in Windows (File Explorer). To help with this, I installed the [Files](https://www.microsoft.com/en-us/p/files-modern-file-manager/9nghp3dx8hdx#activetab=pivot:overviewtab) application.

Unfortunately, this application itself requires significant computing power.

Over the past month, I have been forced to work with Files because File Explorer was driving me crazy to the point where I wanted to format my drive and reinstall Windows 10.

The latest Windows 11 updates (21H2, OS Build 22000.493) were intended to eliminate a number of inconveniences in the system. Unfortunately, in my case it did nothing, although a number of users confirm that everything is starting to work as it should.

However, it should be noted here that these are mainly users who have compatible hardware supported by Windows 11.

In general, Windows 11 is nice and there are no major problems with it. Personally, I feel that it is still an unfinished product.

Just as I remember Windows 10 becoming suitable for professional use with the second or third major update, Windows 11 still has to wait for that.

I even started writing a text entitled **‌# Is it time to update to Windows 11?**, which I kind of abandoned.

Microsoft is working hard to patch up all the pain points in the Tuesday system updates, but I still think the system was released in a hurry, just to get the hardware market going and let others make money.

It has nothing to do with what users want, what matters is money.

Everyone believed that Windows 10 was the last system we would have to install, and that half-yearly or yearly "big" updates would replace the main releases of the system.

However, this did not happen and Microsoft released Windows 11, cutting off a lot of devices from further circulation.

Recently, even in the UK, you could find a good sale on Microsoft Surface 4. The computer with a keyboard could be bought for less than £200. With the prices of the new Surface comparable to Apple computers, this is an incredible opportunity. There is only one problem. This equipment available in the "offer" is based on the 6th (6th) generation of Intel processors, so despite it being official equipment from Microsoft, you can forget about the official update to Windows 11.

However, if you decide to [update to Windows 11 on unsupported hardware](/en/upgrading-windows-10-to-windows-11-without-tpm-2-on-unsupported-hardware/), Microsoft itself will be putting obstacles in your way.

{{% ads-in-article %}}

First, forget about Microsoft's phone support, even if you're a business customer and you pay for it. By installing software on unsupported hardware, you're asking for problems (or so Microsoft believes). These are the problems that the support people won't be happy to solve, blaming us and our hardware.

Second, Microsoft will start throwing obstacles in our way, users who decided to update.

As reported by [OnMSFT](https://www.onmsft.com/news/microsoft-warnings-windows-11-unsupported-pcs), Microsoft will start displaying a warning in system settings that our hardware is not officially supported by Microsoft.

Just as Microsoft previously mentioned that Windows 11 will not receive updates on unsupported hardware (without explaining which updates it refers to), it will take small steps, starting with warnings, to limit the use of old hardware and tempt you to spend some money on new.

For now, Microsoft, in the Insider version of Windows 11 (soon in the consumer version), redirects the user from the warning to a page explaining the fact that they are using an operating system that should not be installed on them due to lack of compatibility.

Over time, Microsoft will certainly go a step further and introduce blockings (which will probably be possible to bypass as they have done so far) to limit this precedent.

If you have a computer that is officially supported by Windows 11, you can do so when you are notified that your update is ready to install.

However, if your hardware is not very old, no matter how powerful it is under Windows 10, I recommend that you wait with a manual update.

Personally, as soon as I have some free time at work, I am going back to Windows 10. In the meantime, I will be looking into upgrading my company hardware (including my computer) to Windows 11 in the future. For now, Windows 10 will once again be on my desk at work (while still using Windows 11 in my virtual environment).


---
## What is the best time to start blogging?
- **URL:** https://dariusz.wieckiewicz.org/en/what-is-the-best-time-to-start-blogging/
- **Date:** 2022-02-13
- **Tags:** blog, Anna, Anna Więckiewicz, blogging, creations, thoughts

### Content

If you're thinking about sharing some of your thoughts or creations with the wider public, one of the good things is to start your website - a blog for example.

Initially, you may think that social media could do the job, but think about social media as a tool to promote your creation, not as a primary place for it. Always back up your stuff with something that is yours.

A blog, where you own the content is yours, not somebody else. On social media you don't own stuff that you publish, social media companies did and they profit from it.

<!--more-->

Also, not everybody likes social media. I particularly lost the sense of using Facebook and found Twitter as my new home for social interaction. Despite sharing stuff there, I try to keep my work, my things and my thoughts under my control. This is why I got my blog (primary) [in Polish](/) and this [in English](/en/).

It is never too late to start blogging, but it is also never too early to do that either.

When I look into my childhood, where there were no computers at home, and the internet came a bit late I know that I lost plenty of my good creations.

When you are a kid, you create a lot of stuff. Same much as you create you destroy or throw away. 

Some of these creations could be worth keeping.

It's not possible to go back in time, but we can look forward, looking at our "creations"... our kids.

Our kids create magnificent things not even knowing about it. This is why it's worth it for us, as adults, to preserve it.

Some parents are doing that in the manner of "book" that they gave to their child when they finish 18 years old. That's one of the ways.

I decided to do this a bit different and worked with my daughter to create a website for her.

Website, a blog or a place that will show (and preserve) her journey through her creativity.

We worked on it for the last couple of months. Due to other life commitments, we did not manage to publish it as planned, when she finished 9 years old, but finally, we found a time for that.

Hope that this will allow her to stay creative and to share her views with wider recipients.

As for now, we work together, but I hope, when the time comes, she will be able to take it into her own hands.

> [https://anna.wieckiewicz.org](https://anna.wieckiewicz.org)

I lunched my private website in 2008. Even though I don't become much popular, I am happy with my creation and the number of visitors I am receiving. The visitors and positive feedback motivate me and assure, me that the content that I create is desired at least by some of them.

At least the knowledge that I put into it is not lost.

Our minds lose things every day. Also, some pieces of information are harder to find when we did not write them down. This is why I am primarily creating posts for myself as notes.

Plenty of times I am returning to them when I need to use some of the knowledge gathered there, so why not share it with others?

The numbers from website analytics show that there are people who appreciate the information I gathered here.

I live in England but I am primarily blogging [in Polish](/). There is plenty of information that can be found in other languages, but not all can access them. When I struggle to find something, I know, that others will struggle even more. This is why, with my website, I am trying to give a helping hand and share the knowledge.

This is also helping me to maintain the language.

Some people will not appreciate that I got a different view on things that others assume as "normal" when it is not. But that's how the society that we live in.

I hope, if you read a bit of my "creation", it's because you want it and not because you have been tricked into reading it by some "click bait" approach.

{{% ads-in-article %}}


---
## Captain`s Log, stardate 20220208, Planet M1
- **URL:** https://dariusz.wieckiewicz.org/en/captains-log-planet-m1/
- **Date:** 2022-02-08
- **Tags:** MacBook Air M1, Apple, MacBook Pro, MacBook Air, apple silicon, certified refurbished

### Content

I have been using my M1 MacBook Air since the end of July 2021, when I replaced my beefed MacBook Pro that I purchased over a year earlier.

It was some kind of a downgrade at the time. My MacBook Pro (2020) has twice the memory and twice of storage as my "basic" MacBook Air. Also, I purchased my MacBook Air refurbished directly from Apple.

Months are passing. We already got rumours of MacBooks with M2's to be released this year, but still, I look on my MacBook Air, and I can't believe how such a small thing like an M1 chip could do such a big shakeup on the market.

<!--more-->

When I looked in the past, I could hold with replacing my ageing MacBook Pro (Late-2013) at the time. Instead of buying a new MacBook a couple of months later, I will have something better.

But, thanks to that I see how powerful MacBooks with M1 chips are.

I saw a huge jump in speed when moved from Late-2013 to the 2020 MacBook Pro. That jump (not as massive as previous) also been maintained when I "downgraded" myself to MacBook Air.

I don't regret anything. The machine that travels daily with me is working hard to pay for its price.

When I used my MacBook Pro, with four Thunderbolt ports, I haven't felt the need for any additional adapters, dongles etc. With just two in MacBook Air, I have been a bit worried, but when it become my day-to-day companion I quickly noticed what I need to have with me and that two ports are a reasonable alternative.

My bag contains [fast external SSD drive](/en/forget-about-slow-memory-sticks-portable-hard-drives/), USB-C hub, USB-C to USB-A dongles, however, they are not in use as often as I thought they will be.

My use of the computer also changed. Utilising cloud storage for most of the tasks help with that a lot.

I feel however in a couple of instances that this device is missing the juice.

Rarely, but I am using some graphic software. This is where I saw the difference between 8GB RAM and 16GB RAM. The glitch, slow down or "the wheel of the dead" when the app stop responding for a couple of seconds remind me that I am on a device that would like to have much more under the hood.

Luckily, the speed of M1 is rectifying everything. Where Intel will still process the information for me, the M1, despite glitches, is already finished.

I may class myself as a Pro user, but this Air proves to me, that it's not very often I need this pro performance. It's not worth extra money.

The price jump between basic M1 and these beasts like M1 Max and Pro is huge now. 

Let's not kid ourselves. If I will need it, I will find a way to get it, but now I know that this extra performance would need to work for me to compensate for the price. 

This computer is used by me in my leisure time. Rarely for doing things for others, hence that's enough.

Looking for all this new tech I need constantly remind myself that I don't need to spend twice as much on hardware. The current one still got a lot to give and it's worth more, even when it's age.

I am looking forward to seeing what Apple will present this year. I am interested to see, how lame response will be from others when Apple will make another [leap forward](/en/leap-forward-apple-silicon/).

My first MacBook least for me 6 years. The longest time that I have had a single computer ever. Maybe this Air will not be in my hands for such a long period, especially if Apple charm me with good [trade-in experience](/en/leap-forward-apple-silicon/#trade-in-experience), but at east, I got a couple of years with the really good device.

{{% ads-in-article %}}


---
## You have been watched...
- **URL:** https://dariusz.wieckiewicz.org/en/you-have-been-watched/
- **Date:** 2022-02-05
- **Tags:** you have been watched, Person of Interest, government, secret system, spies, machine, No Place To Hide

### Content

> "You are being watched. The government has a secret system, a machine that spies on you every hour of every day."

That's how the TV Series Person of Interest used to start in the past.

Since the last series was aired in 2016 past couple of interesting years. This TV fiction shows how abuse of power could lead to invigilation of the world citizens.

The problem starts when the fiction starts becoming reality, and we do not even know about it.

<!--more-->

It is not something new that governments are gathering information about their citizens, most of the time without their knowledge, approval and with full violation of their right to privacy (especially that they are "irrelevant").

This is why, in recent years, more and more companies are trying to put encryption and restriction in ways, how their users, citizens, people, can be spied on every day.

It was not a surprise when at the beginning of January 2022 [The Guardian highlighted an article about Europol](https://www.theguardian.com/world/2022/jan/10/a-data-black-hole-europol-ordered-to-delete-vast-store-of-personal-data), who had been caught redhanded on the processing of data of innocent people violating international laws.

And what a pathetic explanation it was and what they said about it. You can easily call it like in Person of Interest, that they created "a machine", an AI that spies on us every hour of every day.

> "The confrontation pits the EU data protection watchdog against a powerful security agency being primed to become the centre of machine learning and AI in policing."

This reminds me of one episode from Person of Interest, when, on purpose or not, the government machine has been exposed. This is where all involved people tried to wash their hands and cut the ties as much as possible so nobody can come after them. What worries me is that to avoid chasing them, they will probably subcontract the machine, and this unlawful activity will continue (if somebody will ask, they will say that they don't know anything about it). It's like in Person of Interest when a machine called Samaritain takes over the limited role of the first creation.

Let's don't think that this will not happen. All secret services rely on data about people. Social networks are just one of the multiple sources of free information used to target people and build profiles about them.

Not a surprise, that governments are starting to worry about encryption, lack of hardware back doors, and all this software in use that they cannot listen to. 

Some companies like [Barnardow](https://www.barnardos.org.uk/) (without undermining their activity to protect against child sexual abuse) put a campaign [#NoPlaceToHide](https://twitter.com/barnardos/status/1483384708541173760?s=21), that has been founded by the UK Government undermining the end-to-end encryption. 

Looking at that, some people will start saying that end-to-end encryption is used only by criminals and child abusers!

The UK Government was thinking, we when we left the block, we became another North Korea. We don't. 

This government forgets that it is elected by people and that people will have a say about their future. At least until we still can.

Blaming encryption under the stance "you using it, so you probably have something to hide" is total nonsense, but that's how they're trying to play.

> See [Privacy is for paedophiles, the UK government seems to be saying while spending £500k demonising online chat encryption](https://www.theregister.com/2022/01/20/no_place_hide_campaign_anti_e2ee_ukgov/) at [@TheRegister](https://twitter.com/TheRegister).

Privacy and encryption is protecting innocent people around the world against regimes and far-right governments. The far-right government that the UK-one is slowly starting to become. Where free speech is so important, there are powerful people with a lot of influence and money, the money that they can use how they like (lawfully or not). This is why they want to protect their interest pretending that they are trying to protect innocent people.

Pretending that they care about child victims, they will invigilate all people who think differently to them. They will go after all powerful people who cannot be bought, so they will have information on them, and use them when there will be time to do so.

Our surveillance happening all the time. The rich and powerful are raising their voices when somebody is trying to cut their abilities to spy on us. Like Google who is [shouting against their common practice of "surveillance advertising" and people who are trying to put a stop to it](https://searchengineland.com/banning-surveillance-advertising-act-marketers-respond-378706). It's all about money, big money. They don't care about our privacy, our freedom of speech, they only care about their money!

End-to-end encryption has been with us for some time and still special services and police forces can find all these perpetrators. It is harder these days, as the technology is going forward, but they shall also work harder to achieved the result, to which they have been created in the first place. Not to make an innocent person a criminal.

Let's stop pretending that every citizen is a potential criminal and everybody got something to hide. That's right, everybody got something that wants to stay private. As long as it's according to law, then you shall not be flagged each time you create a new profile on a new website on the Internet.

There are always two sides of the coin.

These powerful, on high places, forget that there is always bigger fish in the pond. 

I would appreciate it, if they will look at themselves from time to time and see how they are breaking the law, before chasing others for doing that same. These other people may not have friends billionaires who can save their asses when needed.

The UK Government is so lamely doing a smokescreen by saying that they want to protect children [that even UK data watchdog got enough](https://www.theguardian.com/technology/2022/jan/21/end-to-end-encryption-protects-children-says-uk-information-watchdog).

Luckily there are still some people in high places that understand the value of privacy.

> "ICO (...) said strongly encrypting communications strengthen online safety for children by reducing their exposure to threats (...)"

I am a father and I got kids that I want to protect, but that doesn't mean I don't want to feel safe. I don't want to worry that each time I will say something, something that can be not what other party likes, I will be listened to and somebody will try to "correct me".

Undermining the value of people privacy is an attack on people.

Sadly, there is no law yet that will put a stop to this.

{{% ads-in-article %}}


---
## Connecting UPS Battery Backup to Router with OpenWrt
- **URL:** https://dariusz.wieckiewicz.org/en/connecting-ups-battery-backup-to-router-openwrt/
- **Date:** 2022-02-05
- **Tags:** OpenWrt, Battery Backup, UPS, uninterruptible power supply, APC Back-UPS 1400, Back-UPS XS 1400U, PowerChute, PowerChute Personal Edition, apcusbd, collectd, luci-app-statistics, RRDTool

### Content

Recently I decided to connect an UPS (uninterruptible power supply) at work to one of the devices that runs 24 hours a day. The UPS that we currently have is the APC Back-UPS 1400 (Back-UPS XS 1400U), in addition to the ability to connect up to 6 devices, allows you to monitor the status of the device using the PowerChute software via USB port.

The problem is that this software is not compatible with the server we use, since it is available in a version for personal use (Personal Edition).

So I decided to use one free port (we use another one for [additional internet connection using a 4G router](/en/adding-second-internet-connection-router-openwrt/)) to connect a UPS to it to monitor its status (this device does not have a display apart from two diodes). If we can do something more, it would be even better, but it all depends on what can be achieved using OpenWrt.

<!--more-->

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

## Initial Device Detection

Let's start by seeing how our UPS is detected when connected to our router.

We connect our UPS and from terminal we execute the command `dmesg`

In my case I got the following entry:

```
usb 1-1: new low-speed USB device number 3 using orion-ehci
```

As we can see, my device is detected as a slow USB device and the driver that supports it is `orion-ehci`.

## Proper Device Detection

First, we update the packages in the system and install the `usbutils` package

```bash
apk update
apk add usbutils
```

We check if our UPS is correctly detected using `lsusb`

```bash
Bus 001 Device 003: ID 051d:0002 American Power Conversion Back-UPS XS 1400U  FW:926.T2 .I USB FW:T2
```

## UPS Status Monitoring

We install the `apcusbd` package (and accompanying packages):

```bash
apk add apcupsd collectd-mod-apcups kmod-usb-hid
```

After disconnecting and connecting the USB cable, my UPS is detected (`lsusb`) as follows:

```bash
usb 1-1: USB disconnect, device number 5
usb 1-1: new low-speed USB device number 6 using orion-ehci
hid-generic 0003:051D:0002.0003: hiddev96,hidraw0: USB HID v1.10 Device [American Power Conversion Back-UPS XS 1400U  FW:926.T2 .I USB FW:T2 ] on usb-f1058000.usb-1/input0
```

In the configuration file `/etc/apcupsd/apcupsd.conf` I made the following changes:

```bash
UPSNAME ups1
UPSCABLE usb
#UPSTYPE apcsmart
UPSTYPE usb
#DEVICE /dev/ttyS0
```

> Notice the commented (#) lines like DEVICE

We run it using:

```bash
 /etc/init.d/apcupsd start
```

Then executing the `apcaccess` command we should get the following response:

```bash
APC      : 001,036,0873
DATE     : 2022-02-04 12:28:51 +0000
HOSTNAME : WRT3200ACM
VERSION  : 3.14.14 (31 May 2016) unknown
UPSNAME  : ups1
CABLE    : USB Cable
DRIVER   : USB UPS Driver
UPSMODE  : Stand Alone
STARTTIME: 2022-02-04 12:28:47 +0000
MODEL    : Back-UPS XS 1400U
STATUS   : ONLINE
LINEV    : 228.0 Volts
LOADPCT  : 22.0 Percent
BCHARGE  : 100.0 Percent
TIMELEFT : 26.5 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME  : 0 Seconds
SENSE    : Medium
LOTRANS  : 160.0 Volts
HITRANS  : 280.0 Volts
ALARMDEL : No alarm
BATTV    : 27.1 Volts
LASTXFER : Automatic or explicit self test
NUMXFERS : 0
TONBATT  : 0 Seconds
CUMONBATT: 0 Seconds
XOFFBATT : N/A
SELFTEST : NO
STATFLAG : 0x05000008
SERIALNO : xxxxxxxxxxxx
BATTDATE : 2021-12-16
NOMINV   : 230 Volts
NOMBATTV : 24.0 Volts
NOMPOWER : 700 Watts
FIRMWARE : 926.T2 .I USB FW:T2
END APC  : 2022-02-04 12:28:52 +0000
```

As you can see from the `STATUS: ONLINE` field the connection was successful.

If, however, we see `STATUS: COMMLOST`, then our UPS was not detected or the connection is not working.

## Status Monitoring from the OpenWrt Admin Panel

We install the statistics collection package:

```bash
apk add luci-app-statistics
```

> This command will additionally install the packages `librrd1`, `rrdtool1`, `collectd-mod-rrdtool`, `collectd-mod-iwinfo`, `collectd-mod-cpu`, `collectd-mod-memory`, `collectd-mod -interface`, `collectd-mod-load`, `collectd-mod-network`.

{{% ads-in-article %}}

After going to the administration panel of our router, we will see a new `Statistic` option.

When you run it for the first time and go to the `Graphs` tab, you will be informed that the part responsible for collecting data has not been configured.

[![No RRD data found](OpenWrt_APC_UPS-No_RRD_data_found.png)](OpenWrt_APC_UPS-No_RRD_data_found.png)

We will then be redirected to the `Setup` part where we are actually interested in the `General plugins` tab where we need to **check** `APC` (confirm the default settings - Save), and then **Save & Apply** the changes.

{{% gallery %}}
[![Collectd Settings](OpenWrt_APC_UPS-Collectd_settings.png)](OpenWrt_APC_UPS-Collectd_settings.png)
[![Collectd Settings - General Plugins](OpenWrt_APC_UPS-Collectd_settings-General-plugins.png)](OpenWrt_APC_UPS-Collectd_settings-General-plugins.png)
{{% /gallery %}}

[![APCUPS Plugin Configuration](OpenWrt_APC_UPS-APCUPS_plugin_configuration.png)](OpenWrt_APC_UPS-APCUPS_plugin_configuration.png)

Now, going back to the `Graphs` section we should see our UPS which will fill our graphs over time.

{{% gallery %}}
[![APC UPS Statistics - Part 1](OpenWrt_APC_UPS-Statistics_APC_UPS_Part_1.png)](OpenWrt_APC_UPS-Statistics_APC_UPS_Part_1.png)
[![APC UPS Statistics - Part 2](OpenWrt_APC_UPS-Statistics_APC_UPS_Part_2.png)](OpenWrt_APC_UPS-Statistics_APC_UPS_Part_2.png)
{{% /gallery %}}

Here it should be noted that the collected statistics are saved by default in the device memory and are lost after the device is restarted. If we want to change this, in the `Setup` section, `Output plugins` tab, we configure `RRDTool` and change the location in the `Storage directory`.

{{% gallery %}}
[![Collectd Settings - Output Plugins](OpenWrt_APC_UPS-Collectd_settings-Output-plugins.png)](OpenWrt_APC_UPS-Collectd_settings-Output-plugins.png)
[![RRDTool Plugin Configuration](OpenWrt_APC_UPS-RRDTool_plugin_configuration.png)](OpenWrt_APC_UPS-RRDTool_plugin_configuration.png)
{{% /gallery %}}

And this way we have UPS connected to our router, and we can monitor its status from a web browser.

---

Now it would be useful to do a little more, such as safely turning off the router or other devices connected to it if the battery level gets very low.

For this purpose, I became interested in the [NUT](https://networkupstools.org/) (Network UPS Tools) package, which theoretically will allow you to monitor the status of the UPS (which we have connected via USB cable to our router) from the level of devices in the network. When the software detects a drop in power and at the appropriate battery level, it will react by executing a specific command.

It all sounds great, because you can install it on another computer (server) that is protected by our power supply, and even though the power supply is not directly connected to it, react appropriately depending on the situation based on data from the program.

**But that's fun for another time.**

If you want to try your hand at NUT, I refer you to: [Monitoring UPS status with NUT(Network UPS Tools) on OpenWrt – Linux Man (linux-man.org)](https://linux-man.org/2021/09/28/monitoring-ups-status-with-nutnetwork-ups-tools-on-openwrt/).

Best regards.


---
## Windows Defender – The "Only" Antivirus You Need for Everyday Use
- **URL:** https://dariusz.wieckiewicz.org/en/windows-defender-antivirus-for-everyday-use/
- **Date:** 2022-02-04
- **Tags:** windows defender, antivirus, windows 10, windows 11, microsoft, av-test

### Content

In September 2018, I wrote a few words about [Windows Defender, as my default antivirus for Windows 10](/en/my-antivirus-windows-defender/). It's been a few years since I've used it at work (as well as the rest of the people in the company). I recommend Microsoft's default solution built into Windows 10/11 to anyone I help with their computer.

So I decided to check if Windows Defender is still a solution worth recommending. After all, it's free, and you have to pay for all the others, so what's the catch?

<!--more-->

My opinion of Microsoft has changed drastically over the years. Since Satya Nadella took over as CEO in 2014 and after Bill Gates officially left the company (2020), it's safe to say we're dealing with a completely different company.

> Not to mention Windows 11 itself, which I think was released too soon, just to jumpstart the PC market in an era dominated by Macs with their own chips. Windows 11 is unfortunately an unfinished system. For businesses, as well as individuals, staying with Windows 10 is highly recommended (unless their computer automatically updates), at least until the "big" update is released this year (2022).

Microsoft solutions, although some are paid, are becoming a sensible choice for everyday use. Those that are available for free are causing confusion on the market.

Companies such as Avast, McAfee or Symantec (Norton) have to try harder to sell their software, especially since the built-in, free ones from Microsoft meet the requirements of most users.

The same is true for Google, which at all costs does not want to give up the ability to track users without a fight, promoting Google Chrome with all its might, while we have Edge (based on Chromium), which is available and lacks nothing.

Microsoft can boast (and users can breathe a sigh of relief) the free Windows Defender, which [once again scored the highest score in the AV-TEST antivirus software test](https://www.av-test.org/en/antivirus/home-windows/windows-10/december-2021/).

Interestingly, solutions such as Avast, Bitdefender or Malwarebyte cannot boast the highest score in each category.

Personally, both I and my colleagues have not experienced a single mishap for years, and Windows Defender did its job and blocked everything that could cause these losses.

I remember those days when the whole world started fighting against Microsoft's dominance, especially when it comes to the para-browser, which was Internet Explorer.

While the whole fight was justified then, this time Microsoft delivered a high-quality product that is hard to abandon based on just a few arguments.

Microsoft will continue to use its dominance on the market, promoting its solutions. This time, however, users of its software, not investors, have and will have the feeling that they are getting something that is worth its price, even if it is a free solution.

Microsoft also wants its solutions not to sink their efforts in creating services and software.

In the past, it was the lack of any protection from the operating system that caused viruses to be introduced already at the stage of installing the operating system.

I still remember installing Windows XP and after connecting it to the Internet for the first time, installing an antivirus, I was informed that the system was "already" infected.

Regardless of whether we intend to stick with Windows Defender or our employer forces us to use another solution, our system is now much more secure than it was years ago.

For home users, it is a solution that does not need to be replaced.

The idea behind Windows Defender was basic system protection, which over time has grown into a solution that will satisfy most users, providing them with peace of mind, even from one type of threat.

It is a pity that another market leader, Apple, has not introduced this type of basic solution to its operating system.

Although the number of threats to the system with a bitten apple is much lower than for Windows, it is growing very quickly, along with the popularity of Mac computers.

Interestingly, for selected business customers, Microsoft provides Microsoft Defender for Mac computers.

Microsoft's appreciation of other operating systems and investing in the development of their software on them is something that seemed unrealistic over a decade ago, but it is.

Microsoft's solutions (proprietary or purchased, such as GitHub) change the approach to what (what software) we need to install additionally on our computer.

We needed Chrome to browse the internet, now we just need to stay on Edge based on Chromium.

For virus protection we usually installed Avast, now Windows Defender is all we need.

Even the software available by default for playing movies slightly pushes the need to install programs like VLC.

7Zip is still something that has not been defeated by Microsoft's built-in tools, but I wouldn't be surprised if Microsoft doesn't go down this path and expand its portfolio with this type of solution.

Best regards.

{{% ads-in-article %}}


---
## The squirrel ate my peanuts and left the shells on my hard drive
- **URL:** https://dariusz.wieckiewicz.org/en/the-squirrel-ate-my-peanuts/
- **Date:** 2022-01-10
- **Tags:** cleanmgr.exe, squirrel, squirreltemp, windows 10, windows 11, Atom, Command prompt, Disk Clean-up

### Content

Half jokingly, half seriously. I recently discovered what was eating up my disk space on my work computer.

<!--more-->

From the moment I upgraded from Windows 10 to Windows 11 at work, as part of testing (but also in Windows 10), I noticed that I was losing disk space day by day.

This computer is only equipped with a 128GB SSD (primary) but I always had some free space on it and I never saw the red horror bar.

At first I thought it was all because of upgrading to Windows 11, but no. As this hardware was not for Windows 11, I reverted to Windows 10 and ran into the same problem.

By doing standard cleanups, I freed up a fair amount of unnecessary data (20+ GB). A few weeks passed and the horror bar returned.

By repeating the purge, I only gained a few hundred megabytes, up to one gig at most, so what was eating up my space?

I started searching, uninstalling programs, flipping through files, until I started to analyze the `AppData` folder in my profile (hidden by default), where I noticed that it takes up significantly more space than my colleagues at work.

Again, I thought it was all related to Windows 11, but no, since I experienced this on Windows 10 as well.

The rodent that settled on my drive and made it a granary for the winter was [**Squirrel**](https://github.com/Squirrel).

I found her granary full of useless peanut shells (`TempXX`) that took up over **40GB!!!**

Interestingly, the granaries on other computers were not so full. Apparently, my squirrel was really hardworking and ate my gigabytes at large.

This granary is called `SquirrelTemp` and although it is not necessary for everyday use, it is not included by default in Windows Disk Clean-up.

But from the beginning.

**Let's get to know my squirrel, because she hasn't introduced itself**.

On GitHub, this squirrel is described as `Server-driven updates for native apps`.

Well, Squirrel is a kind of engine that can be integrated with any application in order to update it more easily.

Just as Microsoft Edge and Chrome update in the background, other applications not necessarily. Here a squirrel comes to the rescue.

Curious rodent. I just don't remember what he uses it for or why.

Well, Squirrel is used, among others, Brave, Slack, Atom, as well as Microsoft Teams.

Of these apps, some I don't use, but I used the Atom app a few months ago. Everyone in the company uses Microsoft Teams, so I'm not betting that it is causing the granary to overflow.

Before I started using [Microsoft Virtual Studio Code](https://code.visualstudio.com), I was actively using [Atom](https://atom.io). I appreciated it, among other things, thanks to friendly updates.

When launching the app, it updated in the background, and the next time it was launched, it updated to the latest version. 

Unfortunately, these updates to the app are not small. Each of approximately 210+ MB. Four updates and we used 1GB on the hard drive.

> From what I've read from other friends of pseudo-flying animals, it can store up to 160 GB!

{{% ads-in-article %}}

On an incorrect assumption, I thought that downloaded files were saved in the `Temp` folder, where you would expect it in Windows, but no. For this purpose (this and other applications) the `SquirrelTemp` folder is used.

Unfortunately, unless we use other cleaning programs and use only the tools built into the system (which are sufficient in most cases), we will not notice that over the months (years) some gigabytes have accumulated there, until our system announces that it is time to do spring cleaning. The worst thing is that the system does not know where and what to delete, so we have to do it ourselves.

> Removing 40GB of thousands of tiny files on my (mid-range) SSD took about 5 minutes.

We will not get rid of the rodent itself.

While I gave up Atom, there are still other programs that have become friends with it, and which I do not want to give up. Therefore, I decided to prepare a handy command, which I will run once in a year to get rid of garbage.

We execute the following command from the command line (Command prompt):
```
rmdir /s %UserProfile%\AppData\Local\SquirrelTemp
```

If you don't like fiddling with the command line, you can delete the `SquirrelTemp` folder from File Explorer after the hidden folders are displayed.

[![Windows 11 Show Hidden Items](windows_11_show_hidden_items.png)](windows_11_show_hidden_items.png)

Right-click, select delete, and then empty the trash.

> Like I said before, it took a while from the command line. From within the file explorer, it may take a bit longer.

Our folder is located on the system drive, in the user folder, `AppData` > `Local` > `SquirrelTemp`.

The squirrel is whole, the granary is still available, and you won't have to evict her to her new home.

Regards.


---
## Freeing up space on Google Photos
- **URL:** https://dariusz.wieckiewicz.org/en/freeing-up-space-on-google-photos/
- **Date:** 2022-01-05
- **Tags:** Google Photos, Google, Storage Saver, Manage Storage, Recover storage, Compress existing photos and videos

### Content

Sooner rather than later the time has come when another person asks me what to do when they are running out of space on Google Photos and therefore on Gmail.

<!--more-->

Well, according to Google's announcements, from June 2021, all photos uploaded to Google Photos are included in the space we have at our disposal (by default 15GB).

> Pisałem o tym tutaj: > I wrote about it here: [No more free storage on Google Photos](/en/no-more-free-storage-on-google-photos/).

In November 2020, after the changes were announced, Google estimated that *"80% of users will be able to store up to 3 years of photos within 15GB without having to purchase a larger package"*. All provided that we store them in a compressed version, currently called **Storage saver**.

Of course, I already knew this was a very optimistic assumption. As you can see, some users started approaching the limit after more than six months. I'm referring to users I know who have the basic 15GB plan, as well as those who have purchased the additional 100GB.

In its assumption, Google deliberately took into account the current (at the moment) market situation. Over time, however, our cameras take photos in increasingly higher resolution, which means that they take up more and more space.

> If we also take *Live Photos* photos, a short video is saved in addition to the photo, and so one photo and one video are on average 3MB!

Despite the fact that we have set all photos to be uploaded (and stored) in compressed form by default, sometimes this does not happen.

If we have recently set up a new phone or installed the Google Photos application from scratch, to our surprise we may notice that **by default photos were saved in full resolution**, which means our space disappears in the blink of an eye.

Each photo taken is about 4-5MB. The holiday season is behind us and it is enough that we took over 100 photos during it and we no longer have almost half a gig of disk space.

Google did this somewhat intentionally. Every time we change phones or log in to Google Photos, we have to remember to switch to **Storage saver** so we don't one day be surprised that we run out of space.

[![100GB Google storage deal](100GB_Google_storage_deal_en.png)](100GB_Google_storage_deal_en.png)

However, before you decide to reach into your wallet to purchase an additional, higher package, it is worth performing a simple procedure in the Google Photos options to check whether we can free up some space by compressing what is already uploaded there.

[![200GB Google storage deal](200GB_Google_storage_deal_en.png)](200GB_Google_storage_deal_en.png)

Personally, my current package is 200GB, [shared within a family group](https://myaccount.google.com/people-and-sharing), where all members have this space at their disposal and I only pay once, and despite all the efforts, my usage is over 50%.

> Recently, on one account, I went from a full Google account to over 15GB using this method to gain 12GB of free space!

{{% ads-in-article %}}

## Size of uploaded photos and videos

From our computer, go to the [Google Photos Settings](https://photos.google.com/settings).

If we do not have the **Storage Saver** option checked, we make a change.

[![Google Photos - Settings - Storage saver](Google_Photos_Settings_Storage_Saver.png "Google Photos - Settings - Storage saver")
](Google_Photos_Settings_Storage_Saver.png)

Then click on the **Manage Storage** button.

[![Data storage - Personal estimate](Storage_Personal_estimate.png "Data storage - Personal estimate")](Storage_Personal_estimate.png)

On the next page, we will get information about how and where we are using our disk space, along with an estimate of how long the space will last.

Scroll down the page until we see the **Recover storage** section.

[![Storage Management - Recover storage](Recover_storage.png "Storage Management - Recover storage")](Recover_storage.png)

Here we need to click on the text **Learn more**, after which we will receive information about what this option does, and after checking the box next to the text _I understand_, we will activate the **Compress existing photos and videos** button.

[![Compress existing photos and videos](Compress_existing_photos_and_videos.png "Compress existing photos and videos")](Compress_existing_photos_and_videos.png)

Thanks to this, all photos that were uploaded in **Original quality** will be compressed, and all those that can be optimized will also be passed through the algorithm.

[![Recover Storage – Compressing](Recover_storage___Compressing.png)](Recover_storage___Compressing.png)

This procedure may take a while. While the compression is in progress, we will see the text **Compressing... it may take a few hours**.

We can leave this page and return to it later.

By noting how much data we had at the beginning, we can later compare how much space we have regained with this procedure.

If the above procedure did not help, we still do not have much free space, then it is worth considering a higher package.

While deleting unnecessary photos is not a great solution, it is also worth seeing what else is eating up our valuable space.

> Remember, deleting photos uploaded to Google Photos before June 2021 won't restore any storage space, as they don't count toward your available storage, so there's no point in deleting them. Additionally, when you delete photos, you'll be informed how much space you're restoring.

It is worth noting here that the space on your Google account is divided not only between photos, but also between Google mail and Google Drive. Sometimes it is worth deleting old, unnecessary emails with attachments to recover valuable gigabytes.

Detailed information on how much space we have available and what is using it can be found on the [Google storage management](https://one.google.com/storage) page.

Best regards.


---
## Andrews Fasteners going Hugo!
- **URL:** https://dariusz.wieckiewicz.org/en/andrews-fasteners-going-hugo/
- **Date:** 2021-11-13
- **Tags:** Andrews Fasteners, Hugo, Netlify, SSG, WordPress, 404, Error 404

### Content

I decided to move yet another website from WordPress to [Hugo](https://gohugo.io). This time the website has much more traffic than any other "of mines" (the ones that I am managing).

The main reason was speed (but also recent discussion about the environment and impact of technologies on it).

<!--more-->

Speed was always the main goal of this website. Even that I made a lot of optimisation on it, including [migrating to SiteGround](/en/migrating-business-site-from-namesco-to-siteground/) (which helped a lot!), I still struggle to put the website on Green in Google Search Console - Core Vitals, which annoys me a lot!

So much good optimisation works, but Google still does not see that, despite that Lighthouse analysis showing a different picture.

I will not blame WordPress, however it is partly its fault.

---

Apart from speed, I think a lot about what impact this website has on the environment. The need for powerful servers to serve it just adds up to all the harm that we are doing to the environment. 

Fast websites load quickly and reduce the amount of energy that is needed to display them. But that's only half of the story. This is why I went back to basics and decided to go static with Hugo.

More about this you can read on the company official news post: [Andrews Fasteners Limited website going green!](https://www.andrewsfasteners.uk/news/andrews-fasteners-website-going-green/)

---

The other reason why I decided to resign from WordPress was security and stability.

Each update of WordPress, WooCommerce and other plugins causes me extra validation work to see if nothing is broken. I don't have time for that when I need to concentrate on my main job as a Quality Manager.

I proved myself, by migrating other websites, that going static is a good solution.

It involves a lot of work in the beginning (it took me a month of intensive work to finally push it live), but it pays off later on, especially on the security aspect. No WordPress, no risk of hacking using known vulnerabilities, especially in light of recent discoveries.

The whole job wasn't straightforward. I need to think upfront about what's currently on the website and see how to replicate things on a static site. Just before I even started my Hugo project I spend weeks gathering all the information on how to achieve what is currently in WordPress version.

I worked with this website since it was redeveloped by a third party back in late 2014/beginning of 2015 and since then I modified it a lot. Because of my significant input move into static wasn't as much pain as it could be (in theory).

Apart from content and layout (theme), which is easy to move, there were others, more dynamic things like:

- Contact and Enquiry forms;
- Calculators used by our customers to help them select the right product for their construction;
- Search
- CMS to add the ability for editing of the content by people without coding skills;
- Online Shop (eCommerce).

Before I started any work, the only one point from the above concerned me a bit - eCommerce.

---

The eCommerce part of the website (shop) was based on WooCommerce and payment gate offered by SquareUp (previously used PayPal, but SquareUp is much more cost-effective in a long term).

I didn't want to introduce another payment processing company like SnipCart, which already provides a guide on their website, how to build a static site with a dynamic payment page. I would like to use what we already use, so I need to reach out to the SquareUp API (before I discover another way).

The last thing that I got in my head was to reduce costs related to the website. I didn't want to go free, even though this could be achieved, but I don't mind paying a portion when traffic grows and customers flow. Overall, our website has between 5,000 and 6,500 unique user visits in a month which is not bad.

> Of course, up to 50% of this traffic are bots and people trying to hack our website rather than find a piece of useful information on it. After migrating into a static environment I expect to see a significant drop in numbers, especially after a couple of months, when WordPress parts will not be longer indexed in Google and other search engines.

Let's see, how this all goes...

> The site goes fully live on Friday evening, 12 November 2021.

## Calculators

I started with calculators that I created using simple HTML forms with minimum user input backed by calculation using formulas in PHP.

The calculators have been very useful not only for our customers but also for our sales staff. They have been able, with its support, to correctly advise customers about what products they need.

To be able to use them on a static site, I will need to migrate them into Vanilla JavaScript which wasn't a big problem for me. Once I sort new code on one day, I finish next day and they were placed on the website (still in WordPress) to see how they worked.

On PHP-based calculators data entered into the form has been sent to the server to be calculated on page refresh. This was not necessary but yet worked well. Using Vanilla JavaScript all data stayed local, no need to send anything to the server and no need to refresh the page to get a result.

In case somebody has been concerned about the privacy of the data entered, this issue has been closed once and for all.

Once I got my calculators served from ordinary HTML files, it was easy to implement them later on using Hugo Shortcuts. 

What's more important, once users will not see a big difference, they will feel it in speed and the whole experience when using them.

- [x] - Job done.

## Contact forms

Before I jumped into "easy" commercial solutions with contact forms and will start paying cash for their service, I decided to give it a try of form solution provided by Netlify. The site originally will be hosted by Netlify CDN hence why not?

Netlify Forms provide free of charge forms integration into your website. 

In the free tier, you receive 100 approved submissions (excluding spam etc.) per month and if you need more, then you need to pay for that.

I have calculated over the last months how many filled forms we received from our WordPress (mainly our customers sending emails or giving us a call) page and think 100 will be more than enough, at least in the beginning.

- [x] - Another job done.

## eCommerce

The biggest struggle for me, as natively I am not a developer (more self-taught geek), was migrating from WooCommerce (user-friendly interface) into static equivalent with dynamic content using Vanilla JavaScript, JSON and API. Something, that I haven't had much experience with, but would like to try.

However, with such a solution, I am gaining control on the one hand, but adding extra work to make sure it's working daily. All payment APIs are changing from time to time and this will need to change with it as well. 

This time I decided to take a different approach and use what our current payment provided (Square) is already providing - their [equivalent of WooCommerce](https://squareup.com/gb/en/ecommerce).

In such a way, I have been able to move a shop to them. 

One part of the website will stay dynamic with the need for server behind, but the aspect on security and making sure it's working well will be pushed into somebody else's head. One less trouble for me.

The job wasn't easy as involved a lot of labour. In this instance, I take an opportunity to review all the products and update prices so it wasn't wasted time. 

- [x] - Another point to tick off

## Search Form

Even on my static website, I haven't sorted out a full search facility. 

I have been thinking about that a bit but in the end, I decided to go into using someone else to do the job for me. Who will do this job better than... **not** Google. 

I decided to use a search engine that respects the privacy of its uses, so I stick with DuckDuckGo.

The number of information indexed in DuckDuckGo about this particular website was already impressive. As, when finished migration, I maintained most of the important links to the content, I avoided too many 404 errors.

Maybe in the future, I will decide to integrate some different approaches, like this: [In-Page Filtered Search With Vanilla JavaScript](https://css-tricks.com/in-page-filtered-search-with-vanilla-javascript/). For now, I ticked off this from my list.

> After some feedback from users, I implemented search natively in Hugo using JavaScript as per post [A simple javascript based full text search function](https://discourse.gohugo.io/t/a-simple-javascript-based-full-text-search-function/29119) in Hugo community. Now everybody is happy and can call this done!

- [x] - Done!

## CMS

The reason behind the popularity of WordPress is a fact, that if you knew how to use Word or any other text processing software (like Pages on macOS), then you knew how to add and edit content in a user-friendly editor right from your web browser.

I was in this migration project a bit forward-thinking, where I don't need to. 

I want to be sure, that if somebody in the company would like to add something to the website, they will be able to do this easily without teaching them again how to do this and that. But, as I have been mainly responsible for publishing content of the website (with the cooperation of others who advise the content and helped to make it "readable") it was not necessary to concentrate on that solution only for one person - me.

As the content of the website is provided in widely readable Markdown format, this can be edited in any compatible app. I can send a markdown file for correction and get it back without the need of introducing something new, something that I will need to explain how to use.

At the end (or rather at the beginning) when I finished building the site with Hugo, I decided to do not to look into that.

However, when the need will come, I got an open option to try and implement into the site. That's [Netlify CMS](https://www.netlifycms.org) and it's integrating nicely with Hugo.

[Netlify](https://www.netlify.com) is not only serving our website, they can do a lot more. Overall if you will look at their website you will hardly say that this is a place where you can publish a website, but more likely an app or more complicated project.

They are developing quickly, but competition as well. 

It will take some time before I will see the need for CMS so why waste my precious time? That leads me to the end.

- [x] - "done".

---

{{% ads-in-article %}}

Here is a comparison between **WordPress** and **Hugo** after finishing the migration process.

| Summary | WordPress | Hugo |
| - | - | - |
| Plugins | 168.4 MB | 0 MB |
| Theme | 6.8 MB | 0.61 MB |
| Content | 0 MB[^1] | 0.49 MB |
| Uploads | 952.2 MB | 133.8 MB |
| Other | 55.6 MB | 94.4 MB |
| Database | 31.30 MB | 0 MB[^2] |
| Hosting cost | £239.88 (sitegroung.co.uk) | £0 (zero, GitHub/Netlify) |

A fully loaded website, according to Waterfall in GT Metrix, took 1.1MB of data with WordPress whereas with Hugo it's only 35% of that!

[^1]: Content is stored in a database.
[^2]: Hugo does not store content in the database but markdown files.



---
## Windows 11 on Unsupported Hardware - Day by Day, Part 2
- **URL:** https://dariusz.wieckiewicz.org/en/windows-11-on-unsupported-hardware-day-by-day-part-2/
- **Date:** 2021-10-22
- **Tags:** Windows 11, Unsupported Hardware, file explorer, slow file explorer, OneDrive

### Content

Continuing my previous post ["Windows 11 on Unsupported Hardware - Day by Day](/en/windows-11-on-unsupported-hardware-day-by-day/) it's time for further considerations.

Overall, Windows 11 is not bad. Everything is going in the right direction, but it's not yet time for a mass switch, and here's why.

<!--more-->

## Another day with Windows 11 at work (Friday, 10/22/2021)

After the changes I made in the previous post regarding the context menu and the appearance of the file browser (File Explorer), I was still annoyed by the slow operation of the system when working with files in the OneDrive cloud.

Removing OneDrive and reinstalling it made the file browser work again as it should. Unfortunately, it didn't last long, because as soon as a large part of the files started to synchronize, everything started to slow down. You can't work like that.

> I am currently using OneDrive version 21.196.0921.0007. I have also tried the Inside version, but I do not see any difference, because the main error is in the system itself, not directly in OneDrive.

There is nothing else to do but wait for the update.

And about the updates. Despite the unsupported hardware, they appear as they should. I suspect that Microsoft's fearmongering about the lack of updates will apply, as I thought, to the big ones, released once or twice a year.

---

![Windows 11 - Friday Cumulative Update](win11_Friday_Windows_Updates.png)

And so, on this particular day, I was captivated by the [KB5006746](https://support.microsoft.com/en-us/topic/october-21-2021-kb5006746-os-build-22000-282-preview-03190705-0960-4ba4-9ee8-af40bef057d3) update, which fixed a lot of bugs. Although it’s not clear whether my problem was fixed, I eagerly updated.

> This update mentions some issues with the File Explorer, but they are not exactly related to the issues reported by users on the Internet.
>
> This update also introduced one important fix for AMD Ryzen series processor users who experienced a significant drop in system performance after upgrading from Windows 10 to 11.

After installing the update and restarting my computer, I felt a slight improvement, but, as before, only for a moment. The drawback of working with files in the cloud returned.

> For those interested, my system version changed from 21H2 (22000.258) to 21H2 (22000.282). OneDrive 2021 (21.205.1003.0003).

---

The next days passed and overall I have no objections to the system itself.

The problem with browsing files in the cloud is annoying as hell, but fortunately not only me. On the official Microsoft forum [there is a heated discussion](https://techcommunity.microsoft.com/t5/windows-11/onedrive-issues-on-windows-11/m-p/2674325/). Some propose more or less drastic solutions. However, all of them are short-term.

There is nothing left to do but wait for next Thursday/Friday with the hope that Microsoft will release another update (Cumulative Update) that will fix this problem and allow us to focus on other things.

## Another Friday - No Update (29-10-2021)

You would think that this considerable problem would be at the top of the list in Microsoft's technical department. Unfortunately, that's not the case.

The update on Friday 29/10 did not arrive. What's worse, Microsoft announced the day before that it would be making the Windows 11 update available for more compatible devices (seriously?!).

This is problematic because until the bugs are patched, the update should be optional. As you can see, people at Microsoft will have their hands full, and IT service companies will be raking in the cash.

The only half-hearted solution for the file browser is to switch it to full-screen mode (F11) or to pause OneDrive sync. This is really a half-hearted solution, so we'll see what the next week brings.

{{% ads-in-article %}}

## Microsoft can't do it, users will find a (temporary) solution (02-11-2021)

One of the users of [Microsoft Tech Community](https://techcommunity.microsoft.com/t5/windows-11/onedrive-issues-on-windows-11/m-p/2910932/highlight/true#M1078) correctly observed that to get rid of the problem with the slow file browser, just close the OneDrive program right after starting the computer (by clicking on the icon in the taskbar, then select the Close OneDrive option from the settings), wait a short while and start it again.

This seemingly trivial solution, however, allows you to get rid of the main problem of the file browser (File Explorer) while maintaining the functionality of OneDrive.

I spent the whole day working with files and I can say that it is finally possible to work normally! Of course, until you **restart your computer**, at which point the above procedure has to be repeated.

Since I don't want to remember to do the above step every time I start my computer (especially when the day greets us with a ton of work), I decided to add a simple automation.

Namely, I created a **.bat** file (in Notepad) containing the following command:

```
@echo off
"%USERPROFILE%\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /shutdown
start "" "%USERPROFILE%\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
```

I saved the file as **onedrive-temp-fix.bat** and put it in the Startup folder:
```
"%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
```

Thanks to this, when you first log into the system, your OneDrive will be closed and then restarted after a while.

And so the problem disappears, and your concentration returns to working with everyday problems, rather than struggling with your computer (system).

There is light at the end of the tunnel.

We are waiting for Microsoft to take a step in this direction.


---
## Windows 11 on Unsupported Hardware - Day by Day
- **URL:** https://dariusz.wieckiewicz.org/en/windows-11-on-unsupported-hardware-day-by-day/
- **Date:** 2021-10-19
- **Tags:** Windows 11, Unsupported Hardware, file explorer, slow file explorer, regedit, Task Manager, Menu Start, context menu, fman, Teams

### Content

It's been a while since the official release of Windows 11, and it's time to get to know it better.

Although I've been using Windows 11 for some time now on a virtual machine on macOS, it's not the same, because I don't work with it every day.

To see how everything works, I decided to update my "unsupported" computer at work, according to Microsoft, to see if it's safe to migrate others to the new system.

<!--more-->

> Remember, before you decide to update to Windows 11 - **don't rush!** Microsoft's official support for Windows 10 will end on October 14, 2025, so you have plenty of time. Windows 10 is currently one of the better versions of the system, after the no longer supported Windows 7.

---

The entire installation according to my description [Upgrading Windows 10 to Windows 11 without TPM 2.0 on unsupported hardware](/en/upgrading-windows-10-to-windows-11-without-tpm-2-on-unsupported-hardware/) went through without the slightest problem and all applications worked from the first start-up.

The system, despite Microsoft's warnings, is fairly stable (only twice during the first day did I get some unreadable system application error).

What I did notice, however, is why Microsoft is focusing on newer hardware.

If you plan to install the system on a computer with a platter drive, not a fast SSD, I strongly advise against it. Everything will run really slowly and of course you will blame Windows 11.

---

On my work computer with Intel i5-3 generation (i5-3230M, laptop) I had two SSD drives. One with the system installed and the other, which I put in the slot instead of the DVD drive.

This first drive had been with me for some time. According to [HD Tune](https://www.hdtune.com) its average speed was around 120MB/sec, while the second, added later, boasted an average speed of 250MB/sec (nothing groundbreaking, but better than platter drives). Both drives are SATA2 technology.

And here's where the problem arose.

Having a slower drive, even though it's an SSD, was noticeable. Hence Microsoft's requirements.

Assuming that drives in computers with at least 8th generation Intel are already in NAND NVMe PCIe technology, their speed oscillates around 500MB/sec to 2500MB/sec.

An important note here.

Let's not assume that our SSD drive is "fast". Before we start the installation, let's run HD Tune and check its speed for more than 5 minutes.

> There are various drives available on the market that promise high speeds, but only during a dozen or so seconds of writing, after which their speed drops drastically. These drives are not equipped with dedicated memory supporting transfer speeds. The worst thing about this is that when shopping we are not able to check which drive is which. Of course, those that promise mountains are usually cheaper than those whose real performance is long-term, but it is difficult to choose well. Therefore, I encourage you to look through benchmarks on the Internet before you decide to buy an SSD drive. Even drives based on NAND NVMe PCIe technology can disappoint (see those from Silicon Power).

Since I had an alternative, I downloaded [CloneZilla](https://clonezilla.org), cloned my disk and swapped them. I won't say that the system got a boost, but it immediately started working a bit more smoothly.

During the first few days I worked as before on Windows 10.

Some elements in the system were moved or cleverly hidden under an additional menu.

However, here came a certain disappointment.

## Interface

Since Windows 11 is based on Windows 10 and has been in development for a long time, why are there so many interface bugs?

Someone who sets a high bar for the appearance of the system may say, "what the hell is this".

Just right-click on the desktop to bring up the context menu, which looks "nice". Then we go to additional options (Show more options) and we are greeted by an unfinished menu, the highlighting of which does not fit into the overall order of the system.

{{% gallery %}}
![Windows 11 - Right click on Desktop](win11_Right_click_Desktop.png)
![Windows 11 - Right click on Desktop - Show more options](win11_Right_click_Desktop_Show_more_options.png)
{{% /gallery %}}

Interestingly, when you click the New button to, for example, create a folder, the additional menu is consistent with the rest, so why do the others look like they're from a completely different system?

![Windows 11 - Right click on Desktop - New](win11_Right_click_Desktop_New.png)

We don't have to click far. Just right-click on the trash can to see another inconsistency with the overall appearance of the system.

![Windows 11 - Right click on Recycle Bin](win11_Right_click_Recycle_Bin.png)

Interestingly, the menu looks completely different when you right-click on a file or folder.

Oh well, maybe they'll fix that... someday.

## Custom Font Size

Since on my computer with an external screen I have the system at 100% magnification and only the font at 125% (Full HD 23.5" screen), I noticed some shortcomings, where the text is cut off or invisible (especially on the lock screen). Something I haven't experienced in Windows 10 (Boo...).

## Slow File Explorer

The File Explorer itself is noticeably sluggish.

I understand the high requirements for the system itself, but that they are needed just to display pretty icons in the window? Seriously?

Clicking on any item, file or folder, we are greeted by a spinning circle, as if something additional is being done in the background, while nothing else is displayed.

Often the window also freezes and has to be killed by force-closing. Overkill.

This is especially annoying if you want to enter a folder by double-clicking. The first click and the spinning circle appearing causes the second quick click to be ignored, so we have to double-click again. In the case where the double-click works immediately, we have a visible delay when switching between the contents of the window. Because of this small bug, moving between folders is very annoying.

No wonder there is no shortage of references to the phrase: [windows 11 file explorer slow](https://www.google.com/search?q=windows+11+file+explorer+slow) in Google.

Supposedly, this type of error was observed even before the official version of the system was released, which is why Microsoft's ignorance is surprising. It turns out that it will be like with Windows 10, where everything was perfected only after the second or third major update. Someone in the marketing department was clearly in a hurry and didn't care about the errors that came with it, blaming (of course) unsupported hardware (because the more efficient the hardware, the less of these duds visible).

> ps. apparently this bug is related to the fact that OneDrive is active (whether personal or corporate) and closing it restores smooth functionality. For those users who use OneDrive on a daily basis, this is not an acceptable solution.

Some users have found a way to revert the File Explorer behavior to that of Windows 10 by making changes to the system registry as follows:

```
1. Press START+R
2. Type "regedit" and confirm with Enter (Click YES to run)
3. Go to:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked

(we may need to create a new key/folder (Key) named Blocked if it does not exist)

4. In the folder (key) Blocked we create a new string (String Value)
5. Name it "{e2bf9676-5f8f-435c-97eb-11607a5bedf7}"
6. Restart the computer
```

Or by downloading [file_explorer_old_behaviour.reg](/pobierz/file_explorer_old_behaviour.reg.7z) and running it (after unpacking) to add the above entry to the registry.

Well, `e2bf9676-5f8f-435c-97eb-11607a5bedf7` is responsible for the new menu in explorer.

Here's what it looks like before and after the above change

{{% gallery %}}
[![Windows 11 - New File explorer layout](win11_File_explorer_new_layout.png)](win11_File_explorer_new_layout.png)
[![Windows 11 - Old File explorer layout](win11_File_explorer_old_layout.png)](win11_File_explorer_old_layout.png)
{{% /gallery %}}

After restarting the computer, this change made working with files a bit more efficient.

---

Overall, I like the icons in the system. The whole thing looks more friendly to the eye, one could say clearer. The rounded windows add charm.

## Pinned items to the Start menu

Here I got a bit pissed off.

It's known that Windows 11 introduced a new menu (which I moved to its correct place in the settings by default - on the left!), but it retained the same functionality as pinned applications. Unfortunately, these pinned applications in Windows 10 are not transferred to Windows 11, so we have to set it up from scratch.

{{% ads-in-article %}}

## Task Manager

As you know, we can call up the task manager in two ways. With the keyboard shortcut **Ctrl+Alt+Delete** or (in Windows 10) right-clicking in the middle of the taskbar and selecting it from the rich menu.

Well, this rich menu has been removed. I don't understand why at all.

Fortunately, the menu available by right-clicking on the Start menu has remained.

> Task Manager can now be found in this menu, as well as the Run option and a few other useful ones. It's just a matter of getting used to their new location.

Microsoft likes to hide useful things. Just like in Windows 10, where with the next update it hid the shortcut to the control panel, leaving us only the option to launch it using the Run... option (Start+R > control).

## Recommendations in the Start Menu

The inability to remove the recommendations section from the new start menu is nonsense. While we can disable recently opened files and applications, as well as recommendations, the unnecessary space remains.

![Windows 11 - Start Menu - Recommended](win11_Start_menu_Recommended_showing.png)

## Context menu (right click)

As I mentioned at the beginning, Windows 11 is inconsistent when it comes to the interface. Some menus look different than others.

Referring to the slow file browser issue, when working with files in the cloud, people who use the right-click menu will notice that the new menu does not provide the advanced options they need. They usually have to reach for the last option in the list in the menu to see the additional options, the full ones, known from the behavior in Windows 10.

As I noticed, when working with files in the OneDrive cloud, bringing up this first menu is very slow — even annoying.

If I could restore the look of the file browser known from Windows 10, why not get rid of the new right-click menu, leaving only the ones known so far from the previous version of the system?

Well, you can.

To do this, we will again use a change in the system registry.

```
1. Press START+R
2. Type "regedit" and confirm with Enter (Click YES to run)
3. Go to:

Computer\HKEY_CURRENT_USER\Software\Classes\CLSID

4. In the CLSID folder (key) create a new folder string (Key)
5. Name it "{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}"
6. Inside the key create a folder (Key) named "InprocServer32"
7. In the right part double click on the string "(Default)". In the newly opened window click OK. This will change the default value from "not set" to empty.
8. Restart the computer (optional)
```

We can also use this [file_explorer_right_click.reg](/pobierz/file_explorer_right_click.reg.7z) (after unpacking) to add the above value to the registry.

After closing the system registry, you may or may not need to restart your computer, and the behavior when right-clicking on any file should return to what you experienced in Windows 10.

> In order to apply the changes system-wide (the desktop context menu may still be "new"), I recommend restarting your computer.

Thanks to this, we not only got the full menu back, but also working with files became much faster, although still cumbersome, especially when working with files in the OneDrive/SharePoint cloud.

> Currently, when working on files in the cloud, I experience a spinning wheel several times before I can do anything with the file. Very annoying behavior. So annoying that until a solution is found, I am forced to use an alternative file browser such as [fman](https://fman.io/).

> Supposedly, this issue is fixed in the Insider build (22478). Right now, my build is 21H2 (22000.258) and I do not intend to switch to the Insider channel on a production machine, so I have to be patient and wait for an update.

## Microsoft Teams

Microsoft, with Windows 11, started integrating Teams with Windows. It's not bad, as long as it's done correctly.

Unfortunately, Teams, which is installed by default in the system, cannot be used in a corporate environment (Microsoft 365), because you have to download a separate application for that.

It's a bit stupid, because the default, available application is useless. So what's the point of installing it?

---

Read more: [Windows 11 on Unsupported Hardware - Day by Day, Part 2](/en/windows-11-on-unsupported-hardware-day-by-day-part-2/)


---
## Upgrading Windows 10 to Windows 11 without TPM 2.0 on unsupported hardware
- **URL:** https://dariusz.wieckiewicz.org/en/upgrading-windows-10-to-windows-11-without-tpm-2-on-unsupported-hardware/
- **Date:** 2021-10-07
- **Tags:** windows, iso, Windows 11, without TPM, TPM 2.0, unsupported hardware, old processor, skip TPM check, Skip_TPM_Check_on_Dynamic_Update_v2.cmd, Skip_TPM_Check_on_Dynamic_Update.cmd

### Content

Microsoft made Windows 11 available to all users worldwide on October 4, 2021. Not everyone was able to try it, especially those with older machines that do not meet requirements such as having a TPM 2.0 chip.

Well, you can install Windows 11 from scratch [using an ISO image](/en/image-iso-windows-11/), but what about updates where we don't want to lose our settings, programs, and games?

<!--more-->

Running the Windows 11 installer (from the unpacked ISO image) will be of no use, as you will see the following message:

[![This PC doesn't currently meet Windows 11 system requirements](this_PC_doesnt_currently_meet_Windows_11_system_requirements.png)](this_PC_doesnt_currently_meet_Windows_11_system_requirements.png)

Of course, in my case, in addition to the lack of support for TPM 2.0, I received a message that my processor is also too old. Apart from the back button, the only other available option is **Cancel**.

However, before we get discouraged by Windows 11, there is a possibility to disable the TPM requirement via the Windows 11 installer.

It is different when it comes to the "too old" processor, but let's see if meeting the most annoying requirement (TPM) will allow us to proceed.

> Before we decide to continue, let's make sure that our computer has the system installed on a fast SSD drive. Even the latest computers with Windows 10 and a 1TB hard drive can run much slower than those from almost 8 years ago with a drive changed to SSD (with at least DDR3 memory). Of course, UEFI is also required, as I mentioned here: [Preparing for Windows 11 - UEFI](/en/preparing-for-windows-11-uefi/).

For this test I will be using the Lenovo E530c with a 2nd generation Intel i5 processor.

> But before you start having fun, read this: [Microsoft was right. Don't update your "old" computer to Windows 11](/en/microsoft-was-right-dont-update-to-windows-11/)

So let's get started...

Of course, we need [Windows 11 ISO image](/en/image-iso-windows-11/).

Once downloaded, we run [Rufus](https://rufus.ie/) to put the image to a thumb drive, or use a program like [7-Zip](https://www.7-zip.org) to unpack the ISO file.

Next, we need to download a script that will convince the Windows 11 installer to ignore TPM 2.0.

Script prepared by user [AveYo](https://gist.github.com/AveYo) posted on GitHub Gist [here](https://github.com/AveYo/MediaCreationTool.bat).

There is more than what we need on this page. However, in this example we will focus only on the [Skip_TPM_Check_on_Dynamic_Update.cmd](https://github.com/AveYo/MediaCreationTool.bat/blob/main/bypass11/Skip_TPM_Check_on_Dynamic_Update.cmd) file.

Clicking the **Raw** button in the upper right corner will open the file contents in a new window. Copy the entire contents and paste them into Notepad. Save everything to the desktop under the name `Skip_TPM_Check_on_Dynamic_Update.cmd`.

And so we are ready to install.

First, run our file (**once**) `Skip_TPM_Check_on_Dynamic_Update.cmd` and then (when the new window disappears) start the installation process by clicking on the file `setup.exe` from the unpacked Windows 11 ISO image.

> I wrote that we only run the file once, because when we run it for the first time we disable the TPM check, and after we run it again we restore the settings to what they were. This way we don't mess anything up in our system.

[![Windows 11 Change how setup download updates](SetupHost_Windows11_Change_how_setup_download_updates.png)](SetupHost_Windows11_Change_how_setup_download_updates.png)

First, we will get a start window, where we **DO NOT** click Next yet, but go to the option to change how the system installs updates during installation.

[![Windows 11 Get Updated - Not at the moment](SetupHost_Windows11_get_updates_not_at_the_moment.png)](SetupHost_Windows11_get_updates_not_at_the_moment.png)

We select the second option here so that the installer does not install updates during installation.

> Alternatively, we disconnect our computer from the Internet.

By clicking **Next**, the installer will check if our system meets the minimum requirements, returning (still) an error about missing TPM 2.0.

[![Windows 11 The PC must support TPM 2.0](SetupHost_Windows11_The_PC_must_support_TPM_20.png)](SetupHost_Windows11_The_PC_must_support_TPM_20.png)

However, if we have run `Skip_TPM_Check_on_Dynamic_Update.cmd` once before starting the installation, click **Back** and **Next** again.

{{% ads-in-article %}}

This time the installer will not report a problem with TPM 2.0 and will allow the installation to begin.

[![Windows 11 Licence Terms](SetupHost_Windows11_licence_terms.png)](SetupHost_Windows11_licence_terms.png)

The installation will begin with accepting the license, after which we will receive information (so-called loyalty) that our computer still does not meet the minimum requirements for Windows 11.

[![Windows 11 What needs your attention](SetupHost_Windows11_what_needs_your_attention.png)](SetupHost_Windows11_what_needs_your_attention.png)

To start the installation, you must accept (Accept) the loyalty agreement, which states, among other things, that our system will not receive future updates. **This is not about updates that are made available by default in Windows Update from time to time**, but about major system updates, as was the case with Windows 10, which received major updates twice a year.

However, nothing is lost, because with the help of the ISO file, when a "major" system update is released, we will be able to do the entire process analogously to what we are doing now.

[![Windows 11 Ready to install](SetupHost_Windows11_ready_to_install.png)](SetupHost_Windows11_ready_to_install.png)

After accepting, we are ready to install.

The entire installation process will go smoothly. Depending on the speed of your computer, just wait a little while for it to finish. In my case, it took about 45 minutes.

And so we will update our Windows 10 system to Windows 11 on "officially" unsupported hardware.

[![winver Windows 11](winver_Windows_11.png)](winver_Windows_11.png)

Regards.



---
## How to download Windows 11 image (ISO)
- **URL:** https://dariusz.wieckiewicz.org/en/image-iso-windows-11/
- **Date:** 2021-10-05
- **Tags:** Windows, ISO, Microsoft, ISO image, Windows 11, Windows 11 ISO, Windows 11 64-bit

### Content

As announced, on October 5, 2021 (to be more precise, at the end of October 4), Microsoft officially presented the final version of Windows 11.

<!--more-->

Even though updating to Windows 11 will not be that easy, especially for owners of older hardware, it does not mean that it is impossible.

Microsoft has officially indicated that Windows 11 will be available to all users for free, as long as they have compatible hardware.

This compatible hardware, as verified, is not older than 2-3 years (on average), so it is not like updating Windows 10, where you just had to run the update and that's it.

The basic minimum requirements are:
* 1GHz dual-core CPU
	* In general, Inter 8th generation and newer processors should meet Microsoft's requirements.
* 4GB RAM
* 64GB of free disk space
* DirectX 12 compatible graphics card

UEFI motherboard, TPM 2.0, DX12 graphics, 720p display
Additionally, our motherboard must support:
* UEFI with Secure Boot option.
* TPM 2.0 chip

> To check whether our hardware is ready for the update, we can use the official tool [PC Health Check](https://aka.ms/GetPCHealthCheckMSIX) or use the application [WhyNotWin11](https://github.com/rcmaehl/WhyNotWin11). If we meet all the requirements in the **System Settings**, **Update and Security** section, we should be greeted by a message about the possibility of updating for free.

After numerous negative comments towards Microsoft, the company gave in a bit and announced that it will still be possible to install Windows 11 on older hardware.

To do this, however, you must use an ISO image and, in most cases, install the system from scratch.

**But that's not all.** In order to be able to enjoy Windows 11 on older hardware, you must "sign a loyalty agreement" releasing Microsoft from responsibility that because of Windows 11 our computer will not function fully as it should.

Additionally, Microsoft noted that future system updates may not be available for older Windows 11 devices.

---

So, to install our Windows 11, we need an ISO image, which we then need to upload to our portable memory.

In the case of the Windows 10 image, we had to use a workaround to be able to download the ISO image directly from Microsoft's servers, especially if we had a Windows computer (see [How to download a Windows 10 image (ISO)](/en/image-iso-windows-10/)).

Fortunately, in the case of Windows 11 the situation is a bit simpler. Just go to the dedicated page where we will have three options for downloading the system:

> [www.microsoft.com/pl-pl/software-download/windows11](https://www.microsoft.com/pl-pl/software-download/windows11)

## Windows 11 installation assistant

[![Windows 11 installation assistant](Asystent_instalacji_systemu_Windows_11.png "Windows 11 installation assistant with Download now (Pobierz teraz) button")](https://www.microsoft.com/pl-pl/software-download/windows11)

First, we can use the Windows 11 assistant, which will check our system for compatibility and carry out the entire process for us, including transferring all files and applications.

## Creating Windows 11 installation media

[![Creating Windows 11 installation media](Tworzenie_nosnika_instalacyjnego_systemu_Windows_11.png "Creating Windows 11 installation media with Download now (Pobierz teraz) button")](https://www.microsoft.com/pl-pl/software-download/windows11)

This time, Microsoft has prepared (it did not hide it from us, because it was also available for Windows 10) a simple tool that will download the system for us in the background and create an installer on the portable memory.

Unfortunately, we don't have much control over which version we want to install, so the third option is more useful for users who install the system on different computers.

{{% ads-in-article %}}

## Downloading the Windows 11 disk image (ISO)

In this step, we will receive the Windows 11 installer image file in the form of an ISO, which we can later easily upload to our portable memory using an application such as [Rufus](https://rufus.ie/).

[![Downloading the Windows 11 disk image (ISO)](Pobieranie_obrazu_dysku_ISO_systemu_Windows_11.png "Downloading the Windows 11 disk image (ISO) with Download (Pobierz) button")](https://www.microsoft.com/pl-pl/software-download/windows11)

It's no surprise that with Windows 11, Microsoft ended official support for 32-bit Windows.

[![Windows 11 Polish 64-bit ISO](Pobieranie_obrazu_dysku_ISO_systemu_Windows_11_Polski_64bit.png "64-bit Download (64-bit Pobierz) button for downloading Windows 11 (Polish) ISO")](https://www.microsoft.com/pl-pl/software-download/windows11)

Disappointingly, however, the version for computers with a processor based on the ARM architecture is still unavailable, so users of the virtual system on Apple computers with an M1 processor still have to upgrade to the Insider version.

---

While in the case of Windows 10, the update was recommended for all previous versions of Windows, this time you should not rush so much.

Windows 10 will continue to be supported and we will receive updates for it. However, they will not be as intense and will not contain so many new features, but we can use it without any worries until **October 14, 2025**.

Until then, we should think about replacing our aging equipment or updating (expanding) it, if possible.

Regards.


---
## My thought about the HGV drivers shortage
- **URL:** https://dariusz.wieckiewicz.org/en/my-thought-about-the-hgv-drivers-shortage/
- **Date:** 2021-10-01
- **Tags:** HGV, HGV drivers, drivers shortage, Covid

### Content

Just a thought...

Politics blaming each other’s, but right now trying to blame European people, that they don’t want to come and help Britain in need.

Everybody forgets what was shown last year. Thousands of HGV trucks have been stuck in companies car parks as they were not needed. The world has been fighting with Covid so no such many goods have been moving around.

<!--more-->

What do you all think happens to all these drivers whose trucks, their whole life, have been stuck in a car park? Don’t think they have all been put on a furlough scheme. Most of them faced uncertainty. Most of them suddenly lost their income. They have families that need to be fed, they have bills to pay. Nobody cares about that then... and suddenly they care about them now, when they are needed.

Many of them, when they can, changed their qualifications to do other jobs. Not all have been so lucky. Many forget about them (the country) and many of them (HGV drivers) lost everything. Some of them are still figuring out how to get back on track.

To those who are still on the rough patch, for taxpayers money our government is sending letters (to HGV licence holders) asking them to go back to their original job to help the country in need.

Does the country help them when they need help the most? 

People, who before the pandemic, until now, were able, and still are with that same employer shall be feeling privileged.

It’s easy to forget about people. They (people) don’t forget. 

Don’t expect right now, that those who managed to fit into the new jobs will throw everything that they work so hard for only because the country is in the need of them, again.

This +1 majority voted to get rid of immigrants who have been using open borders to help this country moving suddenly figuring out that we still need them. 

Treating them like dogs, offering short term visas as it suits this country, not them, just to fulfil the needs of this country, not theirs. Then, ready to kick them day after Christmas Eve, without the word “thank you for your service” but like an unwanted present on boxing day with a sticker “get back to your own country”.

Now, there are those, who have been shouting years back, that "they coming here and taking our jobs". Now, those same people shouting that "they don’t want to come here and take our jobs" (as HGV drivers). What a pathetic nation we are.

We do not even know how to learn from our own mistakes. Like other countries (Poland) closing their borders to do not let people in need, forgetting that they own everything that they have to the other countries that helped in the past. British people easily forget and create their wind-rush scandals, again and again, separating families only because half of them haven’t done the right paperwork on time. 

We shall be ashamed of ourselves. We are not a gold island, we are all one. We are just a part of the whole world.

There is no climate crisis in just the United Kingdom, there is a climate crisis whole over the world. 

The borders are made by humans, but we are all "one", let’s don’t forget about that.

If we need help, let’s think if we do all things right so we deserve to receive it. If we did, we will see how a helping hand is reaching us.

Do you see that hand…?

Let’s cherish what we have and be respectful to each other at first.

We are a nation of multi-cultures but if we will work together, we can be "one nation". Doesn’t matter of skin colour, gender or excellence in voyaging of our mutual language.

We can do this. We can do everything, it’s just up to that if we are ready for that.

Like somebody brave said: "HGV drivers are for life, not just for Christmas".

{{% ads-in-article %}}


---
## When a warranty is not worth the hassle
- **URL:** https://dariusz.wieckiewicz.org/en/when-a-warranty-is-not-worth-the-hassle/
- **Date:** 2021-08-11
- **Tags:** warranty, PNY, SanDisk, WD, Western Digital, Kingston, Crucial, integral, ADATA, Samsung, Silicon Power, Transcend

### Content

When you buy Solid State Drive (SDD) the last thing is to have your drive fail and all files are lost.

With SSD is not as easy to restore anything as it could be with mechanical drives. If they fail it's rarely anybody will bother to fix it, and most companies will just give you a new drive if it's still on warranty.

Don't expect any money back or help in the restoration of your files from faulty drives. None of the warranty covers that from any manufacturers - end of the story.

However, in this rare instance of failure, you expect swift action without any hassle and any extra cost for yourself. You already have a big (unrectified) cost for losing all your data so why to get another one?

And here the problem occurs.

<!--more-->

Some companies, like **SanDisk** (**WD - Western Digital**), for example, will send you pre-paid labels and will arrange collection by selected courier free of charge. The package is then sent to Poland (from the UK) and when approved, the new device is sent to you, from Poland to the UK without any costs. That's good customer service and a good customer experience if something goes wrong.

I used twice the SanDisk warranty for my microSD cards and despite that, the issue occurs more than I expect. I still trust SanDisk brand and manufacturer.

I cannot say that same with **PNY**.

They put their warranty condition in such a way, that even that fault is on their side (their device fail) you are responsible to return the item to them.

> https://www.pny.eu/legal/warranty/en
>
> *"Products must be sent to PNY carriage paid, in suitable packaging, by registered post with proof of delivery, and insured when appropriate."*

It will not be a problem if, when you purchased your product in the UK, you will be returning to a UK representative.

**PNY** the closest site is in **France** and due to **Brexit bollocks**, cost sending to France is sometimes more expensive than purchasing a new device. In my case, 480 GB SSD drive that cost me £39.99 in December 2020, carriage cost can be between 25-50% of that value!

That's total **nonsense** and you are not guaranteed that you will get a new device.

What happens if they, after inspection, will disagree with your warranty claim? You are without the device and with the cost of carriage not refunded by anybody.

Because of this **stupid** warranty practice of **PNY** I decided to look at other manufacturers of SSD drives available to purchase directly through Amazon (Sold and Fulfilled by Amazon) to see which one to choose to avoid hassle when something will go wrong.

So, I checked firstly the most popular brand - **Kingston**.

> https://www.kingston.com/unitedkingdom/en/company/warranty
>
> *"To obtain warranty service, you may return a defective product to your original point of purchase, or the authorised Kingston dealer or distributor from which you purchased the Kingston product."*

Their document doesn't explain who is responsible for paying carriage, however, it sounds much reasonable if you return it to the original point of purchase. If you purchase via Amazon UK, their customer service will be able to help you with that. Even if you need to pay, sending in the UK mainland will be cheaper than sending to France "with proof of delivery and insured".

The other popular brand is **Crucial**.

> https://uk.crucial.com/company/warranty
>
> *"You are responsible for returning the product to Micron CPG at your risk and expense."*

Another company put a cost against the customer. Luckily, Micron got its branch in the UK, hence the return cost will be lower than on international postage.

Let's look at **integral**.

> https://www.integralmemoryplc.com/warranty
>
> *"For warranty service please contact your place of purchase."*

Their warranty card is vogue and even links to [Support form](https://www.integralmemoryplc.com/support-form) pointing you to Error 404 page. The plus is, that their head office is in the United Kingdom, hence return shall be hassle free than **PNY**.

It's time for **Samsung**.

> https://www.samsung.com/semiconductor/minisite/ssd/support/warranty/

Samsung warranty is not clear. Without contacting customer service it's hard to say how the procedure will take place and who is responsible for the return. Based on my experience with Samsung I would not be surprised if they would arrange everything for you. However, I need to remember that there are a couple of points in the warranty document reducing their responsibility to replace the faulty item or refunding you only the current market value and not the value paid at the time.

> Also, in case of replacing your device, they reserve the right to send you a refurbished one instead of a new one.

{{% ads-in-article %}}

One of the less popular, but still widely available on Amazon, is **ADATA**

> https://www.adata.com/uk/support/consumer?tab=warranty&warranty=warrantyService
>
> *"Subject to the terms and conditions hereunder, ADATA provides, without any charges or fees, replacement or repair services to our customers for defective products within the applicable warranty term (hereinafter referred to as “Warranty Service”)"*

Sounds optimistic, but if you read further:

> *"In this case, the cost of transportation and relevant insurance for the delivery of the Product to ADATA shall be borne by you, and ADATA shall cover the cost of all other transportation and relevant insurance when returning the Product back to you after Warranty Service completion."*

You are responsible for sending on your own cost to ADATA Headquarter which is Taiwan!?!

Of course, if you purchase through Amazon UK, you may want to express your right through the below point in their warranty.

> *"Please contact the local reseller where the purchase was made for help."*

Other popular, however not such great products are from **Silicon Power** (SP).

> https://www.silicon-power.com/support/lang/utf8/Warranty_Policy.pdf
>
> *"Return to the authorized Silicon Power dealer or distributor from which you purchased the Silicon Power product. Please confirm the warranty policy terms with your dealer's or distributor’s return  policies prior to returning the product."*

Here once again it's very important to where we purchase our device. If we are buying from eBay or companies like **MyMemory**, who is not paying VAT in the UK (this is why products are cheaper), you may have a hefty problem with the execution of your rights.

Another company that specialises in high-end (expensive) products is **Transcend**. From this company, I would expect a high level of support.

> https://www.transcend-info.com/Legal/?no=7
>
> *"Customer is responsible for the cost of return shipping/postage to Transcend."*

That's a bit disappointing considering how expensive are Transcend goods. It's also unclear to which country you will be obligated to return to, hence the cost can go significantly up, similarly to PNY.

There are of course other low-budget companies, and I will highly question their warranty claims above 30 days and will not trust if they offer something close to the warranty end date.

Of course, like with every item covered by warranty, it's worth keeping an original proof of purchase, receipt or invoice (which people in the UK tend to forget, as in most cases is not needed), as without it we may forget about claiming anything, unless we purchased something from Apple, who's procedures are on a much higher level (item traceability to purchase date) to make sure you are 100% satisfied with an output. However, exceptions from that also happen as we need to remember, that executing warranty claims is only a cost for most of the companies. Rarely the cause of the issue will be investigated (unless it happens relatively quickly after releasing it onto the market) to prevent this issue from reoccurring.



---
## Track your 404 traffic the smart way
- **URL:** https://dariusz.wieckiewicz.org/en/track-your-404-traffic-the-smart-way/
- **Date:** 2021-08-09
- **Tags:** 404, Error 404, Google Analytics, Minimal Analytics

### Content

When I moved into a static website made using [Hugo](https://gohugo.io) I optimised almost everything, including the Google Analytics script. Instead of bulky code loaded from Google, I used [Minimal Analytics](https://minimalanalytics.com).

Initially, I put it as always, in the head of my website. Later on, I added it to my **404.html** page. I created my own 404 page to override the default Netlify landing page that appears when the visited URL was not found.

The idea was initially to find broken links that visitors are using and to fix them with relevant redirection. However, it didn't take long until my analytics were spammed by stupid people (and their bots) trying to find a way to break in to my site.

<!--more-->

Despite that, on a static website, there is nothing to break in. "The internet" remembered that I was using WordPress before, so they keep trying to use known vulnerabilities to break into it.

Of course, these attempts were pointless, and they always land on the 404 page.

WordPress on my website is long-term gone and will not come back however I still would like to know what happens on the 404 page.

Luckily, Google Analytics offers the ability to create a property with its own tracking code. You can have your own account, and on it have separate tracking codes for a different purpose.

[![GA - Create Property - Property Details](/images/2021/08/GA_Create_Property_Property_Details-min.png)](/images/2021/08/GA_Create_Property_Property_Details-min.png)

Assuming that you use one **account** (do not mix with Google Account) per website then the main property is used for tracking your main website and any other to track different parts, and they are not mixing with each other.

[![GA - Create Property - Create UA](/images/2021/08/GA_Create_Property_Create_UA-min.png)](/images/2021/08/GA_Create_Property_Create_UA-min.png)

In such a way, I created an additional property that I called **404 Junk Collector** and through **advances options** I created the Universal Analytics property. This gives me the UA tracking code that later, using Minimal Analytics, I implemented it into my 404.html page.

> Referred solution (and minimal analytics code) is based on Universal Analytics that will become obsolete by Google on 1st July 2023. Read [A very Minimal Google Analytics 4 Snippet](/en/minimal-google-analytics-4-snippet/) to use a similar approach with Google Analytics 4.

This property will not be a thing, that I will be looking at very often, but more rather from time to time and see what happens in the background.

{{% ads-in-article %}}

---

After migrating from WordPress I noticed a big drop in traffic which resulted not in the loss of true visitors but more rather bots trying to scan my website to find weak points.

Having 404's in your main traffic gave false assurance about the true meaning and need of the existence of your website.

If, for example, from 1,000 visits you drop to 500 on static site, after excluding 404's you land in like 250. That's your real target audience on which you need to concentrate your efforts and the content that you create.

---

You may live without knowledge of what is happening on the 404 page and nothing bad will happen, especially when your website is static, but from time to time, especially after updating some old posts its worth having a look if we didn't break something, and because of that not losing our precious visitors. Right implemented redirection rule may save us precious time regaining lost traffic.


---
## Leap forward - Apple Silicon
- **URL:** https://dariusz.wieckiewicz.org/en/leap-forward-apple-silicon/
- **Date:** 2021-07-27
- **Tags:** Apple Silicon, MacBook Air, MacBook Air M1, Intel, Trade-In, Brightstar, Apple, Certified Refurbished, Apple Care, Apple Refurbished store

### Content

At the beginning of 2014, I purchased my first-ever MacBook Pro. It was a Late-2013 model with Intel Core i5, 8GB of RAM and 256GB SSD. A superb machine that worked with me for years (till 2020). It could work with me a bit longer but I feel that I need an upgrade.

<!--more-->

For last years I haven't been looking to change this ageing machine due to the main reason, the keyboard.

The butterfly keyboard was a pain, hence buying anything between 2015 and before 2020 refresh wasn't recommended.

Apple finally made a decision to change the design and when they announced in April 2020 new MacBooks, I decided to move forward.

I thought it was a goods decision at the time as didn't know what else 2020 will bring.

The computer was way faster than my old machine mostly because of hard drive speeds (from approximately 500Mbps to over 2000Mbps was a 4 times jump). Apart from quadruples speeds I initially double the storage compared to the old machine along with double the RAM.

At the same time, Apple introduced Development Machines (iMac's) based on A chips used in iPhones and iPads. Later that year they presented the finished product - the M1 chip followed by new MacBooks.

Initially, they advised, that there will be a transition of approximately 2 years before they will move away from Intel, so I thought I would still have time before I will move forward.

All people, including myself, have been watching how M1 performs against Intel machines, and we have all been amazed.

The winner has been obvious. M1 crushed Intel massively (and still crushing in benchmarks on Intel 12th generation of upcoming chips).

Of course, I have been aware, that this chip is just a first-generation and I would not recommend going into it straight away (based on my own first-generation experience with other devices), mostly because of software compatibility that still needs to be sorted for some apps at the time of writing.

> Life confirmed to me, that it's worth waiting before going into the first generation of new devices. I owned the first generation of AirPods which were quickly replaced by the second generation to remove a couple of annoyances, including connection issues and unequal battery usage in each earpod. Similarly when I became an owner of the iPhone X to discover that Xs was the model that was worth moving towards.

Apple made a huge development with its middleman software (Rosetta 2) that allows it to run Intel apps on M1 chips without losing performance (and even gaining it, despite that this has been done through emulation).

Every month, when M1 starts becoming something that will be a future and the software starts catching up (See website: [Is Apple Silicon ready?](https://isapplesiliconready.com/)) with it I looked at how to go into it.

> Same like with iPhone 12, I didn't go into it due to the first attempt to use the 5G modem. I prefer to wait and get an improved one. Similar to M1, I would like to get M1x or M2 (whichever it will be named).

I knew, that buying now (mid-June 2021) a computer with M1 is not a great idea as new hardware is due to be released.

Everyone expected the new M1x chip to be released on WWDC 2021 but that didn't happen at the time.

I looked at the time how much I could get for my MacBook and Apple still offers me decent trade-in value!

However, despite very goods prices, the current M1 MacBook has been cheaper on other sellers by roughly £250 to what Apple offered. Initially, I could exchange my device, without spending anything extra (or minimum) but don't want to do that now and discover, that in September/October I could do a better deal.

I knew, that in a couple of months times Apple will not offer me the same price on trade-in, but possibly I may have a better starting price comparing if I would like to sell it on my own, as sellers/buyers in June 2021 price mine on half what Apple trade-in offers.

> Going back to my purchase in 2020, what I get with my new machine comes with a Touch Bar. This wasn't a killer feature that I was desired to have, but as there was no option to get it without (Pro's), I was forced to have it.
>
> There are already rumours (June 2020) that next-generation MacBooks with Apple Silicon's will not feature it. I will not be sad to go back to physical keys at all.
>
> In the beginning I was using touch bar from time to time, but most of the time it's something extra that I rarely use and would prefer to have keys, as I worked with key-based features much quicker than now, when I need to find them and display on this tiny screen above the keyboard.
>
> Hope that rumours will be true, and we will get MacBook Pro's with full keyboards once again.

Every month I look more and more towards moving into the device with Apple Silicon, and I am not the only one. Initially, I thought I would do that in at least September/October 2021, but seen how much Intel's chip is staying behind, I thought the change was on the horizon.

Also, once I've been very satisfied with my Late-2013 MacBook Pro battery, even after years of use I could say this about the 2020 model. I am seriously disappointed. After just a year I lost like 14% from full capacity and 5 hours on batter was something that I could get, nothing more.

Considering my usage, I also looked in the future on using MacBook Air instead of Pro, but I would like to have this fan for cooling (comparing to MacBook Pro) even with Apple Silicon, which is running way cooler than Intel's on stand-by.

In case I will need to do (rarely) some complicated operation, I would like not to be limited by thermal throttling. I hope that 2021 Air will have an improvement in that field.

As of June 2020, I wait to see what will happen in 2-3 months.

----

In the meantime, I start to make notes based on people's comments and completions to let me decide.

Here is my quick completion of Pro vs Air.

1. Bigger battery. Seriously, if the Air battery wasn’t enough already?
2. Faster charger. Considering that you charge once in a couple of days and at night, what’s the difference?
3. Fan. Considering the fact that the idle temperature of M1 is like room temperature (60C on Intel) is that necessary?
4. Touch Bar. But Apple is killing Touch Bar apparently with m1x?
5. Brighter screen. You need to answer your question, how many times have you worked on your laptop outside on a bright day?
6. Better speaker/mic. 95% of the time my Mac is on mute so what the difference will it make?

---

And so on, **scrap most of the things that I said above**. I didn't wait and decided to go into it.

I don't want to rephrase anything that I said about buying first generation stuff. However, I decided not to wait until September (maybe October or even November) event to discover that there was only a slight upgrade to the Pro-line by introducing the M1X chip (as rumoured).

I decided to trade in my MacBook Pro with 10th Generation i5, 16GB memory and 512GB SSD and exchange it (directly from Apple) for possibly refurbished based model MacBook Air with M1 chip, 8GB memory and 256GB hard drive.

> My Late-2013 model of MacBook Pro had initially 8GB of RAM and 256GB storage, and I never reached more than 60% of storage on it. Considering the fact that I am storing plenty in the cloud and got multiple memory sticks and external SSD drives, don't think I will regret in a downgrade.

Apple offers me a very good price, almost doubling quotes from other trade-in providers. 55% (initially) of my purchased value from a year ago wasn't too bad, considering that I only need to spend 80% of it to get M1 MacBook Air (basic, refurbished).

## Apple Care+ refund

A year ago I purchased Apple Care with it (that later was upgraded for free to Apple Care+) and when I initiated Trade-In on the official Apple website (that is done via Brightstar in the UK) I been advised to contact Apple Customer Service to see if I got any refundable balance because of that. Generally speaking, I used a year from 3 years of Apple Care, so depending on trade-in taking into consideration having Apple Care or not, I may get some extra money back additionally to trade-in value.

> Before I send the device I spoke with Customer Service, and they scheduled a call for me with the relevant department to see what I am entitled to.

What I have been advised is the price I have been offered by the Trade-In programme **is not based on fact**, that device has been or not, purchased with Apple Care+ and in that case, I cancelled it once I sent it away and received a part refund!

In such a way, I get back 60% of the money that I paid for this protection in May 2020! I chose payout in Apple Store Gift Card however the option to pay directly to a bank account was also available.

In that case, trade-in value offered me back slightly over **60%** of the total value that I paid back then.

40% loss after over a year of use is not bad even for Apple devices.

---

> In the UK (and Germany) Apple is offering monthly options for Apple Care+ which is much better than paying upfront (not hurting our budget as much) but this is only available for iPhones, iPads and Apple Watches. Luckily, Apple Care+ for MacBook with M1 chip was recently reduced from £229 to £189 for MacBook Air.

{{% ads-in-article %}}

## Trade-in experience

I used trade-in with Apple before with Apple Watches, but that was when I purchased a new device instead. The whole process at the time was much straightforward, as I purchased the device and initiated a trade-in at the same time to get money back at the end when all been accepted and approved.

When buying refurbished Apple products you don't have the option to trade-in at the same time. Partly I understand it as if you will not be happy with your purchase you can simply send it back.

In that case, I need to arrange trade-in separately. Because on trade-in you are not getting back your money into your account but you are issued with **Apple Store Gift Credit** that you can spend towards your purchase. I couldn't simply buy a new (refurbished) product right now.

I ended up sending my device and waiting for a third-party who is doing trade-in on behalf of Apple UK to confirm a quote value based on device condition and then awaiting Gift Credit that I could redeem against my purchase.

This process is not quick. In terms and conditions been advised that it can take 2-3 weeks before you get paid, so I have been without the device for a bit of time. I don't mind as long as my trade-in value will be met.

And that is where the process takes some time.

My order has been delivered but a part from seen that on the carrier company tracking system nothing changed on the Brightstar website. Contacted their customer service, and they advised that the product arrived and it will take a couple of days for it to be inspected. Till then no update has been visible and I haven't been 100% sure if I will receive the amount advised.

In the meantime, Brightstar customer service informed me that they are short-staffed and inspection is taking longer than expected due to Covid limitations (which you can understand in the current situation). They offered an extension to my initial valuation for my device to give them time to do what they need to do.

I care about all my devices hence I would be very disappointed if I would get an offer less than initially advised. Apart from signs of shine on the keyboard, the laptop has been in an immune condition.

After 10 days from my laptop being delivered to Brightstar, a couple of emails chasing from update finally got confirmation, that my valuation matched with their inspection criteria and I shall receive Apple Store Gift Card in the next 3-5 working days.

Considering the fact, that at the time I waited still for my Gift Card from my Apple Care+ refund (which supposed to be done in up to 10 working days), I shall receive both roughly together. Hurray!

> I received my Gift Card from Trade-In two days later after confirmation of my device.

--------

Still awaiting other credit I already have funds to order my new (refurbished device) which I did.

After that, I still have a leftover for other purchases in Apple Store (on my list I got AirTags).

----

It may look, that I downgrade from MacBook Pro to MacBook Air. Less RAM, less capacity on SSD, however, I think this will give me a better position when I would even consider upgrading to MacBook Air M2 when it will be presented at the beginning of 2022 based on current rumours.

## Wednesday is a day for Apple Refurbished store

What I noticed on the official Apple Refurbished store, the devices showing and going randomly. Mostly, the hottest devices like MacBook Air M1 are taken off in the evenings and for weekends (unless they have plenty in stock).

Typically they appear in stock on Wednesday and disappear at some point Thursday-Friday.

The waiting period allows me to observe how things move there. At the end of the first week (since I sent my device for trade-in) I thought that if they are gone, they are gone, but no, similar stock re-appear midweek next week.

Initially, I thought that if what I want is not available I will need to choose differently but decided to wait. I wait some time without my device so is not a problem to wait a couple more days to get what I want and finally, I got it.

## Summary

So, here is how it looks after this fun with trading-in and been without a device for 3 weeks.

I purchased my device in May 2020 and trade-in back to Apple in July 2021 for ~62% of its purchase value.

I spent £249 for Apple Care coverage from which I get back also ~62%.

At the time MacBook Air M1 in the official Apple Refurbished store cost £849, which was 67% of the money that I get back from trade-in and refund of the Apple Care plan.

Still, after purchasing Apple Care+ for my Refurbished MacBook M1 (£189) I got leftover.

Now the major question is, are all these hustles worth it?

After my initial play with my new (refurbished) device I feel the difference.

> ps. A new, refurbished device, when arrived, if I would put this aside of a new-new device, nobody will tell the difference. I have been shocked at the same time, as I assured myself that purchasing refurbished devices directly from Apple is a win-win. That's the Apple quality.

It's like when I moved from my Late-2013 model to Mid-2020 but this time it's just a year (6 months if you count from the release date) and the leap forward is massive.

> Of course, unoptimized apps need to take time on the first run to be converted by Rosetta, but later on there is no visible difference.
> Surprisingly, most of my apps are reported as Universal, hence developers made a lot of work rewarded in the potential that is in the M1 chip.

Apple makes the right move. If they will manage with further development of their chips in the future, then AMD and Intel (unless they make a move) will be in big trouble. They are already, but M1 was just thunder and the storm is coming.



---
## Be yourself, be average...
- **URL:** https://dariusz.wieckiewicz.org/en/be-yourself-be-average/
- **Date:** 2021-07-24
- **Tags:** motivation, self-esteem

### Content

I never classed myself as a **creator** despite I have learned to use new things to **create** something new. 

I am more of a person who can use certain skills and available tools to achieve my goal.

<!--more-->

In the past, I learned by breaking things. It cost me to fix, but the cost exceeds the knowledge that I gain. The knowledge and curiosity that is with me till now.

Nobody likes new challenges. They may be overwhelming, but rethinking the approach and having a “give it a try” approach can solve everything.

You cannot have a “can do” attitude all the time, as failure is something normal. With “can do” the failure can be overwhelming and can break your confidence. With the “will try” approach if you succeed, you will learn something new. If you fail, the failure will be just a lesson to learn in the future. 

Be aware of your limitation and lack of skills. Have a willingness to develop yourself in areas that you are not good at. Use the time to learn from other experiences. Pick and mix someone’s ideas and solutions to create your unique way to solve the issue.

You cannot always succeed, but you will not be a total failure as well, because at least you tried.

Don’t sit with your eyes oriented in one way. Open your eyes to wide-angle and see the wider picture. Let your mind accept changes and differences especially differences in people. Something new is not always bad. 

Don’t be a caveman who is afraid to go out of the cave to discover something new. 

Don’t be a loser who laughs at others who try and fail. Sometimes against all odds the “will try” approach can save somebody’s life.

Sometimes it’s better to be an average in something. 

You don’t need to be picked into the team. One opportunity lost doesn’t mean that others will not follow.

Reach happiness and self-fulfilment. Find your purpose in this world. 

In the end, when at least a bunch of people (or even one) will miss you, your knowledge, skills, open approach, that means you did well.

When your life comes to the end and you can say that you are proud of your successes and failures from which you learn a lot, that means you find the purpose and live along with it.

{{% ads-in-article %}}


---
## How it is not possible, if it is - Windows 11
- **URL:** https://dariusz.wieckiewicz.org/en/how-it-is-not-possible-if-it-is-windows-11/
- **Date:** 2021-07-03
- **Tags:** Windows 10, Windows 11, Windows Insider, Windows 11 Insider Preview, Windows Insider Programme, Parallels Desktop, WhyNotWin11

### Content

Most of us have certainly heard about the requirements for Windows 11, when it comes to hardware. A large number of users were disappointed, checking whether they will be able to update their hardware to the latest system from Microsoft. But... how it is not possible, if it is!

<!--more--> 

As a private Mac user, I have Parallels Desktop installed to virtualize Windows 10.

This is a very convenient solution, especially when I need to work on something that only works under Windows, or perform operations on hardware that, in development mode, is best operated under that system.

While the hardware requirements for Windows 11 are not fully specified (they are constantly being revised), we already know that it will be possible to install the system on hardware that Microsoft would not want to be used with the latest system.

I have already written about what you would need to do to prepare your computer (even though it may not meet all the requirements) for Windows 11 in the post [Preparing for Windows 11 - UEFI](/en/preparing-for-windows-11-uefi/).

While we wait for the official, final version of Windows 11, to check how the new system will work, we have to use the Windows Insider option.

Having a virtual Windows in Parallels Desktop, I cloned my Windows 10 machine and decided to try to update it to the developer version (Dev), on which Windows 11 is available.

A few days earlier, I read information from the creators of the Parallels Desktop software that they have to "create" a new version (as always) of their software in order to be able to install Windows 11 in the future.

Reading the texts on this topic, one can conclude that it is not possible to install Windows 11 in the current version? But why?

I decided to check it out.

I joined the Windows Insider program and started the update.

Right at the beginning I got a message that my system is not compatible.

[![Windows Insider Programme](windows_insider_programme.png)](windows_insider_programme.png)

When trying to install, the main problem was the amount of RAM I had assigned to the virtual machine. Initially I only had 2GB, so I increased it to 4GB and proceeded to update again.

[![Windows Update Windows 11 Insider Preview](windows_update_windows_11_insider_preview.png)](windows_update_windows_11_insider_preview.png)

This time the entire update process started without a problem.

[![Windows 11 Startup](windows_11_startup.png)](windows_11_startup.png)

The system restarted and I was greeted with the new Windows 11 logo, and then the next stage of the update began.

After restarting the computer several times, the update process reached 100%.

[![Windows 11 Finishing Update 100%](windows_11_finishing_update_100p.png)](windows_11_finishing_update_100p.png)

Then I saw the Windows 11 start screen.

[![Windows 11 First Screen](windows_11_first_screen.png)](windows_11_first_screen.png)

[![Windows 11 First Screen Login](windows_11_first_screen_login.png)](windows_11_first_screen_login.png)

So it can be done!

Since it can be done on Parallels Desktop version 16.5, which does not officially support Windows 11, I will not be surprised that we will find methods to install the system on computers that officially do not meet the minimum requirements.

> Of course, how fast (or slow) Windows 11 will run compared to Windows 10 will depend a lot on your hardware. Don't expect everything to run smoothly on old hardware with a mediocre graphics card.

When Windows 11 is officially released, I'll rush to see how to do it, because both at home and at work I have several computers that are not showing their age but still work flawlessly under Windows 10.

Interestingly, the last update to Windows 10 was marked as 21H1.

[![winver - Windows 11 - 21H2](winver_windows11_21H2.png)](winver_windows11_21H2.png)

Windows 11, on the other hand, is marked as version 21H2, so theoretically there is not such a big difference, and the requirements between the systems are significant.

What's funniest is that the WhyNotWin11 application showed me that I had no chance of running Windows 11 (including without UEFI) in my virtual environment.

[![WhyNotWin11 - Parallels Desktop](WhyNotWin11_parallels.png "WhyNotWin11 - Parallels Desktop")](WhyNotWin11_parallels.png)

Regards.

{{% ads-in-article %}}


---
## Preparing for Windows 11 - UEFI
- **URL:** https://dariusz.wieckiewicz.org/en/preparing-for-windows-11-uefi/
- **Date:** 2021-07-01
- **Tags:** Windows 10, Windows 11, UEFI, WhyNotWin11, MBR, GPT, mbr2gpt

### Content

Even though Windows 10 has settled in on our computers, Microsoft has prepared a real surprise for us — Windows 11. In addition, it announced that the update will be free — well, almost.

<!--more-->

Not everything looks so green.

Microsoft has indeed announced that the Windows 11 update will be free, but it has also added some hardware requirements, which means that devices older than 3 years may have a real problem.

However, these requirements are (constantly) changing. Right after they were published, a number of computer manufacturers poured a bucket of cold water on Microsoft and some of them were quickly "slightly" modified.

Despite this, everything still indicates that a large number of computers will not comply with the minimum requirements.

For now, there is nothing to worry about, because Windows 11 is not officially available yet. At this stage, [methods for installing a test version of Windows 11 on a laptop with an old third-generation Intel Core i5](https://www.youtube.com/watch?v=MgBwiVFhSgs) have already been created, so when the system is officially released, we will see what we have to do.

One requirement will unfortunately become a pain for owners of older machines, namely **UEFI**.

---

A large part of computers released after 2013 support booting the system using the so-called **UEFI** method and the older, so-called **Legacy**.

To boot (install) the system in **Legacy** mode, our hard drive must be formatted in **MBR** (Master Boot Record) mode. In this case, the system creates (in addition to the **Recovery** recovery partition) one system partition (500MB to 1GB) and the main one for the system and that's it.

In the case of **UEFI**, the drive must be formatted in **GPT** mode, which is why the way the system manages partitions is slightly different.

> That's it in a nutshell. If you want to learn more, here's the link: [UEFI - Unified Extensible Firmware Interface - Wikipedia PL](https://pl.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface).

To check if your computer is compatible with the current requirements for running Windows 11, you can use the [PC Health Check](https://www.microsoft.com/en-us/windows/windows-11) program from Microsoft (which has been temporarily suspended), but it's much better to use the [WhyNotWin11](https://github.com/rcmaehl/WhyNotWin11) application, available for free download from GitHub.

[![WhyNotWin11 GitHub](WhyNotWin11_GitHub.png)](WhyNotWin11_GitHub.png)

The application will tell us in more detail whether our computer will be compatible with Windows 11, and if not, it will also tell us why.

> If your processor only supports 32-bit, you can forget about Windows 11.

While we can initially ignore some elements, in the case of **Boot Method**, i.e. the way the operating system is started. If we have the inscription **Legacy**, we need to see if we can change it to **UEFI** before we can think about Windows 11.

If our computer allows it, we can change the boot mode from **Legacy** to **UEFI** without any major problems. Additionally, we will gain additional options in Windows 10 and newer systems, such as **Fast Boot**.

To check (**we do not change anything at this stage!**) whether our computer supports UEFI, we need to turn it off and then turn it on go to BIOS.

> Depending on the manufacturer of our computer, to enter the BIOS, when turning on the computer we must use the F1, F2, F10, F12 or other (different combination) button. For this purpose, I encourage you to read the information provided by the hardware manufacturer.

If in BIOS, usually in **Boot Options**, we find the option to switch from **Legacy** to **UEFI** mode, then that's good, but **let's not switch it yet!**. If we switch it without adapting our disk to boot in UEFI mode (**GPT**), our system will not start!

Some time ago, we would have had to reformat the disk in GPT mode, which would have required reinstalling Windows.

Fortunately, Microsoft has built a tool into Windows 10 that allows us to convert a disk from MBR to GPT without having to reinstall anything.

> This method requires a maximum of 3 partitions on your system drive. However, note that Windows 10 creates a recovery partition when you first install it **and** a system partition (usually around 500MB) preceding your operating system partition (**Drive C**), so you now have three partitions!

By running the command line (**cmd**) in administrator mode and executing the command below, you will convert your drive to boot in UEFI mode.

---

If we just want to check if it is possible to convert, we execute the command:

```
mbr2gpt /validate /allowFullOS
```

If we want to convert, we execute the command:

```
mbr2gpt /convert /allowFullOS
```

---

In my case, it turned out that somehow my system had created two recovery partitions, so I had a total of 4. This resulted in an error and the conversion did not occur.

Using the **diskpart** command from the command line, I selected partition 4 and deleted it.

> In fact, at this stage we can delete all partitions marked as **Recovery** because the above command (mbr2gpt) will recreate them during conversion and the first time the system is started.

{{% ads-in-article %}}

In my case my commands in **diskpart** looked like this:

```
diskpart
list disk
select disk 0
select partition 4
delete partition
exit
```

Yours may be slightly different. Basic knowledge of the subject is required.

Once our conversion has occurred without serious errors (I did this on 6 different computers), we turn off the computer.

When we turn it on for the first time, we go to BIOS and change the system boot method from **Legacy** to **UEFI**.

And so our system should boot without any problem and the [WhyNotWin11](https://github.com/rcmaehl/WhyNotWin11) application should report **Boot Method** as **UEFI**.

[![WhyNotWin11 - Lenovo E530c](WhyNotWin11_e530c.png "WhyNotWin11 - Lenovo E530c")](WhyNotWin11_e530c.png)

---

As I mentioned, there are several requirements for Windows 11. If our system (Windows 10) is 64-bit and the boot method is set to UEFI, we are one step closer to our compatibility.

Although we probably won't be able to meet all the requirements (e.g. DirectX 12, WDDM 2), we will have everything else ready. When it comes to installing Windows 11 using a "clever" workaround, as others have already managed to do in the testing phase, nothing will stand in our way.

Best regards.


---
## Virtual place for your "read-it-later"
- **URL:** https://dariusz.wieckiewicz.org/en/virtual-place-for-your-read-it-later/
- **Date:** 2021-06-27
- **Tags:** read it later, instapaper, pocket, reading list, safari, collections, microsoft edge

### Content

There are a couple of things that I cannot imagine doing when surfing around the internet. One is RSS/Atom to stay on top of new things on websites that I am watching (I wrote about it in a post: [Why RSS still matters in 2021?](/en/why-rss-still-matters-in-2021/)). The other important thing is a virtual place where I can save a website to come back to it or to read it later.

<!--more-->

> I will not be writing about adding a webpage to bookmarks, as the purpose of bookmarks is to add a website to which we will be going back frequently. And is a website bookmark not a bookmark to a specific post on a website. Those who use this differently shall read further.

When you find something interesting over the internet sometimes you don't have time to read it right now. It's pointless to add it to your bookmarks, as after you read it, you may no longer need it. There is no point to make a mess of bookmarks, instead, you need a place, where you can quickly access them, and same quickly delete them when they are no longer needed.

There are a couple of options available, and all of them can be used for free.

[![Instapaper](/images/2021/06/instapaper-min.png)](/images/2021/06/instapaper-min.png)

## Instapaper

Instapaper is the options that I am using daily. I have an app installed on iPhone that's adding a shortcut to the share sheet. When I am surfing in Safari and I see something interesting I am using the built-in share functionality and share (save) it to Instapaper. 

This will save my website on my list in Instapaper. I can then access that list later from an app or through the web. 

The lists are associated with not only a title and a short description but also with a thumbnail. Thanks to that you can visually see what this is.

Along with iPhone, I got installed an extension in Safari on macOS and in Microsoft Edge on Windows 10. Independently on which device I am surfing - at home or at work - I can quickly add something there to do not miss it and read/use (come back to it) when needed.

Before I started using Instapaper I used **Pocket**. 

[![Get Pocket](/images/2021/06/getpocket-min.png)](/images/2021/06/getpocket-min.png)

## Pocket

Pocket has almost the same functionality as Instapaper. Some apps and web browsers may have natively built extensions. For any other, you can easily add what needed and use it in the same way.

I chose Instapaper over Pocket mostly due to interface simplicity. It looks much better for my eyes than Pocket. 

If you prefer one over the other, it's totally up to you.

---

But what to do if you don't want to use third-party apps for this purpose? Some internet browsers got you covered.

[![Safari Reading List](/images/2021/06/safari_reading_list-min.png)](/images/2021/06/safari_reading_list-min.png)

{{% ads-in-article %}}

## Reading List (Safari)

Safari on a computer like on portable devices offering similar things, to two websites above. On Safari for macOS you just need to click plus (+) button to add an open website to Reading List. On iOS (iPadOS) you use a share sheet for this purpose. 

Together with iCloud synchronisation, you got quick access to your lists wherever you will need them.

This solution is good if you are looking for simplicity and don't want to rely on any third party website. Some privacy concerned people shall use this as the only alternative, as in Pocket as well as in Instapaper, your items on the list can be filled with some sponsored content, especially on free plans.

[![Microsoft Edge Collections](/images/2021/06/edge_collections-min.png)](/images/2021/06/edge_collections-min.png)

## Collections (Microsoft Edge)

Microsoft Edge (this Chromium-based) we got Collections that works like Reading List on Safari. Since Microsoft finally sorts our synchronisation along with different devices with Microsoft account, this is the option that can recommend.

Microsoft worked much better on Collections than Apple on Reading List. You don't just add them to the list. You can sort them out in folders and even *Add Comment* (note) to each element there.

---

Which solution you use is totally up to you. Either of them is good, and better to use them (especially these offered natively) than don't use them at all.

I know, that some people prefer to keep open tabs in web browsers, but they can be easily lost. Where what's on your list to read later is there for you and will not go, until you decide to do so.


---
## Why RSS still matters in 2021?
- **URL:** https://dariusz.wieckiewicz.org/en/why-rss-still-matters-in-2021/
- **Date:** 2021-06-26
- **Tags:** rss, atom, feedly, rss readers, feed readers

### Content

If you are a person who is just starting to be tech-wise, or you are an experienced user, who on daily basis monitoring various websites to be always up-to-date, you know that social media is not the place where you will look, it's RSS.

<!--more-->

I started with "tech-wise" wording, but that's incorrect. RSS is so powerful that it can be used widely in many different areas by people with various skill level. In reality, everybody who's using the Internet can benefit from it.

Derek Kedziora explained in his post: [A Gentle Intro to RSS](https://derekkedziora.com/blog/rss-guide), what is RSS and how to use it. I will add my word to that.

---

Imagine RSS (through RSS reader) as your inbox. Instead of getting emails, you get notifications from websites you follow about new things. These new things are published in so-called **feeds** where the latest articles landing on top.

Then the new article is published, the RSS feed is updated and if you are subscribed to receive notification from it, it will pop up like a new email in your inbox, like an unread article from that website (feed).

RSS is a technology that is implemented on most websites and doesn't require any external infrastructure to work. There is no infrastructure to maintain, so it is less likely that it will get killed by a company looking for cost-cutting. See Google, they are the best in killing their services.

For me, it's really strange if somebody will omit that on his website (unless the website does not provide new articles daily).

I know, that if I found a website that is publishing some interesting stuff and it doesn't have RSS (or Atom), and I cannot add it to my RSS reader, more likely I will lose a link to it and will never visit again.

Simple as that. 

What a shame to an author of the website, especially if he is publishing value posts.

> I mentioned "or Atom" as RSS and Atom are technologies that serve a similar purpose and can be used together. Most **RSS readers** can read Atom as well, and they are called **feed readers**.

With RSS you are only notified about what's new on the selected website. There is no algorithm messing with it, dictating what you shall read and what's not (like Facebook Feed). All new content is landing on top.

If you are using a service like Feedly, they will monitor websites for you. Once you log in back into Feedly, you will see which website has new articles.

> Unless you start from the **Today** page, then their algorithm will decide, which posts to bring you first (from only your list of posts).

[![Feedly](feedly.png)](feedly.png)

You can also maintain your feed locally. There are plenty of free RSS readers that will sync (check for new content in feeds) when you open an app.

I prefer Feedly to do this for me, as sometimes I may not have time for a week to open it and don't want to lose anything (some apps do not sync feed too far back).

Of course, after a week I will have 1,000+ things to go through, but with smart gestures and "mark all as read" I can manage this chaos. 

There are days, that I am monitoring certain topics, and I am reading only feeds, that are relevant at the time. This is why I organise mine in folders.

There are days, especially after the Apple conference, that number of articles raises an enormous pace and can reach 250 in just one evening from selected group of websites. This is where you will understand the "mark all as read" button.

My feeds are mostly aggregation of tech websites, however, I got some that publishing new recipes or reviews of new movies. 

As a dual lingual person, I got the advantage to be able to read in two languages even on the same topic. Based on what I read from the source (English) I can see what nonsense and conspiracy theory various authors, writing in Polish, are spreading. Sadly, that's the case.

> If you don't want to look silly, always read or verify somebody's theory at the source.

There are some, that concentrate to get hitting subject with zero-relevant content. Thanks to that I can quickly make my opinion and if needed, stop following it. 

What I follow or stop following is strictly up to me, hence there is no grief from authors that they suddenly, after publishing some nonsense, lost 100k followers.

Or, like some YouTubers, who instead of concentrating on their content checking analytics and complaining, that only the 30% of who watch their content subscribed to the channel. Pathetic.

> I hate YouTube, as it changed over the years massively. Not because of content and YouTubers, but because of Google, who abuse our privacy and try to monetise the website at all cost. Sometimes I simply give up watching something if [I got an ad every minute](/en/youtube-ads-make-you-mad-use-vinegar/) (or every 30 seconds I skip) and prefer to read the matter instead.

Going back to RSS.

{{% ads-in-article %}}

Starting with RSS is easy. Assuming you created a Feedly account (or chose an app for that), you just need to add your website using the plus (+) button and typing the website address (for example [https://smittenkitchen.com](https://smittenkitchen.com)).

[![Feedly - Add RSS](feedly_add_rss.png)](feedly_add_rss.png)

If the website has implemented an RSS reader, you will be able to follow it.

[![Feedly - Smitten Kitchen](feedly_smittenkitchen.png)](feedly_smittenkitchen.png)

Feedly will inform you, analysing the RSS feed for the website, how often authors are publishing new articles. I will avoid those publishing hundreds a day, as this is something that you will struggle to maintain and the whole purpose of monitoring the website to get you information-reach will lose its sense.

Before you click **the follow** button, you can click on the website and check, what last published articles are, and once again, decide before you commit.

[![Feedly - Smitten Kitchen Content](feedly_smittenkitchen_content.png)](feedly_smittenkitchen_content.png)

The content you follow is totally up to you.

Of course, Feedly will try to analyse your feeds and what you read. From time to time they will put some **sponsored** article into your feed, but that's the only price (unless you go into a premium plan) that you need to pay.

If you would like to follow my website and have been notified when I will publish something new, you just need to add my website address.

> For English posts: **https://dariusz.wieckiewicz.org/en/**
> 
> For Polish posts just: **https://dariusz.wieckiewicz.org**

Haven't you tried RSS yet? Give it a go.


---
## Microsoft 365 (SharePoint & OneDrive) backup for free with Raspberry Pi and Rclone
- **URL:** https://dariusz.wieckiewicz.org/en/microsoft-365-sharepoint-onedrive-free-backup-raspberry-pi-rclone/
- **Date:** 2021-06-05
- **Tags:** Microsoft 365, Microsoft 365 Backup, Office 365, Office 365 sharepoint backup, Office 365 onedrive backup, OneDrive, SharePoint, sharepoint backup, sharepoint rclone, Document Library, Shared Documents, backup, backup sharepoint, raspberry pi, raspberry pi onedrive, rclone, rclone sharepoint

### Content

When I started working for my employer, they were using an on-site server and file storage with overnight backups to external drives. Everything was limited by the broadband (internet connection) speed, which in England is quite crazy — business parks rarely have access to inexpensive fibre connections, whereas at home you can get cheap Full Fibre. When things changed (or rather, the company needed to invest in change), we moved everything into the cloud.

**We chose Microsoft 365 as our provider.**

Once the migration was completed and people had got used to accessing their files in the new way (which hadn’t changed much thanks to the integration of the OneDrive app with Windows, apart from the use of file links), I needed to find a method to back up all files in case of an emergency (or the accidental removal of important files by an employee).

Although Microsoft provides an option to restore files for a short period (typically 30 days), sometimes that may be too short — by the time you notice files are missing, it could be too late. It’s better to have a backup (even an old version of the file) than to have no copy at all.

Without going into costly online backup solutions, or even investing in **Microsoft 365 Backup** (with its pay-as-you-go billing model), I decided to build an inexpensive and relatively cheap long-term backup system — **and I did**.

<!--more-->

For this purpose, I used a Raspberry Pi with Raspberry Pi OS (formerly Raspbian OS). Initially, I used a Pi 3, but later moved to a Pi Zero W (_currently Pi Zero 2 W_), as the Pi 3 was overkill for this task. For storage, I used an externally connected hard drive (a 2.5" 1TB hard drive in a USB 3.0 enclosure) connected via a micro USB to USB converter. For power, I used a 2A @ 5V iPad charger with a USB to micro USB cable.

After a quick initial setup and running a few commands, the backup system was ready to go. I have been using it successfully since mid-2019, and now I would like to share it with you.

> Because **WebDAV** access for SharePoint in Microsoft 365 Business Standard has been deprecated, I have updated the guide below for SharePoint sites and their Document Libraries accordingly. I have also revised the setup method to account for configuring everything remotely over the network.

---

**You will need:**

* A Raspberry Pi with a minimum 8GB microSD card (for the operating system);
* A USB-connected external hard drive or memory stick (for external storage — capacity depends on your needs);
* A charger that provides sufficient power (especially when using an external hard drive);
* Raspberry Pi OS (previously known as Raspbian OS);
* Raspberry Pi Imager (official software).

---

## Raspberry OS

To install Raspberry Pi OS on the SD card, we will use dedicated software called [Raspberry Pi Imager](https://www.raspberrypi.com/software/).

[![Raspberry Pi Imager – main window](Raspberry_Pi_Imager_1.png)](Raspberry_Pi_Imager_1.png)

> Previously, I recommended downloading the [Raspberry Pi OS image](https://www.raspberrypi.org/software/operating-systems/) and using [balenaEtcher](https://www.balena.io/etcher/) to flash it onto the SD card. However, Raspberry Pi Imager now has an advantage over balenaEtcher, as it allows you to pre-set certain settings, such as password, hostname, and Wi-Fi connection. This means you can do everything remotely without needing to connect a screen, keyboard, and mouse for the initial setup.

On the initial run, you need to select your Raspberry Pi device (mine was _Pi Zero 2 W_) and choose the operating system.

> Here is a tip — **do not** choose the 64-bit OS. Not all software is yet available for 64-bit, especially on lightweight devices like the _Pi Zero 2 W_. For Microsoft authentication, we’ll be using a desktop environment and the lightweight Midori web browser, which is only available in 32-bit. Chrome would be overkill and a performance nightmare on such a device.

Under *Operating System*, select **Raspberry Pi OS (32-bit)**. Alternatively, if you want the lightest installation possible (_recommended_), scroll down and select **Raspberry Pi OS (other)**, then choose **Raspberry Pi OS Lite (32-bit)**.

> The following steps will be based on **Raspberry Pi OS Lite (32-bit)**.

Next, select the storage. Connect your SD card to your computer and select it.

[![Raspberry Pi Imager – with selections](Raspberry_Pi_Imager_2_with_selections.png)](Raspberry_Pi_Imager_2_with_selections.png)

Once you’ve made your selections, click the **Next** button. At this stage, you’ll be asked if you want to apply custom settings. I strongly recommend doing this and setting everything accordingly.

[![Raspberry Pi Imager – Would you like to apply OS customisation settings?](Raspberry_Pi_Imager_3_customisation_settings.png)](Raspberry_Pi_Imager_3_customisation_settings.png)

> In the **General** tab, I suggest setting the **hostname**, **username and password**, and **configuring the wireless LAN**. Scroll further to set the **locale settings**.

> In the **Services** tab, make sure to **enable SSH**, then click the **SAVE** button.

As mentioned earlier, we will need a desktop environment on our Raspberry Pi and the Midori browser for the setup, but we don't need it to run by default. We'll go through all the necessary steps later.

{{% ads-in-article %}}

## Initial setup

Following the predefined Wi-Fi connection settings from the earlier step, once our device is up and running, we need to connect to it over SSH.

```bash
ssh pi@192.168.1.188 -p 22
```

> Your IP address will be assigned by your router unless you have set a static IP based on the device’s MAC address.

Once we are connected, let’s update our list of software packages.

```bash
sudo apt update
```

### FTP (optional)

We may need access to our device over the FTP protocol to easily upload or download some files. The command below will install an FTP server on your Raspberry Pi.

```bash
sudo apt install vsftpd
```

Once this is installed, we just need to change one setting in the **vsftpd** service to enable write access over that protocol.

Let’s edit the `vsftpd.conf` file.

```bash
sudo nano /etc/vsftpd.conf
```

Uncomment (remove the `#` from) the line stating `write_enable=YES`.

Then, exit and save the file, followed by restarting the FTP service.

```bash
 /etc/init.d/vsftpd restart
```

### Desktop Environment

Let’s install a desktop environment, as we will need to run an internet browser to authenticate with Microsoft services at a later stage.

```bash
sudo apt install raspberrypi-ui-mods
```

### Lightweight Browser

Let’s follow this up with the installation of Midori, a lightweight web browser.

```bash
sudo apt install midori
```

### Remote Desktop

To be able to connect to our remote desktop using RealVNC, we need to install the server first.

```bash
sudo apt install realvnc-vnc-server
```

Once that is done, we will also need to install [RealVNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) on our computer.

To run the virtual desktop and connect to it using the viewer, we need to execute the following command:

```bash
vncserver-virtual
```

> By default, our desktop will run as `:1`.

Once it is running, we will be able to connect to it over RealVNC Viewer by connecting to `192.168.1.188:1`.

To shut down the remote desktop, we can use the command below.

```bash
vncserver-virtual -kill :1
```

---

If you prefer remote connection over the RDP protocol, you can do this by installing `xrdp`.

```bash
sudo apt install xrdp
```

Then, you can simply use the built-in Remote Desktop app in Windows or download the [Windows app](https://apps.apple.com/us/app/microsoft-remote-desktop/id1295203466?mt=12) if you are using macOS.


### Rclone

For the backup purpose, we will be using a package called [rclone](https://rclone.org/docs/).

To install it, use the following command:

```bash
sudo apt install rclone
```

### Screen

To be able to leave the backup running once we disconnect from the terminal, it is worth running it inside `screen`. We need to add this functionality by installing the package.

```bash
sudo apt install screen
```

Now, we are ready to set up our storage.

{{% ads-in-article %}}

## Storage

Let's start by formatting our drive with `exfat` before connecting it to the Raspberry Pi.

If you want to do this on the Raspberry Pi, I recommend using **GParted** — an easy, graphical tool for partitioning.

Let's install it as shown below, then run the virtual remote desktop and format the drive through the graphical interface.

```bash
sudo apt install gparted
```

GParted is not able to create an `exfat` partition natively, so we will also need to install additional utilities.

```bash
sudo apt install exfat-utils exfat-fuse
```

On the virtual desktop, go to **Pi Menu > System Tools > GParted**.

From **GParted**, select your hard drive from the top-right drop-down menu. It will typically be `/dev/sda`.

If there is no partition on the hard drive, we will create one.

If there are any existing partitions, remove them and start from scratch.

Create a partition formatted with `exfat`, as this will allow you to connect it quickly to your Windows computer or macOS and work efficiently on the saved files.

[![GParted - New partition](GParted_new.png)](GParted_new.png)

[![GParted - partition unformatted](GParted_unformatted.png)](GParted_unformatted.png)

In GParted, create an **unformatted** partition (this will create `/dev/sda1`), then format it to `exfat` from the terminal.

```bash
sudo mkfs.exfat /dev/sda1
```

### Mounting hard drive

Because I am using the **Lite** version of Raspberry Pi OS, the desktop environment is not triggered to run at boot, so the drives are not automatically mounted and available upon connection. To mount the drive, we will use the command below, which will set the default write permission to the user **pi**. This is important, as it means we will not need to run further commands with **sudo** all the time.

Before mounting, let’s create a mount point. I created mine at `/media/pi/O365`, so I need to create the relevant empty folders for this purpose.

```bash
sudo mkdir /media/pi
sudo mkdir /media/pi/O365
```

Then, simply mount the drive using the command below.

```bash
sudo mount -t exfat -o uid=1000,gid=1000 /dev/sda1 /media/pi/O365/
```

Confirm that it is visible by using the `df` command.

### Hard Disk Idle Spin-Down Utility (optional)

Depending on the type of hard drive we are using for the backup, it is worth considering preventing it from spinning down in the middle of the backup.

Let’s install the `hd-idle` package.

```bash
sudo apt install hd-idle
```

Once our storage is connected and mounted, we can execute the command below to set the spin-down time to zero.

```bash
hd-idle -i 0 -a sda
```

Now your drive is ready to use.

{{% ads-in-article %}}

## Rclone Configuration

It's time to set up our backup configuration with Rclone.

At this stage, we will be using the terminal (either remote or via the virtual desktop) and the internet browser (Midori) on the remote desktop.

> If you haven't done so already, initiate the virtual desktop with `vncserver-virtual` and connect to it using RealVNC Viewer.

```bash
rclone config
```

From the menu, create a new **remote** connection by pressing `n`.

Let’s **name** it _o365onedrive_ (for Personal OneDrive), and later, create another one named _o365sharepoint_ (for the SharePoint Document Library).

In the next step, we need to decide which service to use.

For Microsoft, select **Microsoft OneDrive**. This is the option for backing up both the user’s OneDrive folder and the SharePoint Document Library. This configuration will require an authentication token (not a password), which is why we will need to do this through Midori.

### OneDrive Personal

Let's select the **Type of storage to configure** from the list by number or by typing **onedrive**.

We don’t need to enter anything for `client_id` and `client_secret` (just press Enter to accept the default).

For **Choose national cloud region for OneDrive**, I’m keeping the default (global) selection.

When asked **Edit advanced config?**, answer **n** for No or just press Enter.

When asked **Use auto config?**, answer Yes or just press Enter.

At this stage, we will be presented with a local URL like `http://127.0.0.1:53682/auth?state=6W7rX_yb67gWJfySzz_WkA`, along with the message **Log in and authorise rclone for access** and **Waiting for code...**.

Copy that link and open it with Midori.

There, you will need to log in to your Microsoft 365 account following the on-screen prompts.

When everything goes well, you will see a simple page with the message **Success! All done. Please go back to rclone.** in Midori, and in the terminal you will get confirmation (**Got code**) that the code has been received.

At this stage, you can close the web browser and return to the terminal.

From the final options, you need to select the type of account.

Choose **1** for **OneDrive Personal or Business**.

> You may see SharePoint listed here as well, but more on that later.

In the last step (**Select drive you want to use**), confirm which drive to use by choosing **OneDrive (business)**.

One last step:
```
Drive OK?

Found drive "root" of type "business"
URL: https://contoso.sharepoint.com/personal/dariusz_contoso_com/Documents
```

We simply confirm with **y** for Yes (or just press Enter) and once again **y** for Yes to confirm that all is fine and the configuration will be saved.

---

Let's quit the `rclone` configuration now (press `q`) and check if we can see the folders in our configuration.

In the terminal, type:

```bash
rclone lsd o365personal:
```

This should bring up a list of directories on your personal OneDrive account. If all goes well, the configuration is ready.

---

### SharePoint Document Library

> In the past, SharePoint Document Library was accessed using the `webdav` protocol, but this method is no longer in use. Microsoft has shifted away from WebDAV-based access in favour of OneDrive sync and modern SharePoint integration.

```bash
rclone config
```

Create a new configuration – `n`.

Let's **name** it _o365sharepoint_ (for SharePoint Document Library).

For **Type of storage to configure**, select the option from the list or type `onedrive`.

Leave `client_id` and `client_secret` blank.

Select your `region` option (global default).

Answer No to **advanced config** and Yes to **auto config**.

Follow the new `http://127.0.0.1...` link in the Midori browser and log in with your account until you get the message **Success! All done. Please go back to rclone.**.

From the **Type of connection** options, select the one related to **SharePoint site name or URL** e.g. `mysite` or `https://contoso.sharepoint.com/sites/mysite` (URL).

On the next step, paste the link to your SharePoint Site (not to a Shared Directory folder or any other, but directly to the created SharePoint site where the folders are located), for example `https://contoso.sharepoint.com/sites/mysite`.

At the next step, you will have to **Select drive you want to use**.

Typically, this will be one of the first options related to **Documents (documentLibrary)**. If you have more than one document library, you will need to create a separate configuration for each document library folder.

One last step:
```
Drive OK?

Found drive "root" of type "documentLibrary"
URL: https://contoso.sharepoint.com/sites/mysite/Shared%20Documents
```

We just confirm with **y** for Yes (or just press Enter) and once again **y** for Yes to confirm that all is fine and the configuration will be saved.

---

Let's quit the `rclone` configuration now (press `q`) and see if we can view folders in our SharePoint configuration.

In the terminal, type:


```bash
rclone lsd o365sharepoint:
```

This shall bring you a list of directories in your SharePoint Document Library. If all goes well, the configuration is ready.

---

We will no longer need the virtual desktop, so we can kill it by executing the command `vncserver-virtual -kill :1`.

## Pre-backup steps

Now it's time to execute the commands that will start the backup process.

We don't need to do this on the Raspberry Pi OS desktop; we can run them via SSH.

Let's go to our mounted hard drive at `/media/pi/O365` and create two folders there, one for each configuration in `rclone`.

```bash
mkdir OneDrive
mkdir SharePoint
```

Now we are ready.

{{% ads-in-article %}}

## Backup

Run the `screen` command and execute the commands below inside it, so you can close the terminal and disconnect without cancelling the backup process. To return to the screen, log in via SSH and recall the screen using `screen -R`. If you have more than one screen running (more on this at the end), you will be presented with a list of screens and need to recall the specific one using its number, for example, `screen -R 693`.

### Backup – OneDrive

Here is my command to back up my `o365personal` OneDrive to my backup drive.

```bash
rclone copy --progress --update o365personal: /media/pi/O365/OneDrive --log-file=/media/pi/O365/OneDrive.log --log-level ERROR
```

This command will start copying our files from OneDrive into our hard drive.

As you see, the command will show not only `--progress` but also record in `--log-file` any errors encountered during file access. The `--update` option is used to update files that have changed rather than download and overwrite them, even if they are exactly the same. Very useful if doing a progressive backup into the same folder as before.

After a successful command, it’s always worth checking the logs.

### Backup – SharePoint

The following command will copy our "Shared Documents" folder on our SharePoint site.

```bash
rclone copy --progress --update o365sharepoint: /media/pi/O365/SharePoint --log-file=/media/pi/O365/Documents.log --log-level ERROR
```

---

In such a way, we have a great backup system for our files in Microsoft 365 Cloud (OneDrive and SharePoint).

Excluding the cost of setting this up — Raspberry Pi and external hard drives (and electricity) — there are no subscriptions to pay, and we maintain full control over our files.

The backup is not fast and may take several hours on SharePoint sites over 100GB.

I have been using this system for years now and have used it at least twice during that time to restore some crucial files.

## Resolving Raspberry Pi network issues

On my Raspberry Pi, I experienced an issue with WiFi that, from time to time, suddenly dropped the connection with my router, especially when tasks on the device finished and there was no network activity. It also crashed under heavy utilisation of the WiFi network. I fixed this in two ways.

### WLAN Power Management

Just before running the backup, I run the commands below to turn off any power-saving features related to Wireless LAN on my device.

```bash
sudo iwconfig wlan0 power off
sudo iw wlan0 set power_save off
```

### Dummy Network Activity

Along with the `screen` running my backup command, I run an additional screen where I just run the command:

```
ping 1.1.1.1
```

This silly thing helped maintain network activity and prevent the Raspberry Pi from crashing during the backup procedure, which can sometimes take hours to complete.

---

And that's all.

Regards


---
## Stop apologising for poor English
- **URL:** https://dariusz.wieckiewicz.org/en/stop-apologising-for-poor-english/
- **Date:** 2021-05-24
- **Tags:** motivation, language, improvement

### Content

Looking across various internet forums, from time to time I see people asking a support question, and straight away they add their apology for their poor English. 

Most of the time, the question, issue or general query is formed correctly. English and not native English speakers can read and understand what the author got on his mind. The addition to showing the author's weakness in the language (where he is not an English speaker) is unnecessary.

<!--more-->

It is unnecessary, but it sometimes shows the ability of that person to acknowledge that their language may not be perfect. He or she knows that, and by acknowledging it, I can bet that they are trying to be better in the future.

This some time ago applies to me, however, I know that right now I don't have anything to apologise for. 

I am not a native English speaker and never will be, even that I am permanently living in the United Kingdom, and the UK is my home. 

When I first come to the UK, I knew that my English was good, but not good for the way people been using it here, especially in Yorkshire. 

I work hard to get it better. Additional courses and working constantly on improvement point me to the statement that I will not apologise for my English anymore, as my English is good, and I am working constantly to be better. Writing and publishing on my website in English is one way to improve my language skills.

I made mistakes in the discussion, in writing, however, I am trying to learn from it as much as possible.

It is not straight forward as you think.

Been a Polish speaker, you cannot translate word-by-word what you want to say from Polish into English, as this will not make sense at all.

The way, how English is formed compared to Polish, is like reading part of the sentence from the back and then adding on the end what's been on the front. And imagine that my brain needs to analyse and process that. 

I am making mistakes. In writing, I know that my weakness is grammar, but it's as well for a majority of English people. There is a lot of people who struggle to write something that will have any kind of sense, even that they been born here and live here for a while in their life. However, they don't have that problem in ordinary discussion.

If you write something somewhere and people will come back to you with "sorry, I don't understand what you mean", then you can "apologise" for that (but not for your try to write in language, that is no commonly used by you in your life). Don't put yourself down. Re-read what you wrote down, and re-think what you want to say, and try to say this differently.

It's like learning new words. Pick one new word and try to use it at least 5 times during a week in conversation, and you will see that this word will not be new for you anymore.

Use supportive tools like [Grammarly](https://www.grammarly.com) or [Outwrite](https://www.outwrite.com). I am using them daily, and even that on every text that I write (fast, to do not forget what I want to say), I got red underlines showing me that I misspelt something. There is nothing to be ashamed of if you work towards self-improvement. Keep trying.

You shall be ashamed of you trying to speak/write in English when you don't bother about it (the form and way of using the language). When you are overconfident in yourself and do not accept any form of criticism, then you got a problem. If you not learn from your mistakes and not trying to improve, then people will know that your language is bad.

If you say/apologising for your language, then you are aware of your weakness, and I believe that you will not allow yourself to keep at the same point all the time, and you will try to improve.

I made common mistakes, that is hard for me to change, like describing things that normally (for English people) is referred to as "IT", where I tend to use "SHE" or "HE". It may sound strange but in the Polish language many sentences describing a thing referring to IT in personalised form. This may sound strange, but yes, that's how this language is built, and other around the world languages as well. It's tricky for our brain to change perception on describing all non-living things as IT.

It's like with magic "THE" in the English language (the moon), or "A" and "AN" (an apple). These things rarely have their equivalent in other languages. In Polish, these forms don't exist, and in many cases, they are combined with personalised form even when describing things.

This is why it is hard to translate what you want to say in Polish into English. It's as hard as trying to directly translate English into Polish. People will look at you, like you would like to talk to them like a prince, a person from a higher class, thinking that you are the master and they as just people. You will sound stupid, and if people will not start laughing at you (most will), they will ignore you. Only a margin will try to correct you and give something from them to you - their knowledge.

I learned this well. There is only a margin of people who would like to correct you when you missay or misspell something. They would like to help you to improve, only you need to want this help. The majority however will don't care, as long you make mistakes (and will not help you to correct), they will treat you as someone worse than them to their advantage.

So stop!

If you respect yourself and you know your weak points, stop acknowledging them to the whole world, as the world doesn't care about it.

Work and improve. Appreciate people, who, despite your mistakes, trying to understand you, and want to help improve you and your language.

{{% ads-in-article %}}


---
## Forget about slow memory sticks and slow portable hard drives, choose wisely.
- **URL:** https://dariusz.wieckiewicz.org/en/forget-about-slow-memory-sticks-portable-hard-drives/
- **Date:** 2021-05-22
- **Tags:** memory stick, portable hard drive, ssd, usb 2.0, usb 3.0, usb 3.1, write speed

### Content

The current price of storage devices fall drastically. Currently, you can buy 128 GB memory stick for as low as £8.99 on Amazon, however I will highly advise you against doing that, and here is why.

<!--more-->

If you look to purchase a high capacity portable device, don't waste your money (and later time) on cheap products that offer you barely 15 MB/s on **write** speeds and 30 MB/s on read.

If you plan to purchase something that can store 128 GB, you need to make sure that you will be able to put (**write**) data on it fast - as fast as you will be able to **read** them from it.

Most of our computers are equipped now with a blue USB 3.0 (or newer standard) port, allowing you to transfer data up to 5Gbit/s (625 MB/s), comparing to 0.48Gbit/s (60 MB/s) on USB 2.0.

The problem is that most portable devices for storing data are not able to use this speed at all.

If you will purchase 2.5" Portable Hard Drive, you will be able to get 70 MB/s on it. If it's some kind of good brand, where they use high spin speed hardware, you may get like 150 MB/s max.

With cheap memory sticks, you may get something in range 30 MB/s, and that's **just a read speed**. What's important is, is a write speed, and that's going to like 15 MB/s.

This digits may not tell you anything really, hence let put some example here.

The average large file that people carry right now oscillate in approx. 1500 MB. Do you know how long it will take you to save this file on your memory stick with 15 MB/s write speed?

The answer is 100 seconds (if you are lucky enough, and write speed is constant all the time - which rarely happens). This 100 seconds is below 2 minutes, and that's like 1% of you total storage offered.

It will take you in **perfect conditions** almost 2.5 hours to fill the stick till its full capacity.

> The rubbish equipment with 3 MB/s will save 1500 MB it in over 8 minutes! And full capacity over 11 hours. That's nonsense!

You may buy some good ones for over double the price, like SanDisk Ultra Flair but once again, they advertise you that they can offer up to 150 MB/s read speed and nowhere to find anything about write speed, which can be even 10x times slower than read speed.

> With this SanDisk Ultra Flair, depending on capacity, you may get from 40 MB/s (16G) to 100 MB/s (128 GB) on peak where average write speed is 30% lower at least.

With 70 MB/s (average) write speed, it shall take less than half a minute, and full capacity below half an hour. Not bad for the average user.

Portable Hard drives, averaging in 45 MB/s, this will take you around a minute to write the file and 45 minutes till full.

---

You may ask the question then, what for I need to use USB 3.0 that offering 5Gbit/s (625 MB/s) if I cannot use it?

To solve the problem with speeds, manufacturers released portable hard drives that are based on that same technology, like hard drives in modern computers - SSD (Solid State Drive).

Of course, SSD are available in different type of connection and technologies, and based on that in different speeds (and price).

One of the most popular and recommended is Samsung T5 1 GB but is a bit pricey (£106.99 in deal on Amazon). Comparing to the same storage in old technology from Toshiba for £37.99.

Samsung will offer you like 430 MB/s of read speed and approximately 330 MB/s write. That's not bad.

Our 1500 MB file will write on it in perfect conditions in just a couple seconds!

If you don't want to spend so much money, or you don't need so much space, there are other options for you to look at, or you can build your own and adjust when needed.

Sometimes building your own is not necessary, giving you any savings (like with building customised computers), but will allow you to build to the performance that you will require, but selecting components that will meet your needs.

---

{{% ads-in-article %}}

To build your own, fast and portable hard drive, you need to start with the case before you will find something that you will put inside.

This is not an easy decision. There is plenty of cheap cases promising you lightning speeds. However, in most cases they disappoint.

One of the good ones is this from SSK M.2 NVME prices £21.99 on Amazon.

The case is offering you full compatibility with USB C 3.1 Gen 2 and speed at 10Gbps (1250 MB/s) and hard drive connectivity via M.2 connection. With the right hard drive and connection in USB C 3.1Gen2, you can easily reach 1000 MB/s on write!

In box, you are getting USB C to USB C cable along with USB C to standard USB type A connector.

Having a good case, it's time to pick up the right drive to put inside.

The case supports M.2. NVME hard drives, and based on that phrase "M.2 NVME" We need to look for our hard drive.

One of the first that you will be offered will be Crucial P2 500 GB for £42.48 at the time that advertise you 2400 MB/s speeds - but what's the writing speed?

Despite descriptions that may state write speed (in that case 1900 MB/s), it's better to find some [benchmarks/reviews](https://www.storagereview.com/review/crucial-p2-nvme-ssd-review). Here you will find that you may have like 940 MB/s. It's fast and can be enough for portable usage considering 1250 MB/s port limit.

This will land you £64.47 for 500 GB or using WD Blue SN550 1 TB at £105.97.

Good quality portable hard drive with a similar level of performance will hike at £200 at least.

You can, of course, start with small capacity and expand when you need to, but need to remember, that same, like with memory sticks, lower capacity drives, even from the same brand and model tend to have lower  speeds.

Deciding what we need and what we can afford, we may be better off making our own device from scratch.

Personally, I used SSK case it with a drive that I got already available, which was Samsung PM961 128 GB M.2 that used to be fitted in a laptop that I upgraded. This drive shall offer 2800 MB/s read speed and 600 MB/s write speeds.

When connected to PCIe port, this is quite possible. In case the situation is slightly different.

On a computer from 2013 equipped with just USB 3.0 port (connection USB A > USB C), I got 200 MB/s on average write speed and 450 MB/s (read 900 MB/s) on a computer equipped with 10Gbit/s port in the latest USB specification (connection USB C > USB C).

Roughly 4 times faster than the fastest memory stick that I have in use.

Of course, its much slightly bigger than memory sticks, but still smaller than typical 2.5" slow portable hard drives.



---
## Not so fast with AVIF, WebP is still the way
- **URL:** https://dariusz.wieckiewicz.org/en/not-so-fast-with-avif-webp/
- **Date:** 2021-05-17
- **Tags:** AVIF, WebP, WebDev, image compression

### Content

When I moved to Hugo with my website, I looked to optimise everything and implement new techniques. Once Safari gain native WebP support back in 2020, I implement WebP following [PawelGrzybek.com - WebP and AVIF images on a Hugo website](https://pawelgrzybek.com/webp-and-avif-images-on-a-hugo-website/). The post introduced not only how to implement WebP (at the time when Hugo <0.83 haven't support it), but also shown how to go step further by implementing AVIF.

> This method require you to have WebP/AVIF files stored along with PNG/JPG and not relay on rendering them when the site is build.

I was interested in implementing this as well, but after some tests in my environment I decided not to, and here I will explain why (and it is not about browser compatibility — Safari incompatibility).

<!--more-->

---

There is so much hype right now about AVIF.

On recent post of [@tempertemper - AVIF image compression is incredible](https://www.tempertemper.net/blog/avif-image-compression-is-incredible) shown his impression on this image file format.

Still, based on my tests, this not convinced me to move forward... yet.

Majority of my graphics on my website are in PNG. Only some are in JPG format. Serving them in WebP gave my website significant lightness.

Most people claiming that overall reduction counts towards 75%. That's a lot, so why I am against?

---

Even before implementing WebP, I optimise (and still do) my images using an unreplaceable tool/website [Optimizilla](https://imagecompressor.com/).

I am using Optimizilla for every website that I am working with, and cannot find a better free solution that will give me such great compression results with some tweak option when needed.

On the @tempertemper website, you can read that, when in some occasions they saw WebP to be bigger in size than PNG/JPG, they not seen this yet with AVIF.

I can say that I have seen it.

> This may be up to the settings that they are using comparing to mines, but cannot check that, as post not going as far.

Here how its looking on my side, and why I am not impressed as much.

## Sample

Four heavy (optimised) JPG files:
```
284403  02-podrobka-2-biala-w-opakowaniu-min.jpg
296100  01-podrobka-1-pelny-kolor-w-opakowaniu-min.jpg
499831  35-oryginal-nike-pride-2020-z-gory-min.jpg
549876  28-oryginal-nike-pride-2020-w-pudelku-min.jpg
```
> Will call it as JPG1, JPG2 etc.


Four optimised PNG files with transparent elements:
```
181186  atom_1_o_aplikacji-min.png
306035  node_errors_3-min.png
338439  wireshark-dns-plain-min.png
358865  wireshark-dns-over-https-tls-min.png
```
> Will call it PNGt1, PNGt2 etc.

Four optimised PNG files without transparency:
```
13121  wise_2021-min.png
74866  Utternaces_Blog_Post_Issue_Mapping-min.png
117208  volume-limit-control-pl-min.png
333806  czynnosci-ustaw-glosnosc-automatyzacja-min.png
```
> Will call it PNG1, PNG2 etc.

WebP (v1.2.0) compression installed using brew:
```
brew install webp
```

And here is my compression command for WebP:
```bash
find ./ -type f -name '*.png' -exec sh -c 'cwebp -q 75 $1 -o "${1%.png}.webp"' _ {} \;
find ./ -type f -name '*.jpg' -exec sh -c 'cwebp -q 75 $1 -o "${1%.jpg}.webp"' _ {} \;
```

AVIF (v0.9.0) compression installed using brew:
```
brew install joedrago/repo/avifenc
```

And here is the one used for AVIF:
```bash
find ./ -type f -name '*.png' -exec sh -c 'avifenc --min 10 --max 30 $1 "${1%.png}.avif"' _ {} \;
find ./ -type f -name '*.jpg' -exec sh -c 'avifenc --min 10 --max 30 $1 "${1%.jpg}.avif"' _ {} \;
```

{{% ads-in-article %}}

## Results

| File | Size | WebP | AVIF |
| ----------- | ----------- | ----------- | ----------- |
| JPG1 | 284403 | 60840 | 79104 |
| JPG2 | 296100 | 66854 | 86324 |
| JPG3 | 499831 | 180972 | 228604 |
| JPG4 | 549876 | 215306 | 276431 |

> WebP 4, AVIF 0

| File | Size | WebP | AVIF |
| ----------- | ----------- | ----------- | ----------- |
| PNGt1 | 181186 | 65870 | 242066 |
| PNGt2 | 306035 | 419860 | 734210 |
| PNGt3 | 338439 | 236288 | 405783 |
| PNGt4 | 358865 | 243666 | 409365 |

> Original 1, WebP 3
> WebP 4, AVIF 0

| File | Size | WebP | AVIF |
| ----------- | ----------- | ----------- | ----------- |
| PNG1 | 13121 | 14006 | 8820 |
| PNG2 | 74866 | 98118 | 94033 |
| PNG3 | 117208 | 84568 | 37583 |
| PNG4 | 333806 | 119470 | 61995 |

> Original 2, WebP 2
> Original 1, AVIF 3
> WebP 0, AVIF 4

## Conclusions

Firstly, the compression time to WebP was **significantly** shorter than to AVIF, especially on PNG with transparency.

In JPG test, you can clearly see that both compression methods win over original (optimised) file, however WebP been better each time comparing to AVIF.

In PNG, the transparency situation slightly changed. WebP in one instance was greater in size than original. However, comparing this to AVIF, WebP win 4 to 0. Also, AVIF resulted increase even up to 100%!

Difference been seen in compression of PNG files that doesn't contain any transparencies.
In two instances, WebP loses to Original, where AVIF loses only once. However, AVIF win significantly to WebP 4 to 0.

---

I know that this test is not a scientifically based. On @tempertemper, it was highlighted that smaller file is better for various reasons. Concentrating on that, you cannot say that AVIF is the winner, as WebP prove the right choice for now.

On larger sample, when I decided to convert all my images I noticed, that there is no point at this stage for me to go into AVIF.

Of course, AVIF been developed back in 2019 (initial release 2018), where WebP is on the market for whey longer (2010). The algorithms and compressors improved over the time, so we can expect that AVIF will develop in the future as well.

Only hope that we will not need to wait another 10 years until it will be implemented in the Apple ecosystem. Unless they don't see the future in it, like they don't see in Adobe Flash, and we all know how it ends and who win.

Regards.



---
## Monitoring and limiting traffic in the local network on a router with OpenWrt
- **URL:** https://dariusz.wieckiewicz.org/en/monitoring-and-limiting-traffic-in-local-network-router-openwrt/
- **Date:** 2021-05-01
- **Tags:** OpenWrt, luci-app-vnstat, luci-app-nlbwmon, luci-wrtbwmon, luci-app-nft-qos, luci-app-qosmate, monitoring, ograniczenie transferu

### Content

As the number of users increases, it is time to introduce speed limits in the network.

While I do not need this on my home router, in corporate use, it is worth knowing who and how much is using the connection and, if necessary, introducing appropriate restrictions.

First, you need to find out who, and then how much.

<!--more-->

So let's start with the tools to monitor our connection.

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

## Monitoring

Depending on how much information we need, we can install two packages from the router: `luci-app-vnstat2` or `luci-app-nlbwmon`.

### luci-app-vnstat2

```bash
apk update
apk add luci-app-vnstat2
```

After installing the package, you will see an additional option in the menu **Status** > **VnStat Traffic Monitor**

By default, the application will be configured to monitor traffic in our local network (`br-lan`) and the basic Internet connection (`eth1.2`). If not, go to the **Configuration** tab and in **Monitor interfaces** select what we want to monitor.

[![OpenWrt VnStat Configuration](openwrt_vnstat_configuration.png)](openwrt_vnstat_configuration.png)

In the main section **VnStat Graphs** we have several methods of presenting the collected data.

**Summary display** we receive information in the form of data and graphs, how much data we have collected today, yesterday, this month and in the previous month.

[![OpenWrt VnStat Summary Display](openwrt_vnstat_summary_display.png)](openwrt_vnstat_summary_display.png)

**Top 10 display** will show us the 10 busiest days in our network. Of course, we have to allow our router to collect them, so we won't see everything at once.

[![OpenWrt VnStat Top 10 Display](openwrt_vnstat_top_10_display.png)](openwrt_vnstat_top_10_display.png)

**Hourly traffic** will show us the load for the last 24 hours. Similarly, **Daily traffic** translated into days and **Monthly traffic** months.

We will not receive any information about who has stressed our connection. This package will mainly serve us to analyze how much we use our connection.

### luci-app-nlbwmon

```bash
apk update
apk add luci-app-nlbwmon
```

This package gives us insight into even more information.

We have a dedicated **Bandwidth Monitor** menu (or **Services** > **Bandwidth Monitor**) with extensive configuration options (**Configuration**) and the ability to save data collected over time (**Backup**), as well as restore it. Particularly useful in the case of [firmware update](/en/firmware-update-openwrt/) on the router.

In the **Display** tab we will get a preview of how individual users in our network loaded our connection (**Traffic Distribution**).

[![OpenWrt nlbwmon Traffic Distribution](openwrt_nlbwmon_traffic_distribution.png)](openwrt_nlbwmon_traffic_distribution.png)

Including the division into protocols of individual applications (**Application Protocols**)

[![OpenWrt nlbwmon Aplication Protocols](openwrt_nlbwmon_application_protocols.png)](openwrt_nlbwmon_application_protocols.png)

If communication in our network takes place via both IPv4 and IPv6, the **IPv6** tab will show us how traffic is divided depending on the communication method.

What's more, in the **Export** tab we can save the collected data in several formats, allowing for their later analysis in external programs.

---

There is nothing against installing both packages and deciding which one is better in the next few days. A lot of users notice that `nlbwmon` skips some traffic, which is why its statistics are lower than `vnstat`.

Of course, it should be noted that in `vnstat` we can set which interfaces are to be monitored by it (by default our main Internet connection and local network). In the case of `nlbwmon`, the interface responsible for the local network is monitored by default (however, this also includes transfer from WireGuard clients, if we have it installed [according to my other post](/en/installing-vpn-server-on-router-openwrt-wireguard/)).

Overall, everything is fine, but I still feel there's something missing here.

So I would like to know what the current usage of the internet connection is. At a given moment, at what speed a given user is downloading something. This is especially important in the next step, where we will want to limit what some people do.

OpenWrt theoretically has a built-in monitoring system (**Status** > **Realtime Graphs**).

In addition to the graphical charts, we have the **Realtime Rate** tab, which **should** show live current bandwidth usage by individual IP addresses.

---

Once we have gathered information about who we need to impose restrictions on, it is time to implement them.

{{% ads-in-article %}}

## Bandwidth Management and Prioritisation

> Starting with OpenWrt 25.12, `luci-app-nft-qos` has been officially dropped. For modern `nftables` based rate limiting and prioritisation, we now use the `luci-app-qosmate` package.

```bash
apk update
apk add luci-app-qosmate
```

After installation, the **QoSmate** option will appear in the **Network** menu.

### Traffic Prioritisation (VoIP)
In the **Prioritization** settings, we can ensure that critical network traffic takes precedence over bulk downloads. This is essential for environments with multiple VoIP phones; it prevents a large file transfer from causing jitter or delays in a voice conversation. 

Once you enable the prioritisation engine, you can define rules based on ports or protocols. For instance, you can ensure the SIP/VoIP protocol (port 5060) is treated as high priority, while standard HTTP (80) or HTTPS (443) traffic is handled with a lower priority.

### Rate Limiting (Per-User Control)
In the **Rate Limiter** tab, we can impose specific bandwidth caps on individual users. To get started, you must first tick the **Enable** box. 

You can define limits based on IP addresses or MAC addresses. For the best results, it is highly recommended to assign fixed IP addresses to your devices via **Network** > **DHCP and DNS** > **Static Leases**. This ensures that your rules always apply to the correct hardware.

> **A note on units:** Pay close attention to the units used in the configuration. **Megabit/s (Mbps)** is not the same as **Megabyte/s (MB/s)**. A 100Mbps connection translates to approximately 12.5MB/s. You can use an online converter if you are unsure of the values to enter.

### Static vs. Dynamic Management
QoSmate allows you to set a **Default Rate** for any device not explicitly listed in your rules. For example, on a 100/100 Mbps connection, you might set the default for unidentified guests to 5/5 Mbps, while identified workstations receive higher limits.

One of the strengths of the modern QoSmate approach is its move toward more "fair" queuing. While `nft-qos` often relied on hard, static "policing" (which wastes bandwidth when the network is idle), QoSmate aims to keep latency low for everyone.

### The "Dynamic" Challenge
I am still looking for a perfect "middle ground" solution—the ability to keep limits low during periods of high demand, but allow a single user to burst to the full available speed when the rest of the network is quiet. It can feel restrictive to cap a user at 5Mbps if they are the only person in the building using the internet. As I continue to explore the advanced capabilities of QoSmate and its integration with SQM (Smart Queue Management), I will update this guide if I find a more flexible "burst" configuration.

> If you care about monitoring other parameters from routers in addition to transfer monitoring, the `luci-app-statistics` package will be indispensable for you. This package, together with the list of modules `apk search collectd-mod` will significantly expand the capabilities of our device.

Regards.


---
## Prevent sub-reports from ruining your report in Crystal Reports
- **URL:** https://dariusz.wieckiewicz.org/en/prevent-sub-reports-from-ruining-your-report-crystal-reports/
- **Date:** 2021-05-01
- **Tags:** SAP Crystal Reports, Crystal Reports, sub-reports, WhilePrintingRecords, suppress, Underlay Following Section

### Content

I like SAP Crystal Reports. Why? Because it helps gather the information needed and present them as I would like to, with just basic crystal reports design knowledge.

<!--more-->

I never planned to learn it until I started to work for my [current employer](https://www.andrewsfasteners.uk) years ago.

Despite years of learning how to use it for business purpose, there is always something new that I learn when I create a new report.

Mostly I am self-taught on it, but I can with easy call myself an advanced user now.

My reports are not only drag and drop fields from the database and display in the desired format. There is plenty of formulas, parameters, exclusions and inclusions, and of course, on some of them have sub-reports.

I am not going into sub-reports when I can achieve what I want using a standard approach. Really, sub-reports are the last thing that I am going for if I cannot see all the data I need.

There is one main reason why I am not using sub-reports in practice very often. They tend to break the way how I want the final report to look, and display data in preview.

The other reason is when you need to create a report that people will export (to Excel or CSV). Then, apart from layout issues, you face problem with duplicated values.

Recently I created a report that works as a middle-man between our main program and our digital board, displaying customers' orders on a designated screen for our warehouse staff.

Multiple different tables (live, in-progress and archive) are not designed to coexist on single report. This time it was not possible to achieve all what we need without going into sub-reports.

Knowing how bad reports looks with embedded sub-reports, I knew that I need to find a way, as in other case, output can cause a serious problem for the company (duplicated orders).

And the solution for that issue so simple that I was amused, that I haven't fought about it before.

But, starting from the beginning.

> I will not be explaining how to use sub-reports here. Let's assume that you know this already.

When in sub-report you try to get a value into the main report, you use something like that in **Formula Fields**.

```sql
WhilePrintingRecords;
Shared NumberVar Items := DistinctCount ({sopdet.part})
```

You put this field into your sub-report.

Then you create another one in Formula Fields inside the main report like that.

```sql
WhilePrintingRecords;
Shared NumberVar Items
```

When you put this field into your main report you see, that records **/or/** not showing **/or/** are moved by 1 place (row 1 displaying figure for row 2 etc.).

To you need to put your sub-report one section above (for example, by creating **Details section A** and **Details section B**, where A contain sub-report and B contain your formula field from which you take specific data in the main report).

[![Crystal Reports - Report with two Details sections](/images/2021/05/crw32_report_with_two_details_sections-min.png)](/images/2021/05/crw32_report_with_two_details_sections-min.png)

What you are interested about is to get specific data and display it in **Details B** section.

You not really bother with **Details A** and sub-report there. You really would like it to disappear. However, this section is needed to be able to work and bring data, but not needed for the purpose of displaying data in preview.

You **cannot** suppress **Details A**, as this will not bring any data into the field in **Details B**.

What you can do is to head to your **sub-report** and **suppress every single section there**.

[![Crystal Reports - Suppressed Sub-Report sections](/images/2021/05/crw32_suppressed_sub_report_sections-min.png)](/images/2021/05/crw32_suppressed_sub_report_sections-min.png)

Despite that sub-report, all sections have been suppressed, and the data are still passed through to the main report.

In **Details A** on the main report, where the sub-report probably will throw multiple output lines, you will have now an empty section (single line).

Because its theoretically empty, the main report still not showing correctly in Preview, as this section - **Details A**, is dividing your data in preview from **Details B**.

To get rid of it, you can, by right click on **Details A** section and selecting **Section Expert**, tick the box to **Underlay Following Section**.

[![Crystal Reports - Underlay Following Sections](/images/2021/05/crw32_underlay_following_sections-min.png)](/images/2021/05/crw32_underlay_following_sections-min.png)

Thanks to that, section **Details A**, that's printing blank single line will be placed on top of **Details B** on preview.

> You can also adjust Details A height to match Details B.

In such way, preview is neat.

{{% ads-in-article %}}

Here how it looks on each stage on my example report:

{{% gallery %}}
[![Crystal Reports - Preview - with sub-report](/images/2021/05/crw32_preview_1_with_subreport-min.png)](/images/2021/05/crw32_preview_1_with_subreport-min.png)
[![Crystal Reports - Preview - with sub-report suppressed](/images/2021/05/crw32_preview_2_with_sub-reports_suppressed-min.png)](/images/2021/05/crw32_preview_2_with_sub-reports_suppressed-min.png)
[![Crystal Reports - Preview - with sub-report suppressed undelayed](/images/2021/05/crw32_preview_3_with_sub-report_suppressed_underlayed-min.png)](/images/2021/05/crw32_preview_3_with_sub-report_suppressed_underlayed-min.png)
{{% /gallery %}}

Of course, on export of the report to Excel, you may still have empty rows, but that's better than duplicated data. This can be easily removed in Excel (hidden) using the funnel option in the Data section.

In case you export to CSV, then you got clean data, without duplicates or extra empty lines. This was particularly useful for me, and my solution where I used it.

Thanks to that "trick", working with sub-report become much easier and not breaking the way, how you would like your preview to looks like.

**Regards.**



---
## From WordPress lover to WordPress hater
- **URL:** https://dariusz.wieckiewicz.org/en/from-wordpress-lover-to-wordpress-hater/
- **Date:** 2021-04-24
- **Tags:** WordPress, Jamstack, free thoughts

### Content

Since I migrated my personal blog to Hugo, I dusted off my knowledge for HTML and CSS. It's like been back in 2008, with some extra magic available.

When WordPress starts been popular, I been using it on every project. Luckily, that's not a case anymore.

<!--more-->

WordPress is a great tool, you cannot not say it. However, the development of the site is a pain (unless you got a staging environment). It requires you to be constantly on guard. You need to been on top of new releases, changes in script and its plugins. You need to make sure your website is running smoothly, all components working each day, keep your fingers crossed, to do not be hacked.

Problem is starting, when you look on it from the side of JamStack user and environmentalist (which I am not, but trying to do my bit to save the planet).

WordPress requires a lot of resources, and that's bad for our wallet, as when our website grows, then we need to start spending more. Increase need of processing power, memory, storage, and in result energy is not good for our environment as well. 

When sites used to be written in "notepad", in HTML, all been simple. Growing popularity of Jamstack in making websites bringing this simplicity back to the internet.

The change is on the horizon, and even Wordpress lovers see that, discussing recently about WordCamp sponsors who, despite sponsoring them, demoting the use of Wordpress. How's ironic!

How easy would be if WordPress could offer back end as we know, but the front end generated statically? This will bring evolution to WordPress and cuts its impact on the environment (of course you can use plugin for that, but that's not that same).

My hate to WordPress start growing slowly. Yours, as an WordPress user, may grow even slower, but at some point you may see the pain of been tightened to the solution, that is ripping a hole in your pocket (and in the environment), unless some drastic change will be pushed forward.

{{% ads-in-article %}}


---
## Migrating business site from Namesco to SiteGround
- **URL:** https://dariusz.wieckiewicz.org/en/migrating-business-site-from-namesco-to-siteground/
- **Date:** 2021-04-21
- **Tags:** Namesco, SiteGround, Core Web Vitals, SG Optimizer, migration, WordPress, Cloudflare

### Content

For over a couple years my [employers website](https://www.andrewsfasteners.uk) been served from shared hosting solution on [Namesco](https://www.names.co.uk). On recent years however, we feel that we been left behind. It started with just PHP, where we stick with the 7.3 version without not plan to go into 7.4 and not thinking even with 8.0. Until significant issues with performance of the servers (where even Customer Support couldn't help without persuading you to migrate to dedicated servers), it was time to think what's next.

<!--more-->

Despite heavy use of **[W3 Total Cache](https://wordpress.org/plugins/w3-total-cache/)** together with [Cloudflare](https://www.cloudflare.com/en-gb/), where the front end served to customers (oscillating in 350 people in weekdays) seems to work fine, any work on the back end was a constant pain. Working with Wordpress shall be fluid. I personally, as a person responsible for managing the website, hate it.

When websites like [GTMetrix](https://gtmetrix.com) start dropping us in performance results, once we hit the read, I said enough and start looking for a change.

In the same time, where in 2021 website speed start matters the most, I struggle to improve **[Core Web Vitals](https://web.dev/vitals/)** of the website, and sooner or later we will see a drop in Google results and visitors.

Where in the past (around 2015) we used couple solutions  like TSO, and even one in Poland on Polish servers, we stick with Namesco as a good value for money. As this value stop representing the money that we were paying, decided to go on a hunt.

I was thinking even into purchasing a **[WP Rocket](https://wp-rocket.me)** plugin to improve performance until I read again about [SiteGround](https://www.siteground.co.uk) and their hard work into bringing [SG Optimizer](https://www.siteground.co.uk/tutorials/wordpress/sg-optimizer/) into live, who people compare to WP Rocket as a competitor on their servers

Even that SiteGround state, that website on their servers can work together with WP Rocket, I planned to put their **SG Optimizer** to the test, along with Cloudflare that we use for some time, and see how this will go.

Our site is not big (slightly over 1 GB including all files and 50 MB in MySQL database), however, it has a quite decent number of visits, as it contains plenty useful informations for our customers.

Waterfall on GTMetrix shown between 1-2 MB of our home page, which I think personally is a lot, especially that privately I am using Hugo for blogging, and my website in waterfall goes below 512 KB.

But nothing annoy you when somebody from Namesco is changing something in a code of your website without informing you and without any particular reason. Many times I personally put a change into our Wordpress Theme to realise that it been changed back to old code at some point (possibly they restore from backup?). That's totally unacceptable!

---

So I started migration to SiteGround at the end of January 2021.

To avoid any caching issues, I turned off caching plugins and put Cloudflare into development mode. Then I followed automatic migration process via the SiteGround Migration plugin.

In background, I've been observing cPanel on Namesco and noticed a lot in RED from I/O on 1.46 MB/s as 100% (!) and memory usage in the range of 860 MB. I was a little worry as progress bar not appear for a couple minutes, but suddenly there was a light in the tunnel.

I struggle to find what are the I/O limits on SiteGround, so hope that will not discover this shortly, and this will become a big issue.

I started on the StartUp Hosting package before I read that for using Dynamic Cache and MemCached, you need at least GrowBig, but even that I decided to move and see.

MemCached may not give me performance that I am expecting, but if Dynamic Cache will give me a boost, I will consider upgrade (I later upgraded to GrowBig, and this was a good decision).

---

At the time of last renewal, I paid £120.99 for cPanel Professional hosting, and additionally to that £24.99 for cPanel Backup (R1Soft Restore Backup) on Namesco.

On SiteGround, I started with a promo offer for £5.99 per month, paid annually (£71.88), which included daily backups, so I been still in the budget.

I started the migration process 10 minuted before 7pm. 10 minutes later, I saw progress in the migration plugin with a message starting file download.

During this time, cPanel on Namesco were screaming of almost 90% CPU usage, with slightly less memory usage, but still in Yellow.

Further, 10 minutes later it's been at just over 1100 downloaded files from nearly 9000.

After another 10 minutes+ passed 2000 files. It looks that this will take at least an hour to finish (this step).

An hour and 10 minutes later, we have been close to 8000 files...

An hour and 20 minutes later, all files were downloaded, but migration was far from over, as it just started site migration... just to finish with **failure**!

What I noticed, it mostly failed, as suddenly **migration key become invalid** (?). Possible, as I generated it at approx 3pm that day and started process just before 7pm, this will give approx 6 hours life of the key. Fair enough.

Despite that migration guide advise moving manually in case of issue, I decided to try again and then [follow it](https://www.siteground.com/tutorials/wordpress/move-copy/) if needed.

And so on, 10 minutes to 9pm of the migration day started again. This time, hours later it failed again (11:20pm)!

Failing reasons are unknown, but as is mentioned in the Error message, it more likely due to differences in the hosting environment. Namesco is using Apache for default and SiteGround Nginx.

Funny thing is, that I received emails from SiteGround that migration finish successfully (!?!).

At this time, I was thinking about manual migration, as mentioned above.

Before I did that, I need to move my redirections (from Apache format in .htaccess into Nginx). I been using [Redirection plugin](https://wordpress.org/plugins/redirection/), hence just head to plugin settings, section Import/Export, and selected export Everything in Nginx rewrite rules. Then when the website will migrate, will need to import Nginx rules.

To avoid temporary issues with redirects, I have moved my redirects into Wordpress group (despite that native redirect are faster, this will be more compatible than not having them working for start). I need to remove them manually from .htaccess file as well, as plugin don't seem to do this for me (which I discover painfully at a later stage of migration).

Before I start manual migration, I need to delete content of the public_html folder in my domain on SiteGround servers, that contained remaining files from failed migration. I used **File Manager** for that in **SiteGround Tools**, as it's faster than via FTP (Dashboard > Site > File Manager). I remove also, created by migration process, databases (MySQL).

As I prepared myself for manual migration, I started from cPanel on Namesco and their File Manager, where I compressed my website folder into .tar.gz archive which I later downloaded into my computer. On the next step, I dump my database from phpMyAdmnin (I am always using Custom Export where I am selecting output as gZiped).

In such a way, I finished with two compressed files, one containing my sight and one containing database. Good backup in case some hick-ups.

> Off-course, you can ask SiteGround employees to help you with migration, but as you already half-way through (have your files and database ready), don't think that it's needed to spend extra 20 pounds for that, unless you are not sure what you are doing.

I was moving this site a couple of times in the past, and think I will handle this one, despite that I haven't got too much experience with Nginx.

So let's start with it using provided [tutorial](https://www.siteground.co.uk/tutorials/wordpress/transfer/).

Before I will start importing files, I will need to create a new MySQL database on the SiteGround side. After that's done, the fun will begin.

---

{{% ads-in-article %}}

On the next day, I uploaded extracted database into the server and do Import Database Dump from Tools panel.

All been simple.

Then I went into phpMyAdmin, and what I noticed was a pain for Namesco that their default engine was MyIsam, on Siteground was InnoDB, which was an additional plus. I just needed to convert remaining MyISAM engines into InnoDB, and all done for now (shortly speaking, speed prevail). Some time in the past, I spoke with Namesco Customer about that and struggle to get a positive approach on database engines.

Next is to upload my files.

After that, just updated my wp-config.php file and pointed Cloudflare to the new server, and have been ready to go. Surprisingly, everything works fine on front-end and back end require slight TLC.

First run of GTMetrix didn't show any improvement, however Cloudflare cache was off as well as other plugins.

Activated SG Optimizer and straight away I want to activate Dynamic Cache, hence need to upgrade to the GrowBig plan, which I did.

After all settings done on plugin, I re-run Performance tests.

Firstly, I run Speed Test inside plugin, which shone 80 on Desktop and 61 for mobile on homepage, which is quite poor.

Retest on GTMertix shown slight improvement from E to F on Canada server and C on UK one.

There is nothing better however than results shown in [web.dev](https://web.dev) website.

Web.dev for home page shown Performance at 51% (lot to improve still), Accessibility 94, Best Practices and SEO at 100.

> Off-course, on the initial tests, the Cache just start to build up, hence I cannot assess yet that all is working well and speed increased compared with Namesco. At least I don't have for now an issue with my Wordpress back end.

On the following weeks and months, I checked everything and been very please that I could work in the back end without pulling my hairs. All been very responsive and don't have any warning about limited resources (that I have on TSO host!).

Since the website been hosted at Namesco, I always got some errors reported at Google Search Console, which I now reported for re-evaluation to see if different hosting fix some of them.

Doing [web.dev](https://web.dev) and [PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/) checks for selected part of the website noticed that I need to enable **Combine CSS** in SG Optimizer. Typically, this was done by plugin Autooptimize, however SG Optimizer got this as well, hence will not duplicate this functionality.

From time-to-time, I used to have issue with Images, especially with displaying WebP Images. I used **[EWWW Image Optimizer](https://en-gb.wordpress.org/plugins/ewww-image-optimizer/)** by default, and during migration I moved already generated WebP files as well. When using SG Optimizer as a replacement, I removed all WebP images and Bulk regenerate them with one click.

As this process was time and resource consuming, I decided to do that in the evening hours when the number of visitors on our website is not such big.

Apart from using Dynamic Caching, I turned on MemCached as well.

---

Time for clean-up.

**[Async JavaScript](https://en-gb.wordpress.org/plugins/async-javascript/)** plugin replaced by SG Optimizer (Front End Optimisation > Defer Render-blockin JS.

**[Autooptimize](https://wordpress.org/plugins/autoptimize/)** (very good plugin from the same author as above) also been replaced with SG Optimizer and Front End Optimisation.

**[W3 Total Cache](https://wordpress.org/plugins/w3-total-cache/)** for obvious reasons is not longer needed.

**[EWWW Image Optimizer](https://wordpress.org/plugins/ewww-image-optimizer/)** removed.

**[Heartbeat Control](https://wordpress.org/plugins/heartbeat-control/)** (by WP Rocket) alternative is also included in SG Optimizer hence removed it as well.

Shortly speaking, even on the GrowBig package, for what SG Optimizer offering, including free daily backups in their Site Tools, its was worth the move.

The only thing I struggle to connect Cloudflare on SiteGround Tools, which I would need to reach Customer Service. Initially all worked well, including Cloudflare, hence not sure if that integration is needed (after month confirmed that probably not), however still need to ask question, as don't see the option in SG Optimizer to purge cache from Cloudflare as well when post is published or updated.

In a mean time I installed the official Cloudflare plugin (which I not used due to the same functionality in other plugins) that help me with the above issue.

> As been advised by Customer Service, as I am using DNS servers and full management through Cloudflare, there is no need to add Cloudflare in Site Tools.

Just in Cloudflare plugin, I enabled auto purge cache when something changed on the website, and that's all for now.

Almost...

One more thing. I got into Wordpress back end > Site Health (from Tools), where firstly got a notification on PHP 7.3, where recommended by WordpPress, was 7.4, so change that without problem in SiteGround Site Tools. By the way, SiteGround at this time marked 7.3 as recommended.

Other thing highlighted, there was missing optional package `imagick` but SiteGround website quickly gives me a [method to enable that](https://www.siteground.co.uk/kb/enable-imagick-imagemagick/). Super!

As everything start working well, it was time to say goodbye to Namesco (almost).

---

> I noticed that going into GrowBig or higher package, you got to disposition Staging Copies of my website. Thanks to that, there is no need to do local deployment  before putting it live. This function is particularly interested in me and will be checking that on the following weeks, as recently local development become pain for myself.

And so on, couple months later (mid April), everything been working really well. Site was responsive, nobody complained, and (after doing some tweaks in code - which I am still improving from the original theme developer), I started gaining back in Google Search Console Core Web Vitals.

Despite that website start to be showing in green on Mobile and Desktop (web.dev and PageSpeed Insight itself), Google approach with 28 days validation, to tell you that validation failed or pass start annoying me, but I saw a light in the tunnel.

All the migration has been a big success, and the work that been put towards SG Optimiser was so incredible, that I don't need to use anymore any other caching and performance plugins. 

As I calculated, when times will come, renewal of hosting will be more expensive than on Namesco, however the time that I spent solving issues with them, and then performance gained through SG, compensated it all.

---

Overall, through recent months, WordPress start been less and less useful tool for myself, and for any new projects I am starting to use Static Site Generators like Hugo.

For our company's website, it may be too early (mostly due to WooCommerce), however, we are already looking into options, how to improve the site in the future.

For now, I will concentrate to bringing current theme (on back end site mostly) to modern techniques of HTML and CSS, as theme developer (external company) who created it initially (I changed it a lot since then) put some silly HTML/CSS solutions that are far from modern practices. This was back in 2014, hence since then, a lot has changed.

Time will show what will happen next, but at this stage SiteGroud is my recommendation for business users.

And so on, I said goodbye to Namesco, but not fully. I still pay with them for domains that we hold. And even we could move them across, Namesco, to release them from their company, is asking for [a fee](https://www.names.co.uk/support/articles/transfer-a-domain-away-from-names-co-uk/) (like an extortion) that in mostly equal or more than annual extension of single domain. They claim that this is an administration fee, which I disagree. 

As this is not cost effective, I will stick with them for that only purpose.

Regards.


---
## Maximise use of Microsoft 365 Business Basic license (formerly Office 365 Business Essentials)
- **URL:** https://dariusz.wieckiewicz.org/en/maximise-use-of-microsoft-365-business-basic-license/
- **Date:** 2021-04-20
- **Tags:** Microsoft 365, Microsoft 365 Business Basic, Office 365, Office 365 Business Essentials, Microsoft Entra ID, Azure Active Directory, Azure AD

### Content

If you are looking for a good solution for emails and file storage for your business, independently how big or how small it is, the Microsoft 365 (was Office 365) is the best solution on the market. If you are not a big company, probably you don't want to burden to many costs, the Microsoft 365 Business Basic (formerly Office 365 Essentials) is something that you shall look forward.

Even if your business is trying to migrate from on-premises Windows Server into the cloud, in most cases, you can achieve what you need for just £4.90 per month per user. The money well spent. Let me show you why.

<!--more-->

Soo... the question why?

Microsoft 365 Business Basic offering you way more than is written on the label, and this is why you shall explore all function, to use as much as possible from this £4.90 per month per user (with annual commitment).

## What's on the label

Let start reminding what Microsoft 365 Business Basic offering for your business ([as per official site](https://www.microsoft.com/en-gb/microsoft-365/business/microsoft-365-business-basic)):

- Host email with a 50 GB mailbox and custom email domain address.
- Create a hub for teamwork to connect your teams with Microsoft Teams.
- Access web versions of Office apps: Outlook, Word, Excel, PowerPoint, OneNote (plus Access and Publisher for PC only).
- Store and share files with 1 TB of OneDrive cloud storage per user.
- Host online meetings and video conferencing for up to 300 users.
- Get help anytime with around-the-clock phone and web support from Microsoft.

Now, let's say what Microsoft is not trying to tell you (or is hiding it slightly [deeper](https://www.microsoft.com/en-gb/microsoft-365/business/compare-all-microsoft-365-business-products)), so they can convince you to go with a higher plan, which for start you may not really need... **yet**.

Here are some features that I discovered over the last years when I moved my employer into Microsoft Cloud. The features that you business will appreciate, especially, that they are available in just a basic plan.

## Microsoft Entra ID and Windows integration

What used to be in companies who use on-premises Windows Server, that their users log-in on their computers with user-profiles that been pulled from server resources. This kind of solution allow syncing user settings and files in case user need to log-in into a new computer. Quite clever solution with big issue. This doesn't sync apps. The apps need to be installed on a new computer to be able to use with files and shortcuts that been pulled with the user profile.

Of course, you can use special scripts and group rules to install whatever need to be installed, which you will not find in your basic package of Microsoft 365, however if you look into files only, there is basic Active Directory available, which together with OneDrive will allow you to achieve the most of what you used to have from on-premises server.

Personally, I am preparing the user's computer, installing the required software, etc., before the computer is passed forward. Then, just login into the relevant account and all set (after it's synced).

Windows 10 or 11, together with Microsoft 365 in its basic package, allow you to add a computer and its user to company infrastructure (like on-premises Active Directory) in cloud - currently called Microsoft Entra ID (formerly Azure Active Directory or Azure AD). You will require Windows Professional edition to do that.

> Below screenshots showing **Join this device to Azure Active Directory** which, in latest Windows 11 it will be shown as **Join this device to Microsoft Entra ID**.

[![Settings > Accounts > Access work or school](/images/2021/04/Settings__Accounts__Access_work_or_school-min.png)](/images/2021/04/Settings__Accounts__Access_work_or_school-min.png)

[![Settings > Accounts > Access work or school > Join this device to Azure Active Directory](/images/2021/04/Settings__Accounts__Access_work_or_school__Join_this_device_to_Azure_Active_Directory-min.png)](/images/2021/04/Settings__Accounts__Access_work_or_school__Join_this_device_to_Azure_Active_Directory-min.png)

Then you just need to sign-out and login using Option **Other** from the login screen, where you will use your email address in Microsoft 365 and password.

Thanks to that, you or other user can log in into his computer using his email and password, and the administrator still got full control on credentials. When needed, can revoke or prevent the user from accessing the computer (logging in) and files stored there.

Off-course, Entra ID (Azure AD) is not available in its full glance. You will still need a licence for that, but in the basic version you will be able to connect and (an admin user) manage access wherever its needed.

Without paying extra pennies, you have for your disposition [Microsoft Entra admin center](https://entra.microsoft.com/) (formerly know as Azure Active Directory admin centre).

Again, without extra licence, you cannot push any Group Policies to user computers, however you will find some interesting options there, worth to use.

What you may not know, you can use Microsoft Entra ID to login into Windows computer by unlicenced users, who don't need to have attached a paid licence! You can use your licences for these users, who need to have e-mails **mailbox**, all others can be **Unlicensed**, and they will still have some functionality.

You can create an email address for them that will be used for logging-in, but without licence they will not be attached with mailbox, hence their email details will only be useful for device login. Good option for limiting the ability to send emails for users, who shall not have the option for that. Have the user ready in such a way, opening you an option, when needed, to attach the required licence, and the mailbox will be enabled/created when needed.

## Email signatures - disclaimers
In the company that I am working in, when we have on-site Windows Server, we used to use Exclaimer to insert business signatures to users' emails.

When migrated to cloud, you can still use this kind of software, but moving into a sort of cloud solution, but what you will do, if I will tell you that there is no need for that, and you can achieve this kind of solution using build-in options available in your basic 365 package.

Yes, its possible.
It may not be as perfect and as flexible, like Exclaimer (which I will let you know how further in text), but it's a really good solution.

From [Microsoft 365 admin centre](https://admin.microsoft.com/Adminportal/Home#/homepage) you are heading to [Exchange admin centre](https://admin.exchange.microsoft.com/#/homepage).

Inside **Mail flow > Rules** you just need to create for users in your organisation.
- **Name:** Disclaimer
- **Apply this rule for:** The sender is...
	- (Select these users, to who this will apply in your organisation)
- **Do the following:** Append the disclaimer
	- (here you can paste your disclaimer in HTML format and even using [dynamic fields](https://docs.microsoft.com/en-us/exchange/policy-and-compliance/mail-flow-rules/signatures?view=exchserver-2019) like `%%DisplayName%%`. 
- **Except if:** The sender is...
	- (It's worth to add users who will have different rule - different signature added)
- **or** The subject or body included...
	- (here is worth to add part of your disclaimer text, so this will work, that full signature will be pasted when there is no disclaimer stated, and when is, you will create other signature for that - other rule).

Other bits and bats, like which rule need to be used first (**Priority**) and that rule shall be **Enforced**, is really up to you.

Personally, in our organisation, we got two type rules with disclaimers for external emails and two for communication internally. There is no need to add disclaimer and all other rubbish to emails when we just send this between company users. Just *Regards and Name* is typically sufficient.

---

As mentioned above, this solution is good, but not perfect.

The downside is that signature is always pasted on the bottom of the email.

If you replay to your email, this will be still on the bottom of the email, and not on the bottom of your text that is added in response. This, what's on the bottom of your response, can be sorted directly in the desktop Outlook app. On the end, you will see, that is longe emails you will last page with just bits from signatures.

To help with that, you can always evaluate [Exclaimer](https://exclaimer.com) solution for Microsoft 365, which is not as expensive (starting from £0.70 per user, to £1.35 in Pro package) but can supercharge your signatures when there is a need for that.

## Blacklist (spam) and Whitelist for emails

Yes, from just heading, you have your answer. Your basic package will give you the ability to create Blacklist - Spam list and Whitelist as well, with the option to report Junk, Not-Junk and Phishing from your desktop or mobile app as well.

In [**Microsoft Defender portal**](https://security.microsoft.com), you will have pre-set policies in [Anti-spam policies](https://security.microsoft.com/antispam) where you can create your own or just turn on ones that are there available. I strongly recommend **Strict Present Security Policy**. Any messages marked by these policies you can trace in [Quarantine](https://security.microsoft.com/quarantine).

## Group emails

From [Exchange admin centre](https://admin.exchange.microsoft.com/#/groups) you can create distribution lists / group emails, where people will be sending their emails, which later will be forwarded to relevant people. 

## Shared Mailbox

From the [same place](https://admin.exchange.microsoft.com/#/mailboxes) you can create shared mailboxes that can be used by multiple users or even just for storing copy of sent messages. You cannot sent email as a shared-mailbox, as a shared mailbox doesn't have licence attached (to send email, you need to do this from your own account). You can store messages in this type of mailboxes without the need to waste money on licence.

The other good option to utilise free shared mailbox is when the user is leaving the company. You don't need to remove his mailbox to release mail licence. You just need to convert his mailbox into shared mailbox. This will preserve mails, then you can disconnect licence from user (user account can be later deleted) and attach licence for another person.

Shared mailboxes carry out the same name as the user email. You can change this from settings, and thanks to that, you can later created distribution list where emails sent to this address will be forwarded to someone else inside the organisation (or just add this email as an alias to one of the licensed user).

In case that person will come back to the company, you can easily convert shared mailbox into ordinary mailbox, attach it to the user and licence and user can start using it like before (still heaving access to old email).

## Contact management and Planning

As a part of Outlook, you are getting [Contact management](https://outlook.office.com/people/) and [Calendar](https://outlook.office.com/calendar/view/month). If you would like to plan something more, you got even Planner for your disposition.

## OneDrive and sync of Desktop, Documents and Pictures

Each licensed user is receiving, in a price of £3.80, personal storage in OneDrive. For this price, you are getting 1 TB of storage for each user! Together with Windows integration, you can specify synchronisation for your precious folders like Desktop, Documents and Pictures. In case that your computer will fail, on a new one you just need to login into your OneDrive account, and all these folders will be sync back. Magic!

It's like restoring a user profile that by default been stored from the company's on-premise windows server, but this time it will be restored from the cloud.

## SharePoint - Step above OneDrive

Apart from that each user is receiving its personal 1 TB OneDrive storage, you can create a Document Library using SharePoint, that is also included into your licence! For just £3.80 per month, you can create a shared document library, that later you can attach to each user OneDrive App (in Windows 10 or 11) and use this across your company as a Shared Drive. All files are sync across all computers, and you can even set access permission for each folder or file. Mobile OneDrive (iOS and Android) will also give you swift access to your personal OneDrive and SharePoint Document Library. You can even attach files from them in the mobile Outlook app.

Imagine, how its useful if you don't have access to your computer, and you know that the file you need is stored inside your folder in Document Library - the library, that you can have access easily on the go (same like Desktop, Documents or Photos on your personal OneDrive that you have access under your finger tip).

Document Library is an additional 1 TB (company wide) storage that each user will be getting on top of 1 TB OneDrive personal storage! Really nice for such a small price.

That's not all. As I mentioned in Entra ID (Azure AD), you can have users without licence, who will be using the above feature for free.

As users without license (unlicensed) are not receiving their own OneDrive storage, they can still have access to Document Library into the OneDrive app.

Your need to login into OneDrive in Windows 10 or 11, then head to SharePoint through browser, and in the Document Library section use the **Sync button** to attach the library to the desktop app. This will later appear inside File Explorer as an additional location for use.

![SharePoint Document Library Sync OneDrive](/images/2021/04/SharePoint_Document_Library_Sync_OneDrive-min.png)

Despite that unlicensed user don't have access to personal OneDrive features, he will have access to files (let's call it "shared drive") that can be collaborated between other users inside organisation.

{{% ads-in-article %}}

## You can still use desktop Office apps

**What mistakenly people assume**, also because Microsoft saying that you can "Access web versions of Office apps", **that you cannot use desktop apps** with a basic licence.

If you own your licence for any full Office package (like Office 2016 or 2019 - not 365 version), there is nothing against you to use these apps with your Microsoft 365 Business Basic. And that's including managing e-mails through Desktop app - Outlook together with free mobile Outlook on iOS or Android!

You can even have some collaboration features.

If you company spend some money on licences before moving into cloud, you don't need to waste them and use them with Business Basic!

## Microsoft Access database in Cloud (SharePoint)
Many organisations in the past create local databases to conduct various tasks. The problem with these databases is that, when is moved into the cloud, it's hard to work on them on more than 1 person at the time, as when each change is made by one user, this need to be synced to be seen by other user.

This is another function that is not widely advertised, but available in the basic package of Microsoft 365. You can move your outlook data (tables - back end) into cloud (SharePoint), leaving just a front-end file containing queries, forms, macros or reports locally.

When design of the database is done it is rarely that these elements, apart of data in tables, is changed. Because of that, when your databases (lets say - 500 MB in weight) is stripped from data, you are left with just a chunk of storage to exchange between users (like 2-5 MB in average!) in a form of file that need to be sync between them (for example through SharePoint Document Library).

All users can use, stored in cloud, front-end database, or even they can save it on their local computer, but still they will be working on live data (back end) stored in tables in cloud - SharePoint.

Even when somebody will change front-end and one person will be working on newer than the other, it still is possible to get some kind of working-all-together experience.

Personally, we are storing our Access databases in SharePoint synced via Document Library (SharePoint), which is then synced with all users desktops/laptop. Then everybody is working on data, that is served from cloud - SharePoint.

It's not easy to resign from Microsoft Access just like that. Despite that Access don't exist for MacOS users, re-designing them and moving into a different solution can be time-consuming and sometimes expensive. With integration with SharePoint for storing tables, this can be done swiftly.

Off-course, some changes need to be made, especially in forms, formulas and queries, to be able to use data in this kind of hybrid environment (especially when your initial database been designed in Office 2000 or older), but the time spend to do that is rewarded with flexibility without the need to re-write everything from scratch.

## Microsoft Forms

Have you ever used Google Forms to create interactive pools or questionnaires that you send (as a link) to your customers or suppliers? Microsoft in its basic package got you covered. With Microsoft Form, you can create this as well, which is later well integrated with your whole infrastructure. You (user who will be filling it) can even attach files in form, that will later be saved in SharePoint documents Library.

The forms can be accessed on various devices without the need of a licence or even logging into Microsoft's account (anonymously).

## Backups

Apart from mentioned above stuff, Microsoft gets you covered in backup as well. They offer backup of your files with options to restore them up to 30 days back. They even send you an email if you detect abnormal activity on your files. For example, if you deleted by accident a folder that contain like 100 files. They will ask you if that was intended and if you would like to restore it.

## All other apps

Apart from the mentioned above features, you are getting much more, and you can discover it [Office portal](https://www.office.com/apps).

[![Microsoft 365 Business Basic > All apps](/images/2021/04/Microsoft_365_Business_Basic_All_apps-min.png)](/images/2021/04/Microsoft_365_Business_Basic_All_apps-min.png)

From OneNote, Planner, Power Apps, Power Automate and Power BI, you are pleased with Teams (including desktop and mobile apps for free, even for users without licence!), Sway, Stream, To Do, Yammer and even Whiteboard.

Delve will give you an overview on most collaborated content, but what's more powerful is that you can integrate other services like GoodSync or rclone for creating backups of all your precious files.

> Personally, apart from Microsoft build-in backup feature, I am using rclone with prepared Raspberry Pi to carry our full off-site backup of OneDrive content for myself, along with the Company SharePoint Document Library that all users are working on. Additional independent backup, stored outside of the company's premises, is always good.
> What's better, this kind of integration, apart from hardware cost, not costing you anything extra! I will write about that in the near future, and will paste a link to this here when ready.

Admins who are missing some functionality of on-premises Windows Server, Microsoft prepares [Security](https://security.microsoft.com/) portal, where you will find your Quarantine messages, will be able to do some message trace activities along with other options in [Exchange admin centre](https://admin.exchange.microsoft.com/). Additionally, to that, you got for your disposition a [Compliance centre](https://compliance.microsoft.com/homepage).

Once again, not all options will be available in basic licence, but for small and medium organisations, what's offered in the basic package is more than enough.

## Final Word

Now look on the other bright side of migration to cloud. You don't need to spend money on electricity to maintain on-premise server, as well. You don't need to have a dedicated person to keep up-to-date of your server. The IT person may lose a job or part of responsibilities (sorry!), but this is how it's going to be. Microsoft will offer you support for free over phone, email and chat.

Is it worth it? Absolutely.

If you are aware of issues like hacking and phishing, you will be happy with the possibility to implement two-step authentication for your users for free. For that, you can use various methods, and Microsoft prepare something for you as well. They create Authenticator app available for mobile platforms that will allow you to create one-time pass codes required to login into the user account. Additionally, with New Microsoft Edge based on Chromium, profile synchronisation and recently added function of storying securely user password, you can have this aspect sorted out as well. No more storying passwords in Excel spreadsheets or in your file called password.txt on your desktop! **Yes, I know that some of you doing this like that - crazy!**

**BTW.** Microsoft did a good thing with his move into Chromium based Microsoft Edge browser, hence this app shall not be ignored and you all shall start using it. You don't need to use Google Chrome - the threat that Google seems to realising now. The change happens already, and Microsoft is seems to be winning - at least against users on Windows 10 or 11 system (Edge and Chrome is far from recommendation for use on MacOS, especially when working on battery!).

The above is only top of an iceberg. I can bet that you will find many other features that you would not expect in having for such a small price of a basic licence.

**When you will be going into Microsoft 365 Business Basic assume, that you need a licence only for users, who need to have their individual emails.** The rest you can achieve without extra spending! Just have a try. Start with Number of licences equal users with emails (mailboxes) plus one extra.

This one extra licence is to attach to a separate account, highly protected, set with all two-step authentications and strong passwords, that will be used as your master admin account. Then you shall be ready to go.

---

Microsoft used to be a company that creates expensive software, and due to that they earned a lot of money. Over the recent years, they gave something more (typically for free) to the society than it is actually worth.

Hope I help you made a right decision where to start with Microsoft 365 for business.

Regards.



---
## Cookie and Storage Policy
- **URL:** https://dariusz.wieckiewicz.org/en/cookies-policy/
- **Date:** 2021-04-17
- **Tags:** policy, terms

### Content

## What Are Cookies and Local Storage

To provide a professional and efficient experience, this site uses cookies and similar technologies, specifically **Local Storage**. Cookies are tiny files downloaded to your device, while Local Storage allows us to store data within your browser to remember your preferences.

This page describes what information they gather, how we use it, and how we respect your choice to opt-out of non-essential tracking.

## Managing Your Preferences

We utilize a consent banner to give you control over your data.

* **Accept All:** You agree to our use of local storage for analytics, site preferences, and advertising. This helps us understand how visitors use the site and allows us to serve relevant content.
* **Reject All:** We will only use "strictly necessary" storage to keep the site functional. No persistent tracking identifiers will be stored, and analytics will run in a restricted, anonymous mode. Advertising may still be shown but will not be personalized based on your past browsing data.

## How We Use These Technologies

### Strictly Necessary Storage
We use storage to keep the site functioning correctly. This includes:
* **User Preferences:** To remember if you have accepted or rejected our privacy notice.
* **Security:** To prevent fraud and ensure the integrity of our contact forms.

### Performance and Analytics
We use **Minimal Google Analytics 4** to understand site traffic. This implementation is designed to be privacy-respecting:
* It utilizes **Google Consent Mode v2**, meaning no data is stored or used for advertising purposes unless you explicitly grant permission.
* If you **Reject** tracking, analytics data is sent in a cookieless, anonymous format that does not identify you across sessions.
* If you **Accept** tracking, we use local storage to measure things like how long you spend on the site and which pages are most helpful.

### Advertising
This site serves advertisements to remain free for our readers. Our advertising partners may use cookies and similar technologies to collect information about your visits to this and other websites in order to provide relevant advertisements about goods and services of interest to you. 
* If you **Reject** advertising cookies, you will still see ads, but they will be non-personalized (contextual).
* If you **Accept**, these partners may use identifiers to improve ad targeting and measure performance.

## Third Party Services

In some cases, we use plugins to enhance functionality:
* **Social Media:** Buttons for LinkedIn or Facebook may set their own cookies if you interact with them while logged into those platforms. These are managed by the respective social media providers.

## Disabling via Browser

You can prevent the setting of cookies by adjusting your browser settings (see your browser "Help" menu). Note that disabling all cookies via your browser may "break" certain features of this and other websites. We recommend using our on-site banner to manage your privacy settings specifically for this website.

---

Cookie: Fot. Flickr, lic. CC by Michael Verhoef


---
## About Me
- **URL:** https://dariusz.wieckiewicz.org/en/about/
- **Date:** 2021-04-17


### Content

<!--more-->

<img alt="Dariusz Więckiewicz" src="https://avatars.githubusercontent.com/u/271114" width="260" height="260" class="avatar">

{{< tldr >}}
Professionally Quality Manager in [the construction company](https://www.andrewsfasteners.uk), Master of Science in Engineering (MSc Eng). Privately father of two, husband, karate-ka 🥋 (ダリユシュ) at [AKASHI](https://www.akashishotokan.co.uk) (3rd dan), self-taught web developer, IT support person and blogger. British and Polish national living in Leeds, West Yorkshire, United Kingdom. Read more on [LinkedIn](https://www.linkedin.com/in/wieckiewicz/).
{{< /tldr >}}

## Private life

I am a Polish-born, naturalised British citizen living in the UK.

Father of two, a daughter [Anna](https://anna.wieckiewicz.org) and son Edmund (gifted with his [special abilities](https://en.wikipedia.org/wiki/Autism)).

When not working or spending time with my family, I am training Shotokan Karate at [Akashi Shotokan Karate Association](https://www.akashishotokan.co.uk) (in short, Akashi or ASKA) and currently at my 3rd dan grade.

In some extra time, I am helping people with their IT struggles and building websites. I become an enthusiast of SSG (Static Site Generators) like [Hugo](https://gohugo.io) and have full control of your own content using [markdown](https://commonmark.org/help/) files. 

## Blog

My native language is Polish, this is why my [main website](/) (without /en) is written in Polish, however, I decided to create a section of my website that will carry text written [in English](/en/).

As you will notice, I am writing in a specific way. I am not biased and before I recommend something to someone I need to try it first and agree with it. 

Everything is changing so am I. I may recommend something today and in a couple of years change it. This is how life works. Sticking with one solution, without trying something new is not the way how we evolve.

## IT Support

Despite not having[^1] formally recognised IT knowledge, plenty of people including my employer can say a lot about my skills in that matter. I helped many over two decades and I am constantly developing myself to be on top of the current technology.

[^1]: ECDL [European Computer Driving Licence] Core Certificate

I know, that officially recognised skills are in value, so I:
- Hold ECDL (European Computer Driving Licence) Core Certificate (08/2010) that covers
  - Concepts of Information Technology (IT)
  - Using the Computer and Managing Files
  - Word Processing
  - Spreadsheets
  - Databases
  - Presentation
  - Information and Communication

I am good with Windows, macOS and Linux. From my various posts, you may see how I utilised the linux environment on various devices including routers or Raspberry Pi. Depending on what I need to do, there is always a way of doing it. You just need to like "tinkering", like I am, and you can achieve marvellous things.

Have you got a problem with computers, hardware or software? I am a person who can share a lot of knowledge in that matter and can support you in person or remotely.

As I am coming from Polish background where money was (still are) not as easy to earn, I like to utilise free services as much as possible and for as long as possible. This aspect includes hardware. If something (laptop for example) is a couple of years old, with a little upgrade, can still serve following years, why not try?

Feel free to [contact me](/en/contact/) to discuss what I can do for you.

Be aware that I am a very busy person. My family need to come first, and then karate. After all of that (and work commitments) I can find some time for you, so be patient.

## Web Development

I am a self-taught web developer. Started my experience in the late 1990s when I go through creating websites using as simple tools as notepad. I used Microsoft FrontPage as well, which was a big mistake. After coming back to basics I go through CMS like WordPress and work in it on various projects since 2006. In 2021 I migrated all remaining WordPress sites to Hugo banishing them from my portfolio altogether (no regrets!).

My current (active) portfolio includes:
- My blog in English [dariusz.wieckiewicz.org/en/](/en/) and in Polish – [dariusz.wieckiewicz.org](/)
- My daughter's website – [anna.wieckiewicz.org](https://anna.wieckiewicz.org)
- My employer website – [www.andrewsfasteners.uk](https://www.andrewsfasteners.uk) – commercial
- A good friend of mine offering commercial balloon flights – [www.paraplan.com.pl](https://www.paraplan.com.pl) – commercial
- [www.turboklinika.com.pl](https://www.turboklinika.com.pl) – commercial
- [www.aqua-tech.net.pl](https://www.aqua-tech.net.pl) – commercial
- [yummyrecipes.uk](https://yummyrecipes.uk) - personal

Despite not having formally recognised Web Development knowledge, apart from the websites that I built, I am still expanding my skills in various ways.

I am currently working on some Coursers and Certifications, as I know, that there are still people who value them and it gives them greater confidence before they put their faith into someone's hand.

My skills cover HTML, CSS, Basics of JavaScript (I can build JavaScript calculators with HTML forms like I did for example [here](https://www.andrewsfasteners.uk/quality/technical-support/bolt-length-hr-calculator/) or use and modify scripts that are already in place). Can work with PHP and SQL and implement all of this together can create something very useful.

> For example:
>
> Together with my IT skills I managed to build for my employer a set of Digital Boards that take information from the PostgreSQL database, work it through formulas and using web development skills display it in a friendly format for use by our warehouse and sales staff. This all is working live in cooperation with the company internal system for managing stock and sales activities.

I may not know how to do something now, but that doesn't mean that I will not want to learn how to get this done.

Always looking forward to developing something new and making further use of my web development skills. Constantly working on improvement, of mine and others' websites by implementing the latest solutions to them.

Are you looking for web development? [Contact me](/en/contact/) and we can discuss what I can do for you.

## Disclaimer

### Professionally

At least once a week I receive an email from LinkedIn (or other social media), that somebody is asking to add me to their contacts, friend list or network.

I am open to cooperation in IT and Web Development. If you got a problem with your computer, software, hardware, I may offer you a helping hand, however, the answer for the above paragraph is **no**, and here is why.

If I don’t know you, I haven’t exchanged even a word with you, please don’t send me an invite to connect. Let’s contact in other ways first and see how it's going.

Most of the requests I got are from fasteners manufacturers and salespeople. To this group now I can add various advertising companies and recruitments firms who want to offer services for my employer and its nothing to do with me.

Because I am QM in the fasteners industry that doesn’t mean that I want to connect with everybody in the industry. There are other people in the company who are involved in various aspects of the business.

**If you reading this page, don't try to contact me to sell services to my employer**.

### In relation to my blog

If you decided to criticise me, my writing, myself, **don't bother**, unless your criticism is constructive and topic-based. I am open to discussion and even cooperation. Use the comments form located under each post if you want to add your bits to it.

---
Do you read in Polish? Head into my polish section of [About Me](/o/).


---
## Optimising the Internet connection on a router with OpenWrt
- **URL:** https://dariusz.wieckiewicz.org/en/optimising-internet-connection-router-openwrt/
- **Date:** 2021-04-06
- **Tags:** bufferbloat, lag, sqm, sqmqos, smartqueuemanagement, OpenWrt

### Content

Recently while playing Call of Duty Mobile, I would occasionally experience a sudden slowdown in the form of increased ping, which would make the game temporarily unplayable.

<!--more-->

In my home I have a few devices connected to the network. Thanks to streaming services, our household easily downloads over 1TB (1000GB) of data per month with about 50GB of data sent. With a 100/10Mbps connection, that's a lot.

A sudden jump in Internet traffic has a negative impact on people playing online in the form of so-called lag.

This sudden jump, slowdown, extended response time (ping) is related to the so-called **Bufferbloat** - lag between packets.

While it is difficult to deal with this with a normal router (Linksys WRT32X with the factory software uses the so-called Killer Prioritization Engine to optimize, among others, Bufferbloat), with OpenWrt there is no major problem with this, because we can add this type of functionality.

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

To do this, you need to install the SQM (Smart Queue Management) package:

```bash
apk update
apk add luci-app-sqm
```

or from LuCI (**System > Software**).

Setup is incredibly simple.

We go to **Network > SQM QoS**.

[![OpenWrt — Network > SQM QoS](OpenWrt_Network_SQM_QoS.png)](OpenWrt_Network_SQM_QoS.png)

In the **Basic Settings** tab, check **Enable this SQM instance** and select our interface to which our Internet connection is connected.

Next, you need to set the speed of your Internet connection.

It is recommended to set the speed to 95% of the full connection speed, although, as part of the test, you can decide for yourself which setting is best. Since each connection has a certain amount of overhead, we are usually able to achieve more than officially stated.

> My Virgin Media router with the assigned configuration allows you to receive up to 117 Mbps (117000047 bps) for downloads and 10.50 Mbps (10500047 bps) for uploads.

At the beginning I set **100000 kbit/s download** (equivalent to 100 Mbps) and **10000 kbit/s upload** (equivalent to 10 Mbps), then increased the download to 110000 kbit/s (equivalent to 110Mbps).

> In order not to clutter our router's log with unnecessary entries, I changed **Verbosity** to only reporting errors (**error**).

[![OpenWrt — SQM QoS — Basic Settings](OpenWrt_SQM_QoS_Basic_Settings.png)](OpenWrt_SQM_QoS_Basic_Settings.png)

In the Queue Discipline tab, I changed the default **fq_codel** to **cake** and selected the **piece_of_cake.qos** script.

[![OpenWrt — SQM QoS — Queue Discipline](OpenWrt_SQM_QoS_Queue_Discipline.png)](OpenWrt_SQM_QoS_Queue_Discipline.png)

In the **Link Layer Adoption** tab I selected **Ethernet** and **Per Packet overhead (byte): 44**.

> Depending on your connection type, **Per Packet overhead** may be worth experimenting with (22, 26, 34), although **44** is the optimal setting.

[![OpenWrt — SQM QoS — Link Layer Adaptation](OpenWrt_SQM_QoS_Link_Layer_Adaptation.png)](OpenWrt_SQM_QoS_Link_Layer_Adaptation.png)

And that's it.

Then **Save & Apply** and you're all set.

{{% ads-in-article %}}

---

If you have noticed, in the **Basic Settings** tab there is a green **Add** button, which allows you to add additional configuration in case we have [additional internet connection on our router](/en/adding-second-internet-connection-router-openwrt/).

---

Here's how using [DSL Reports - Speed ​​Test](http://www.dslreports.com/speedtest) my internet connection gained some stability.

[Before (without SQL QoS)](http://www.dslreports.com/speedtest/67941789):

![Bufferbloat pre SQM QoS](Bufferbloat_pre_SQM_QoS.png)

[After (SQL QoS, Cake, piece_of_cake, LLA 44)](http://www.dslreports.com/speedtest/67941836):

![Bufferbloat post SQM QoS](Bufferbloat_post_SQM_QoS.png)

Can you see the difference? 😎

Best regards.


---
## A day from a life as a Quality Manager
- **URL:** https://dariusz.wieckiewicz.org/en/a-day-from-a-life-as-a-quality-manager/
- **Date:** 2021-04-05
- **Tags:** quality manager, brainstorm

### Content

Recently I found myself in an interesting situation at work. 

I have been sitting comfortably on my office chair, slightly distanced from my desk, empty-looking on the computer screen that doesn't display anything apart of my desktop with icons.

A bright observer from the "outside" can say that I am not doing anything, wasting time or even pretending I'm working. In reality, I got a brainstorm and debate with myself on how to do this and that.

This is how sometimes a job of Quality Manager looks like. 

<!--more-->

Some people will argue, that QM is not doing anything but earning more than them.

The others will say that if QM can do things quickly, so why not pass him other jobs? He doesn't have enough to do, or he got too much free time let's fill this for him.

When you are at that stage, then you learned for years to do a thing in an hour rather than eight, you know, to don't bother with what others saying and keep doing your job. 

> Recently I read a quote, "Because I can do a thing in one hour, that will take couple hours by another person, that doesn't mean that I shall be paid for one hour. I learned years to be able to do this thing in an hour and these years deserve appropriate pay".

If they complain? Well, I will be happy to take a part in a discussion, or even go with them through my day and see if they will be able to keep the pace.

Been in a job for some time, you are thinking about what you already know and plan/making ideas for the future.

An auditor of Quality Management System will say, that when you are sitting on your chair and having an imaginary meeting with yourself (those others will not appreciate), these are the moments of building "Opportunities for Improvement".

If you respect what you are doing at work, and always giving a heart, you know when you can let yourself work at 75% speed and when needed to jump into 125% of your capability.

By the way. The 75% is still way above 100% of the ordinary person who thinks, that he could jump into your shoes and do almost "nothing" every day.

{{% ads-in-article %}}


---
## Updating Software in macOS
- **URL:** https://dariusz.wieckiewicz.org/en/updating-software-in-macos/
- **Date:** 2021-01-02
- **Tags:** macOS, App Store, Updates, MacUpdater

### Content

Unlike iOS devices where we install (and update) all applications from the **App Store**, when it comes to macOS, the situation is a bit more complicated.

<!--more-->

Although the App Store for macOS also exists, a large number of software developers still release their programs bypassing it.

The App Store imposes certain requirements (quality and privacy), but also restrictions. Not to mention costs, the restrictions in the App Store mean that some applications that introduce modifications to the system desired by users are not welcomed by Apple.

Additionally, the entire verification process, even with a simple update, makes it unfavorable for developers. Therefore, a large number of them, bypassing the App Store, have introduced the option of checking for available updates in their software.

Thanks to this, they can offer the update to the end user much faster.

However, not all programs have this convenience, and even if they do, some do not notify us that an update is available. On the one hand, if everything works, why would you update (as many people in the IT industry say), on the other hand, I personally believe that it is always worth using the latest version of available software.

If something stops working or is in conflict with other parts of the system, it is not so obvious that a given program (not updated) may be the cause of all the confusion.

So how do you update software in macOS?

First - App Store.\
Second - built-in update system (if it exists)\
Third - downloading the latest version from the software creator's website.

Quite a lot of steps, isn't it? What if all this could be simplified a bit and saved a little time? Well, here comes a certain application to help us.

## MacUpdater

MacUpdater is an application that scans our software on our computer and compares it with the latest version available in the software database. When an update is available, it gives us the option of a simple update with the use of one button (almost).

[![MacUpdater 2 - Application window](macupdater_okno_aplikacji.png)](macupdater_okno_aplikacji.png)

I have been using this program for quite a long time and, although it is paid (**read more!**), in its version **without having to pay** it offered what was sufficient for me.

Thanks to it I found out which applications on my computer were outdated and even about which ones had been discontinued by their author (Discontinued).

[![MacUpdater 2 - Discontinued App](macupdater_discontinued_app.png)](macupdater_discontinued_app.png)

In the free version of the program we have the ability to make 10 updates using the simple method of clicking the **Update App** button.

[![MacUpdater 2 - Open App Homepage](macupdater_open_app_homepage.png)](macupdater_open_app_homepage.png)

For years I didn't even use these 10 free updates, because mainly when a program appeared on the list as outdated, from the menu I selected the option to go to the software developer's website (**Open App Homepage**) from where I downloaded the latest installation file. Then I scanned the given application in the program again (**Re-scan this App**) to check if it had been properly updated and disappeared from the list of outdated software.

Since December 2020, the latest version of the program (**MacUpdater 2.0**) has been actively developed. During this period, it was not possible to purchase a license for the previous version (1.5.9), and version 2.0 (or more precisely 1.9.9) could be used for free (without any limits) in the form of a public Beta version.

As I have never used my 10 free updates, this time (since everything in the Beta version is free) I decided to see how this application will help me save some time that I waste on manual downloads and updates.

Let's not kid ourselves, updating software in macOS is not painful. It's not Windows. In most cases, we download a **.dmg** file from the software developer's website, run it, and drag our program to our Applications folder, and that's it!

![MacUpdater 2 - Drag to Applications folder](macupdater2_przeciagnij_do_folderu_aplikacje.png)

> Due to the way apps are distributed and "installed" in macOS, just as they are easy to throw into our Applications folder, they can be easily removed from the system along with all of its remnants using [AppCleaner](/en/appcleaner-add-remove-apps-macos/).

Programs like TeamViewer (which require some interference in the system) have a slightly more advanced installer (usually applications of this type are distributed using **.pkg** files). In the case of updating from MacUpdater, we will also have to go through these steps (we are informed about this accordingly).

> In case of removing applications installed using **.pkg** files, we can use a tool from the same author as MacUpdater, namely [UninstallPKG](https://www.corecode.io/uninstallpkg/), unless the creator of the original software has prepared an uninstallation package for us.

On January 1, 2021, the author, as promised, released the final version of MacUpdater 2.0.

While the previous version cost $9.99, this time unfortunately we have to count on an increase to $14.99 for a regular user (Standard License). Additionally, the author introduced a division of additional Pro and Business licenses ([compare what individual licenses offer](https://corecode.io/macupdater/comparison.html)).

[![MacUpdater 2 - License Comparison](macupdater2_comparsion.png)](macupdater2_comparsion.png)

For a regular user, the Standard license is more than enough.

This time, the author also emphasized the possibility of using the application **without having to buy a license**.

![MacUpdater 2 - Editions](macupdater2_editions.png)

**Free Edition** only offers scanning of the application for updates. Of course, in the trial version we still have 10 free updates available, after which we must purchase a license or stay with the free version.

If we decide to purchase a license, in some cases we can expect a discount.

As [described](https://www.corecode.io/macupdater/faq.html#DISCOUNT) by the author of the program himself, some people can expect discounts on the purchase of a license:
- students receive a 40% discount, and
- people living outside the list of the 40 richest countries in the world can also expect a 40% discount.

To do this, contact the author using the email address provided (in the link above) to receive a discount code.

> Depending on the list we choose, Poland is in 47th, 54th or even 56th place, so a discount is guaranteed.

{{% ads-in-article %}}

There is also a 60% discount, which is not fully explained, but I assume it is about buying more licenses, although I would personally prefer a discount for buying more than one program ([UninstallPKG](https://www.corecode.io/uninstallpkg/index.html)).

The program can be [downloaded for free](https://www.corecode.io/macupdater/index.html#download) from the manufacturer's official website.

When you first start the application, you will be greeted with a screen that allows you to configure the basic way the application works and will guide you through a short tutorial presenting the application and its options.

![MacUpdater 2 - Welcome screen](macupdater2_welcome_screen.png)

Personally, on the screen for selecting the preferred work mode, I selected the alternative mode (**Alternative**), because I do not need the application to start automatically and check for updates on an ongoing basis, but only when I decide to do so.

[![MacUpdater 2 - preferred mode](macupdater2_preferred_mode.png)](macupdater2_preferred_mode.png)

---

Before I started using MacUpdater in its entirety, I used to use [MacUpdate Desktop](https://www.macupdate.com/desktop/) which costs $20. However, considering that the latest version 6.4.1 was released on December 19, 2018, well before the changes introduced in macOS Big Sur, I would even be tempted to pay for MacUpdater 2.0.

The reason I abandoned MacUpdate Desktop in favor of MacUpdater was their database of applications. I was often able to find an update faster than their program informed me. That's why MacUpdater 2 is a better option. It's no wonder that the price had to go up, since you have to keep the information up to date.

I'll leave the choice to you.

The application is really recommendable.


---
## Adding a USB printer to a router with OpenWrt
- **URL:** https://dariusz.wieckiewicz.org/en/adding-usb-printer-router-openwrt/
- **Date:** 2020-11-21
- **Tags:** print server, OpenWrt, AirPrint, p910nd, avahi, HP JetDirect

### Content

Recently I decided to add a USB connected printer to my OpenWrt router.

While I normally use a wireless solution with built-in AirPrint (so I can print directly from my iPhone/iPad), sharing a USB printer on a network involves purchasing a print server.

Unfortunately, currently available print servers lack support for, for example, AirPrint, i.e. the ability to print wirelessly from Apple devices such as iPhone or iPad.

If I find one that has AirPrint, it is either very expensive or the manufacturer has discontinued its further development, which is a pity.

So I decided to use my OpenWrt router. Since it has two USB ports, one of which, USB 2.0, which I happen to have free, is perfect for connecting a printer.

In fact, I cared most about AirPrint, and you can read about what came out of it below.

<!--more-->

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

## Introductory Word

> First, the hardware I'll be using in the example below:
> * Router: _Linksys WRT3200ACM with OpenWrt software_
> * Printer: _Samsung CLP-325 on USB_

My main goal will be to share a printer on the network, with the ability to print from a macOS computer. I will also include printing from a Windows computer.

In a typical solution (Raspbian + Raspberry Pi + USB printer) I would use the CUPS package and that's it. Unfortunately, in the current version of OpenWrt software, the CUPS package is not available due to router limitations (memory and computing power). CUPS itself has high requirements in this regard, so official sources recommend a different approach.

> Of course, if you want, you can compile your own CUPS package from source. It can be done and will even work. However, the problem will arise when you want to update the software on your router. Although according to [my description](/en/firmware-update-openwrt/) you will be able to restore the settings and installed packages easily, in the case of CUPS, you will have to recompile it, and believe me, it is not a quick solution.

## Print Server - installation

The **p910nd** print server is available as a ready-made package for installation from a browser (System > Software) or terminal:

```bash
apk update
apk add p910nd
```

Additionally, it is worth installing an application that adds the ability to manage the server from our LuCI administration panel.

```bash
apk add luci-app-p910nd
```

The last package we need is USB printer support.

```bash
apk add kmod-usb-printer
```

## Finding a printer

Before we start configuring our print server, we need to check if our printer is detected by the system.

After connecting the USB cable (with the printer turned on) and executing the `dmsg` command in the terminal, we should see something like this:

```
usb 1-1: new high-speed USB device number 4 using orion-ehci
usblp 1-1:1.0: usblp0: USB Bidirectional printer dev 4 if 0 alt 0 proto 2 vid 0x04E8 pid 0x329F
```

And using the `lsusb` command we check if our device is recognized correctly. In the case of my printer I got:

```
Bus 001 Device 004: ID 04e8:329f Samsung Electronics Co., Ltd CLP-325 Color Laser Printer
```

So everything is on the right track.

We check if the printer is recognized correctly:

```bash
ls /dev/usb/lp*
```

After that we can move on.

## Print Server - configuration

From the browser go to **Services** > **p910nd - Print server**.

[![OpenWrt - Services - p910nd](001_OpenWrt-Services-p910nd.png)](001_OpenWrt-Services-p910nd.png)

Setup is actually very simple.

[![OpenWrt - p910nd Print Server](002_OpenWrt-p910nd-print-server.png)](002_OpenWrt-p910nd-print-server.png)

First, we select the **enabled** option to turn on our server.

In the next step we need to specify our device (**Device**). By default _/dev/usb/lp0_. If we only have one printer, then we don't really need to change anything here.

In the **Interface** option we select **LAN**, which means our print server will listen for print requests from the local network.

Then **Port** which is set to _9100_ by default.

We leave the **‌Bidirectional mode** checkbox unchanged (in the case of some inkjet printers we will have to disable this option).

Then click **Save & Apply**.

**IMPORTANT**
After all this fun, it is worth restarting our router or restarting the **p910nd** server from the terminal to avoid problems.

```bash
/etc/init.d/p910nd restart
```

Personally, I didn't do it on my first attempt and I was wondering why it wasn't working 😂.

## Installing the printer on a macOS computer

> In the example below I used macOS Big Sur 11.0.1 (but it also works in macOS Sonoma)

We go to system settings (**Settings**) and the Printers and Scanners section (**Printers & Scanners**).

[![macOS Big Sur - System Preferences - Printers & Scanners](003_macOS_Big_Sur-System_preferences-Printers_and_Scanners.png)](003_macOS_Big_Sur-System_preferences-Printers_and_Scanners.png)

Using the + (plus) button we add our printer.

[![macOS Big Sur - Printers & Scanners](004_macOS_Big_Sur-Printers_and_Scanners.png)](004_macOS_Big_Sur-Printers_and_Scanners.png)

In the **Add Printer** window, select the middle icon and enter the IP address of our router in the address field.

[![macOS Big Sur - Add Printer](005_macOS_Big_Sur-Add_printer.png)](005_macOS_Big_Sur-Add_printer.png)

In the **Protocol** field, select **HP JetDirect - Socket**.

Then we go to the **Use** field, where we need to select what method our computer used to process printed documents.

We choose **Select software...** and from the list we choose our printer. If we previously connected the printer to our computer with a USB cable and were able to print to it, it is very likely that the software will be available.

Of course, in the **Name** field, which I skipped, we enter the name of our printer that we want to see in the system.

Then press the **Add** button and try to print something.

> When adding a printer, we may get a message that the system is unable to verify the printer on our network. We don't need to worry about that too much, so we click the **Continue** button.

{{% ads-in-article %}}

## Installing a printer on a Windows computer

> In the example below I used Windows 10 (20H2) but it also works in Windows 11.

To install the printer in Windows, from the **Start menu** go to **Settings** and then to the **Devices** section.

[![Windows 10 - Settings - Devices](006_Windows10_Ustawienia-Urzadzenia.png)](006_Windows10_Ustawienia-Urzadzenia.png)

On the left side of the window, select **Printers and scanners** and then click the **Add printer or scanner** button.

[![Windows 10 - Printers and Scanners](007_Windows10_Drukarki_i_Skanery.png)](007_Windows10_Drukarki_i_Skanery.png)

Of course, at this stage our printer will not be found automatically, so we need to click on the option **The printer that I am looking for is not listed**.

[![Windows 10 - The printer I'm looking for isn't listed](008_Windows10_Drukarki_ktorej_szukam_nie_ma_na_liscie.png)](008_Windows10_Drukarki_ktorej_szukam_nie_ma_na_liscie.png)

In the next window, select **Add a printer using a TCP/IP address or hostname** and click **Next**.

[![Windows 10 - Adding a Printer](009_Windows10_Dodawanie_drukarki.png)](009_Windows10_Dodawanie_drukarki.png)

In the address field we enter the IP of our router.

We uncheck the **Check printer and automatically select drivers to use** box, because our router does not inform what printer is currently connected. We select the **Next** button.

[![Windows 10 - Add a Printer - Enter Hostname or IP Address](010_Windows10_Dodawanie_drukarki-Wpisz_nazwe_hosta_lub_adres_IP.png)](010_Windows10_Dodawanie_drukarki-Wpisz_nazwe_hosta_lub_adres_IP.png)

After a while, the system will start detecting the TCP/IP port.

[![Windows 10 - TCP/IP Port Detection](011_Windows10_wykrywanie_porty_tcp_ip.png)](011_Windows10_wykrywanie_porty_tcp_ip.png)

Once this is completed, on the next step we leave the default settings selected (Generic Network Card) and click **Next**.

[![Windows 10 - Additional port information required](012_Windows10_Wymagane_dodatkowe_informacje_na_temat_portu.png)](012_Windows10_Wymagane_dodatkowe_informacje_na_temat_portu.png)

Now we need to select the drivers for our device.

Similar to the previous step, if we previously connected our printer via USB cable to the computer and were able to print without any problems, everything should be in the system.

After selecting what we are looking for, click **Next**.

In the next step we can specify the name of our printer or leave the default selected by the system. Click **Next**.

[![Windows 10 - Enter printer name](013_Windows10_Wpisz_nazwe_drukarki.png)](013_Windows10_Wpisz_nazwe_drukarki.png)

When asked if we want to share the printer on the network, we select **Do not share this printer** as it is already on the network.

[![Windows 10 - Printer Sharing](014_Windows10_Udostepnienie_drukarki.png)](014_Windows10_Udostepnienie_drukarki.png)

In the last step, we will have the option to print a test page. If we did everything correctly, the printer should start printing.

[![Windows 10 - Printer successfully added](015_Windows10_pomyslnie_dodano_drukarke.png)](015_Windows10_pomyslnie_dodano_drukarke.png)

## But what about AirPrint?

And while I didn't want to go the route of CUPS, which would have added AirPrint in an easy way, I had to think about what to do next.

Reading deeper, I found out a bit that AirPrint uses the IPP protocol. The **p910nd** server works on the AppSocket principle with support for the LPD/LPR protocol.

Additionally, AirPrint requires mDNS support (Bonjour/Avahi) for the printer to be discovered by Apple devices.

The **avahi** package is available from the packages level in OpenWrt.

But first things first.

First, I made sure that the printer was detected automatically on the network.

## Automatic printer discovery on the network

For this purpose we use entries in the **avahi** service.

If we do not have **avahi** in our system, we will install it as follows:

```bash
apk update
apk add avahi-nodbus-daemon
```

According to [original entry](https://oldwiki.archive.openwrt.org/doc/howto/p910nd.server) we create a new file from the terminal `nano /etc/avahi/services/printer.service` and paste the following content.

```xml
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">

<service-group>
  <name replace-wildcards="yes">Samsung CLP-325 on %h</name>
  <service>
    <type>_pdl-datastream._tcp</type>
    <port>9100</port>
    <txt-record>qtotal=1</txt-record>
    <txt-record>note=room 2</txt-record>
    <txt-record>ty=Samsung CLP-325</txt-record>
    <txt-record>product=(Samsung CLP-320 series)</txt-record>
    <txt-record>usb_MFG=Samsung</txt-record>
    <txt-record>usb_MDL=CLP-320 series</txt-record>
    <txt-record>Color=F</txt-record>
    <txt-record>Duplex=F</txt-record>
    <txt-record>Bind=F</txt-record>
    <txt-record>Collate=F</txt-record>
    <txt-record>Sort=F</txt-record>
    <txt-record>Staple=F</txt-record>
    <txt-record>Punch=F</txt-record>
    <txt-record>PaperMax=legal-A4</txt-record>
  </service>
</service-group>
```

Of course, we adapt the printer name to our needs.

We restart the service:

```bash
/etc/init.d/avahi-daemon restart
```

In the case of macOS, the value in the `product=` section is responsible for the name of the driver in the system, so that our printer will not only be detected automatically, but the system will also select the correct drivers.

[![macOS Big Sur - Add printer - Bonjour](016_macOS_Big_Sur_Add_printer_Bonjour.png)](016_macOS_Big_Sur_Add_printer_Bonjour.png)

**However, as you will notice, the printer is detected correctly in macOS but not in Windows 10**.

[![Windows 10 - Search for printer](017_Windows10_wyszukanie_drukarki.png)](017_Windows10_wyszukanie_drukarki.png)

This is the nature of **avahi** and the lack of support from Windows 10.

In the case of Windows 10, we have to add the printer in a more manual way, as described above.

## Printing from a phone (including iPhone)

Unfortunately, when using **p910nd** as a print server, there is no way to add AirPrint support.

I slowly started to get used to it (looking for another solution), but I decided to experiment.

Well, since my printer works on the network and is detected by macOS automatically, maybe there is hope.

HP (the current owner of Samsung's printer section), like other manufacturers, release their own software for mobile devices (whether with Android or iOS/iPadOS) that enables printing, even when there is no possibility of using the native option built into the system, i.e. AirPrint.

So I reached for the Mobile Print app ([Android](https://play.google.com/store/apps/details?id=com.sec.print.mobileprint), [iOS/iPadOS](https://apps.apple.com/app/hp-samsung-mobile-print/id1301469531)).

> Even though I'm not a fan of this type of solution, like most users, as evidenced by the very low ratings, I have nothing else left.

After starting the application, I clicked on the **Select Device** text to add a device and after a moment I saw that my device was detected correctly! What's more, after adding it to the program, it suddenly appeared as available with a green checkmark.

{{% gallery %}}
[![iOS - Mobile Print](018_iOS_Mobile_Print.png)](018_iOS_Mobile_Print.png)
[![iOS - Mobile Print - Select device](019_iOS_Mobile_Print-Select_device.png)](019_iOS_Mobile_Print-Select_device.png)

[![iOS - Mobile Print - Selected device](020_iOS_Mobile_Print-Selected_device.png)](020_iOS_Mobile_Print-Selected_device.png)

[![iOS - Mobile Print with printer](021_iOS_Mobile_Print_with_printer.png)](021_iOS_Mobile_Print_with_printer.png)
{{% /gallery %}}

I quickly printed one photo from my gallery. Something I didn't expect, the print appeared and it did as it should.

So it works!

Even though it was only a partial success (I still don't have convenient AirPrint), I can print.

## But what about AirPrint?

Unfortunately, using OpenWrt, at the current stage of development this is not possible. End of story.

> Of course there is hope thanks to the [OpenPrinting/ipp-usb](https://github.com/OpenPrinting/ipp-usb) project, but that may be in the future.

Using **p910nd** instead of CUPS has its advantages and disadvantages.

The advantage, as I mentioned earlier, is its low resource consumption, so you can install and use it without problems even on a low-performance router. The print server is fast, print preparation (spooling) is done on the client side and sent directly to the printer.

The disadvantage, however, is the lack of AirPrint support, which means that printing from phones such as iPhones can only be done thanks to an additional application, as I mentioned earlier.

## So what remains?

The goal of this post, i.e. **adding a USB printer to a router with OpenWrt**, enabling network printing, has been achieved.

For me, however, this is not enough, so I treat the above as an experiment and I will be tempted to use **Raspberry Pi** again.

This time, on [The Pi Hut](https://thepihut.com) I bought [Raspberry Pi Zero W](https://thepihut.com/products/raspberry-pi-zero-w), which cost only £9.30 (~46.60zł)! I also bought a [mini-HDMI cable](https://thepihut.com/products/official-raspberry-pi-mini-hdmi-cable) (because I didn't have one) - £2.40 (~12zł) and a [case](https://thepihut.com/products/premium-raspberry-pi-zero-case) for £3.00 (15zł). Using some unused phone charger (1.5A), I solved the charging problem. I also used a microSD card lying around in a drawer and a microUSB to full-size USB adapter. And so, using pure Raspbian and the installed CUPS package, I can easily get my own wireless and low-power print server... with AirPrint support.

Ah.. I could have done it right away, but I preferred to see if I could use what I already have. And maybe someone will find the above solution useful.

Regards.


---
## No more free storage on Google Photos
- **URL:** https://dariusz.wieckiewicz.org/en/no-more-free-storage-on-google-photos/
- **Date:** 2020-11-11
- **Tags:** Google Photos, Google

### Content

It happened! Google calculated that the business it got into with **Google Photos**, while it has irreversibly changed the way we store photos, is very expensive for itself.

Disk space (**storage**) and its maintenance cost a lot, and not a little. The energy necessary to ensure the continuity of its services plays an even greater role, especially in the era of caring for the climate.

Someone at Google did not consider the fact that people like what is free, especially when you can't see the difference. And we are talking about photos and videos stored by us on Google Photos in compressed form, but without losing visual quality, and at the same time without them taking up disk space available as part of the service.

And so after over 4 trillion (4,000,000,000,000) photos uploaded by users to Google Photos, and as large companies began to look at the money they were generating from their operations during the pandemic, it was time for Google to start thinking like a profit-oriented company.

On one hand, someone had a great plan, to offer something that would revolutionize the market. **On the other hand, someone had an even better plan!**

Did anyone know that after a few years (over 5) of using Google Photos, it would be increasingly difficult for anyone to move from it to another solution, if such a thing exists?

<!--more-->

## Co się zmieni?

[Google has announced](https://blog.google/products/photos/storage-changes/) that **High quality (free unlimited storage)** will no longer be **free** as of June 1, 2021.

Photos that previously did not count toward your Google Mail and Drive storage will suddenly start counting toward your storage.

While people who use Google Photos to store their photos in their original resolution will not see any change, everyone else will.

**Fortunately, not everything is so bad.**

Namely, photos and videos uploaded to Google Photos before June 1, 2021 will still be available and will not use up the space available in the service. However, all new photos and videos uploaded since June 1, 2021 will use up our available space.

Considering that the 15 GB of default space, divided between files on Google Drive, Gmail and now photos, is really nothing. We will quickly have to reach for our wallet.

While I personally pay £15.99 per year (89.99zł) for 100GB as part of the Google service (of which I have about 60% occupied), I bet that within the first few months of the changes coming into effect (and let's take into account that the changes are coming during the summer holidays!) I will be forced to switch to a 1TB package, which is around £7.99 per month!

People who use the basic 15GB package, depending on how active they are, will notice within the first month that they suddenly run out of space. **Well, unless they have a phone from Google.**

> Users of Google Pixel 1 to 5 (and newer) phones will still have the option of using unlimited storage space for photos stored in High Quality (compressed, but visually indistinguishable).

Google's entry is clear enough, but it leaves a lot of questions unanswered.

While Google is betting that 80% of users will be able to fit up to 3 years of photos within 15GB without having to buy a larger package, I personally sincerely doubt it.

I assume that in the Google Photos settings we will still have the option of choosing to store photos in original quality, as well as high, compressed. However, this will only slightly delay the inevitable, i.e. paying.

To understand what takes up space in the Google Photos service, the company refers to [a dedicated page](https://photos.google.com/storage).

## What's next?

As Google promises, in June 2021 it will release a special tool that will allow us to transparently manage copies of our photos. In particular, it will inform us about the photos that are taking up our space and are of poor quality, overexposed, underexposed, blurred - those that we would normally delete, but since everything has been free so far, we simply did not want to.

This method will allow us to regain some space, although, as I mentioned earlier, it will only slightly postpone the inevitable.

> If we are already interested in how much the "new" (old) service will cost us in the future, Google refers to their website [Google One](https://one.google.com/about).
> The Google One service allows, as part of a private Google account, to purchase one package and [share it within the Family Group](https://one.google.com/faq/plan-sharing). The situation is different for users who, like how, use a Google account within [Google Workspace](https://workspace.google.com).

If we decide to download photos, videos (and everything else) that we currently store in Google, we can do so using the dedicated [Google Takeout](https://takeout.google.com/settings/takeout) page.

> When I did my first Takeout about 2 years ago, my photos took up over 120GB!

This method allows us to save everything that we currently have stored in Google and transfer it somewhere else. Whether to an external hard drive (back to the past), or to transfer it to another service.

## Inne usługi?

You might ask yourself, is there a good alternative to Google Photos?

Well, yes and no.

Before we rush to move our precious memories from a safe place to one that could be the final nail in the coffin, think about it!

When searching Google for information about an alternative to Google Photos, we can find several companies, but no one guarantees that these companies won't close down overnight, cutting us off from our precious memories.

> While Google's move is not cool (but understandable), the company itself knows that this type of change is not something that can be replaced overnight, which is why they give us more than 6 months' notice.

The same goes for an external drive. While we can use it as a backup, we can't count on it being our only lifeline. If it's stolen or damaged, we lose everything. Even keeping it in a bank safe deposit box doesn’t guarantee anything.

So what? You ask.

Well, one of the players on the market, especially in the initial stage of abandoning Google Photos, will be Amazon with its **Amazon Photos** service ([Amazon Photos](https://www.amazon.com/Amazon-Photos)).

{{% ads-in-article %}}

### Amazon Photos

With Amazon Photos (part of the paid Prime), we get unlimited space for our photos (in original quality!), but our videos count towards the 5GB limit of the basic package, which won't be enough for long.

While this service is trustworthy (Amazon won't close or change the terms of service overnight), it's not without you. Sooner or later, we'll have to reach for our wallets here too.

## So what else?

The problem is that the number of important services is negligible and Google knows that well.

I think we'll have to wait and see what changes in the meantime.

Of course, there are services from other service providers where we can store our photos (while paying for disk space), but it will be really hard to replace something that has so far offered us so much for so little (for free).

### Dropbox?

Before Google Photos, I used Dropbox to store copies of my photos. Their service [also offers dedicated cloud storage options](https://www.dropbox.com/pl/features/cloud-storage/photos).

Prices start at £7.99 for 2TB, but you won't find any photo and video compression options like Google offers with Google Photos, so you'll quickly fill up your available space.

I'll be keeping a close eye on what happens over the next few months and I'll definitely write about something else that's worth considering and could be a good alternative.

We'll see if players like **Flickr** take advantage of the opportunity with their Flickr Pro package.

Certainly, Apple users will be more likely to stick with iCloud photos than experiment with Google Photos, especially since Apple has released its version of [Apple One](https://www.apple.com/pl/apple-one/).

Microsoft, as part of its [365 package](https://www.microsoft.com/microsoft-365) could also take some of Google's market share, as could [Adobe](https://www.adobe.com/uk/products/photoshop-lightroom/store-manage-photos.html) with its 1TB package and free Lightroom app for desktop and mobile devices (£9.98 per month).


---
## iPhone Upgrade Programme in 2020 - is it worth it?
- **URL:** https://dariusz.wieckiewicz.org/en/iphone-upgrade-programme-in-2020-is-it-worth-it/
- **Date:** 2020-10-26
- **Tags:** iPhone Upgrade Programme, iPhone, iPhone 12 Pro, iPhone 12 Pro Max, AppleCare

### Content

As a person who likes technical innovations, I like to play with the latest equipment. When it comes to Apple equipment, if changing the device to a newer one right after its release is not part of our work, a typical upgrade is usually expensive and not always profitable.

Having owned an iPhone 6 a few years ago, I was in no rush to upgrade until the iPhone X came out, which I had for two years. When the iPhone 11 Pro was released, I moved towards purchasing the iPhone XS (yes, one generation back). As the item (an exception to the rule) turned out to be inconsistent with the description, I had to return it, and in order not to be left without a phone, I decided to buy the iPhone 11 Pro 256GB.

As Apple offers 0% installments, the total amount was £49.99 per month with the first payment of £20 and the last payment of £29.23. It's not some kind of **deal**, but I don't overpay at all, as is the case with operators in the UK (especially for individual customers).

I have been looking at Apple's iPhone Upgrade Programme[^1] for a long time. For a fixed monthly fee, you get a new phone, which you can replace with a newer one after a year (without having to pay the remaining "installments"). Apple Care is included in the total, which additionally encourages you to think: is it worth it?

<!--more-->

---

This year, Apple presented the iPhone 12 series of phones. While I am not interested in a pure 12 or mini, I immediately saw the prices for 12 Pro and Pro Max.

Even though my 11 Pro works great and I don't think about changing it until the next iPhone in 2021, I decided to do a little reconnaissance, especially since iPhones have become a bit cheaper this year compared to 2019 prices.

---

iPhone 12 Pro (256GB - my recommended minimum and maximum at the same time) costs around £45.79 per month (£4.20 cheaper than 11 Pro last year).

For the price I pay for the 11 Pro (£49.99), I could brag about the 12 Pro Max (256GB) model for £49.95 (and here £0.05 cheaper).

> If we want AppleCare+ we will have to add £8.29 per month.

And here's a little catch. Well, the above prices are calculated for a period of 2 years (24 months). Comparing them directly with the iPhone Upgrade Programme, we can shake our heads.

![iPhone Upgrade Programme Comparison](iPhone-Upgrade-Programme-compare-min.png)

The price of the same iPhone 12 Pro is £61.45 and Pro Max is £66.45.

However, this program spreads the payment over 20 months, after which we can receive a new phone after 11 months of repayment.

| Phone | First installment | 20x | In total | 24m |
| :-: | :-: | :-: | :-: | :-: |
| 12 Pro 256GB | £69 | £61.45 | £1298.00 | (£54.08) |
| 12 Pro Max 256GB | £69 | £66.45 | £1398.00 | (£58.25) |

For comparison, when buying normally

| Phone | First installment | 23x | Last | In total |
| :-: | :-: | :-: | :-: | :-: |
| 12 Pro 256GB | £20 | £45.79 | £25.83 | £1099 |
| 12 Pro Max 256GB | £20 | £49.95 | £30.15 | £1199 |

**But without AppleCare+**

With AppleCare+ it is as follows:

| Phone | Cost | AppleCare+ | In total | 24m |
| :-: | :-: | :-: | :-: | :-: |
| 12 Pro 256GB | £1099 | £198.96 | £1297.96 | (£54.08) |
| 12 Pro Max 256GB | £1199 | £198.96 | £1397.96 | (£58.25) |

After rounding by 4p, do you see any difference here?

> Comparatively, after 12 months of using the iPhone 11 Pro 256GB, I can still sell it immediately for £526 on [musicMagpie](https://www.musicmagpie.co.uk/start-selling/) recovering at least 43% of the value.

In the iPhone Upgrade Programme we can get a new phone every year, and the price includes AppleCare+ and it looks like this:

| Phone | First installment | After 11x | 43% | Difference |
| :-: | :-: | :-: | :-: | :-: |
| 12 Pro 256GB | £69 | £675.95 | £472.57 | £203.38 |
| 12 Pro Max 256GB | £69 | £730.95 | £515.57 | £215.38 |

As we can see, after paying off 50% (*actually over 57%!*) of the phone's value, if we wanted to sell it to replace it with a new one, we would lose between £203.38 and £215.38.

However, when AppleCare+ is not necessary for us (personally, I have a phone insured under my home insurance, and I have used it only once in the last 7 years), the difference is slightly smaller.

{{% ads-in-article %}}

And so, when we buy the phone ourselves:

| Phone | Cost | After 12m | 43% | Difference |
| :-: | :-: | :-: | :-: | :-: |
| 12 Pro 256GB | £1099 | £549.50 | £472.57 | £76.93 |
| 12 Pro Max 256GB | £1199 | £599.50 | £515.57 | £83.93 |

Here, as we can see, after paying off 50% of the value of the phone, if we wanted to sell it and replace it with a new one, we would lose between £76.93 and £83.93.

The above assumption is valid when we sell our phone at a guaranteed price. By using other sales methods, we can break even or make minimal profit. Additionally, since this year's phones are "cheaper", we can profit from this.

> As an iPhone X user, looking at the iPhone Xs successor, I realized that by purchasing the X, I became a kind of guinea pig, because all the problems with the X were fixed in the Xs and 11 Pro. By choosing iPhone 12 Pro with an "old" 5G chip that eats up the battery 20% faster, won't we become another guinea pig until everything is fixed on the next model - whether it will be iPhone 12s or iPhone 13? We will see. Personally, after reading various opinions, I am led to believe that this will be the case. And so, if you have an iPhone 11 Pro, changing to 12 Pro may turn out to be a shot in the foot.

Apple advertises the iPhone 12 Pro with the slogan "It's a leap year". For me, it's more like "It's a skip year" (i.e., let's forget about this year's iPhones and see what 2021 will bring). Anyway, this year sucks enough.

Regards

[^1]: [iPhone Upgrade Programme](https://www.apple.com/uk/shop/iphone/iphone-upgrade-program)


---
## Upgrade Windows 10 Home to Pro
- **URL:** https://dariusz.wieckiewicz.org/en/upgrade-windows-10-home-to-pro/
- **Date:** 2020-08-15
- **Tags:** Windows, Windows 10 Home, Windows 10 Pro, Windows 10 Professional, Windows 10 Education, upgrade

### Content

Recently I had the opportunity to transfer data from one computer to another. Since the first one was already running Windows 10 in the latest version and everything worked perfectly (only the hardware was a bit lagging behind), I decided to clone the disk from the first one to the second one.

Using `dd` as a method (a little slow but effective) I ran the same system on the new hardware, with one difference. The target hardware was licensed with Windows 10 Pro compared to the old hardware with Windows 10 Home.

Therefore, I decided to do an upgrade.

<!--more-->

According to information on Microsoft forums, it would be enough to change the product key to a Pro key for the system to detect and upgrade itself.

In my case this did not work because the product key that was assigned to the hardware originally corresponded to the Windows 8 Professional version (originally read from BIOS using [RWEverything](http://rweverything.com) `ACPI button, MSDM tab`) .

The system, instead of changing and upgrading to Pro, accepted the new key and activated remaining in the Home version.

---

I decided to try a different approach, namely using the Microsoft Store.

Of course, I did not intend to buy a key that I already have, so I chose the "...I already have a key..." option (I have in Windows 10 Pro product key).

Unfortunately, after entering the product key, the system still did not see the need to upgrade and stayed with the Home version.

Finally, I found a discussion on the Microsoft forum [^1] in which you need to change the parameters in the system registry and reinstall Windows to upgrade it.

> The entire procedure requires (depending on the hardware) about an hour+, but fortunately it does not involve the loss of any data, including applications. Everything remains as it was.

First of all, I needed [Windows 10 ISO image](/en/image-iso-windows-10/) saved and unpacked locally (we can use [7-Zip](https://www.7-zip.org) for this purpose)).

**And so we open the system registry.**

We can do it in two ways, although my favorite method is the keyboard shortcut `Windows Logo + R`, typing `regedit` in the newly opened Run... window and confirming with the Enter button.

[![Windows 10 Run regedit](Windows_10_run_regedit.png)](Windows_10_run_regedit.png)

This is how we will open our registry editor.

[![Windows 10 Registry Editor](Windows_10_registry_editor.png)](Windows_10_registry_editor.png)

> It is worth noting here that the changes we make are temporary and they will be restored to their original values after restarting the computer (some of them anyway). So if we decide to upgrade, we have to do it in one go.
> 
> It is also worth making sure that we have all available Windows updates installed, as this will significantly speed up the entire process.

And so we go to our base folder `HKEY_LOCAL_MACHINE > SOFTWARE`.

1. Then to `Microsoft\Windows NT\Current Version`

Here, in the right part of the window, we change the values of `EditionID` to `Professional` and `ProductName` to `Windows 10 Pro`.

[![Windows 10 Registry change 1st](Windows_10_regedit_change_1.png)](Windows_10_regedit_change_1.png)

2. Return to the basic folder and go to `WOW6432Node\Microsoft\Windows NT\Current Version` and make the same change as above.

3. Go to our unpacked Windows 10 installation image and run `setup.exe`.

If we have done everything correctly, after a shorter (or longer) analysis, the installer will ask us whether we want to install `Windows 10 Pro` with `Keep Files and Applications`.

{{% ads-in-article %}}

> If the installer still informs us about `Windows 10 Home`, then we close it and check our system registry again, in particular `Microsoft\Windows NT\Current Version`.

Now just wait and enjoy the effect.

---

If we have not previously entered our new product key for Windows 10 Pro (or we were not asked for it during the upgrade), go to `Windows Settings`, in the `Update and security` > `Activation` section, select the option to change (update) the key product.

If we have done everything correctly, the key will be entered and our system will activate automatically via the Internet.

---

With this method you can change the Home version (`EditionID: Core`) to the Professional version (`EditionID: Professional`) as well as to the Education version (`EditionID: Education`).

> In the case of the `Windows 10 Education` version, in the second step of changing the registry, `EditionID` will show `Enterprise` and `ProductyName: Windows 10 Enterprise`.

[![Windows 10 Registry change 2nd](Windows_10_regedit_change_2.png)](Windows_10_regedit_change_2.png)

[^1]: [answers.microsoft.com > downgrade from windows 10 pro to home](https://answers.microsoft.com/en-us/windows/forum/windows_10-windows_install/downgrade-from-windows-10-pro-to-home/345f5464-cb7a-44b3-8856-237cbec072c8)


---
## Best Mobile Photo Editor (2020)
- **URL:** https://dariusz.wieckiewicz.org/en/best-mobile-photo-editor-2020/
- **Date:** 2020-06-09
- **Tags:** Software, AppStore, photo editing, Google, iPhone, Snapseed

### Content

Even though I'm not a fan of excessive photo editing, sometimes even the best-taken photo just cries out for a little TLC (as the English say, "touch love care").

There are a ton of apps on the AppStore (and Google Play) that will help you achieve your goals. Some have just a few useful options, while others have limitations that force you to reach into your wallet to get what you want.

I've recently been going through a ton of apps to find the one that has everything I need to achieve the desired effect.

<!--more-->

On my phone, I have apps like [Photoshop Express](https://apps.apple.com/us/app/photoshop-express-photo-editor/id331975235) or [Lightroom](https://apps.apple.com/us/app/lightroom-photo-video-editor/id878783582) from Adobe and [Fine](https://apps.apple.com/gb/app/fine-photo-editor/id1391571907).

To play with photos I use [Prisma](https://apps.apple.com/us/app/prisma-photo-editor-filters/id1122649984) and [Animatrix](https://apps.apple.com/us/app/animatix-photo-animation/id1410307843), but recently I have been reaching for one application more and more often - [Snapseed](https://apps.apple.com/us/app/snapseed/id439438619).

* * *

**Snapseed** is a very powerful free tool with a lot of options that you would have to pay a lot for at the competition. No wonder it was bought some time ago (December 2012) and is owned by Google. I personally used it at the turn of the years, but somehow I never liked it, until now.

Most editing is done using intuitive gestures to the sides or up and down. There is no shortage of ready-made filters (**Look**), but the most extensive section is the available tools (**Tools**). After finishing the 'fun' we can save our photo (**Export**) with the changes made, which can be undone, or as a final file.

{{% gallery %}}
[![Home screen](snapseed-homescreen-with-image.jpg)](snapseed-homescreen-with-image.jpg)
[![Available tools](snapseed-tools.png)](snapseed-tools.png)
{{% /gallery %}}

[![Export](snapseed-export.png)](snapseed-export.png)

The application has an extensive tutorial in which we can get to know the possibilities of the application, as well as learn how to add magic to our photos in a professional way.

[![Tutorial](snapseed-tutorials.jpg)](snapseed-tutorials.jpg)

Of course, the app will not replace us. If we do not have a trained eye and our photos come out average, we will not suddenly turn them into a masterpiece.

Additional options worth checking include information about the photo, which will display basic data regarding the aperture or exposure, but will also read the geolocation and present it in the form of a Google map.

[![Photo Information](snapseed-image-details.jpg)](snapseed-image-details.jpg)

The options for the application itself (**Settings**) are very basic. We can set whether the application will somehow change the size of our image (disabled by default) and the quality of our final image will be saved (JPG 100% by default, but a PNG option is also available).

[![Options](snapseed-options.png)](snapseed-options.png)

[![Options, Format and Quality](snapseed-options-format-and-quality.png)](snapseed-options-format-and-quality.png)

Here's an example of one of the edits using the iPhone 11 Pro and the HDR filter in Snapseed.

{{% gallery %}}
[![Original](img_8629_original.jpg 'Original')](img_8629_original.jpg)
[![Snapseed + HDR](img_8629_snapseed.jpg 'Snapseed + HDR')](img_8629_snapseed.jpg)
{{% /gallery %}}

Of course, "best" is a relative term, so this may change in the future. Below are a few videos showing how the program works in a nutshell.

{{% ads-in-article %}}

By the way, I invite you to my [Instagram](https://www.instagram.com/dariusz.wieckiewicz/).

{{< youtube id="PJ1OubQFiAo" title="Look - Portrait & Accentuate" >}}*Look - Portrait & Accentuate*

{{< youtube id="TahN1OgX4Gs" title="Look - Tune Image" >}}*Look - Tune Image*

{{< youtube id="H6tKGYAWilQ" title="Tools - HDR" >}}*Tools - HDR*

{{< youtube id="WYk5mDHMoe8" title="Tools - Noir" >}}*Tools - Noir*

{{< youtube id="sv_cw8hVnUs" title="Tools - Brush" >}}*Tools - Brush*

**Regards**


---
## Turbocharge your internet connection (WARP, IPv6, OpenWrt)
- **URL:** https://dariusz.wieckiewicz.org/en/turbocharge-your-internet-connection/
- **Date:** 2020-05-29
- **Tags:** Internet, Cloudflare, IPv6, OpenWrt, VPN, WARP, WireGuard

### Content

Cloudflare is known for being the next Google and providing us with high-quality services, many of which can be used for free without any compromises. Fortunately, unlike Google, it is not so eager to kill its services.

From domain management, to [SSL certificate for your website](http://translate.google.com/translate?js=n&sl=auto&tl=en&u=https%3a%2f%2fdariusz.wieckiewicz.org%2fcertyfikat-ssl-dla-twojej-strony-www%2f), [secure and fast DNS](/en/secure-dns/), to turbocharging your internet connection with WARP (or WARP+ for those who want more).

<!--more-->

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

## Cloudflare WARP

WARP is a sort of VPN server designed to speed up your internet. However, it is not a true VPN like TunnelBear or others. It does not allow you to hide your original IP address or the country you are browsing from. WARP focuses on directing traffic in such a way that it is fast and secure.

WARP, in conjunction with DNS (Name Server) 1.1.1.1, encrypts traffic not only through DNS, but also between you (your device) and Cloudflare's servers. This ensures that only you (and Cloudflare) know what you're visiting online, not your ISP or the country's intelligence services that actively eavesdrop on your traffic, especially unencrypted traffic.

The name server itself (1.1.1.1) caused quite a stir and "speeded up" the internet. When it was joined with encryption of our DNS queries, creating the so-called secure DNS (DNS over HTTPS), WARP added its own, additionally encrypting the traffic leaving our device.

WARP is available as an app for various devices via official apps.

## Cloudflare WARP & WireGuard

At a time when Cloudflare desktop apps weren't available yet (they are now), I dug into this topic, trying to get a Cloudflare tunnel up and running using [the appropriate WireGuard app configuration](https://github.com/ViRb3/wgcf).

**Yes, you read correctly, Cloudflare uses a protocol based on WireGuard.**

In recent weeks, most major VPN providers have noticed the positive side of this solution and are adding it to their network (like NordVPN with their NordLynx).

> In my post I described [how to add a WireGuard-based VPN server to an OpenWrt router](/en/installing-vpn-server-on-router-openwrt-wireguard/).

Since Cloudflare WARP uses WireGuard for communication, you can also use our router as a VPN client.

**Why? I'll explain.**

Well, WARP is not only about encryption and speed, it is also IPv6 support. If your ISP (like mine) does not offer connection over IPv6, connecting to WARP gives us that option.

> Occasionally, the official Cloudflare app for macOS causes issues with IPv6 network access. Setting up a Cloudflare connection through WireGuard (using **wgcf**) rather than the official app helps fix this.

I recently described how to add an [IPv6 tunnel to our internet connection](/en/adding-ipv6-tunnel-router-openwrt/) in order to get access to the world via IPv6. However, this type of solution has a few drawbacks if your ISP (in my case Virgin Media in the UK) decides to introduce unwritten filtering and slowing down of traffic coming from these types of connections. In my case, the entry I created is ideal, but for me personally useless, so I am constantly looking for another solution.

When Cloudflare (1.1.1.1) desktop apps weren't available yet, I decided to use WireGuard and add WARP to my computer. Of course, I did it with [wgcf — Unofficial, cross-platform CLI for Cloudflare WARP](https://github.com/ViRb3/wgcf).

This got me thinking.

## Cloudflare WARP, WireGuard & IPv6

The [IPv6 tunnel (6in4) created by me according to my previous post](/en/adding-ipv6-tunnel-router-openwrt/) is not useful on my current connection (due to the speed being limited to 10% of my full connection speed), while IPv6 connectivity via WARP does not have such problems, I thought that since it uses WireGuard as a VPN server, why not use it as a client on my router?

Having the client and server on one device is somewhat strange, but entirely possible.

I use the WireGuard server to connect to my local network when I'm away from home. I would use the Wireguard client to add encryption to my internet traffic and IPv6 support using Cloudflare WARP.

Of course, connecting to WARP on the router side is one thing, but adding WARP support to devices on the local network is another, especially when it comes to IPv6 (which is not so obvious).

Adding WARP to the router is done by adding a new interface and configuring it. It is not extremely difficult and will allow us to use the Internet over IPv4 via a Cloudflare connection. More on that in a moment.

Another issue is with IPv6. Cloudflare does not assign us a range of IPv6 addresses to use, but only a local single address (in the /128 mask), which is then directed further with appropriate rules.

Once we have IPv6 available on the router, we can also use it to route traffic over this protocol using available rules and masquerading.

So let's see how to do it.

## Cloudflare WARP and a router with OpenWrt

First, we need to generate the Cloudflare WARP configuration file and then add it to our router.

### wgcf - the app

To do this, we log in to our OpenWrt router via SSH terminal and download the **wgcf** app.

Going to [**Releases**](https://github.com/ViRb3/wgcf/releases/latest) on GitHub, from the **Assets** section we need to download and save the version compatible with our hardware.

> In some browsers, the **Assets** list is displayed in a truncated form. To see all available files for various hardware platforms, we must additionally click the button below the list, **Show all XX assets**.

Going to our administration panel of the router with OpenWrt (default 192.168.1.1), after logging in, on the first information page we will immediately receive information, in the **Architecture** section, about what processor we have.

In my case it's **ARMv7** so I need to download the file `wgcf_2.2.30_linux_armv7`.

> At the time of updating this post, the latest version was version 2.2.30.

Using **curl**:

```bash
curl -L https://github.com/ViRb3/wgcf/releases/download/v2.2.30/wgcf_2.2.30_linux_armv7 > wgcf
```

or using **wget**

```bash
wget https://github.com/ViRb3/wgcf/releases/download/v2.2.30/wgcf_2.2.30_linux_armv7 -O wgcf
```

After downloading it, we add execution rights and run it without parameters to see if it works.

```bash
chmod +x wgcf
./wgcf
```

When everything works as it should, we can proceed to the next step, which is generating the necessary configuration files.

### wgcf - configuration file for WireGuard

Once we have `wgcf` on our router we need to register with Cloudflare WARP:

```bash
wgcf register
```

After accepting _Terms of Service_ we will receive the file `wgcf-account.toml`

Using this file (the app will use it itself) we will generate our configuration file:

```bash
wgcf generate
```

If everything went well, we will get the `wgcf-profile.toml` file. This file contains the WireGuard configuration, which we will use to set up the connection on our router.

> You can use the configuration file generated in this way on any device where you can [install the WireGuard app](https://www.wireguard.com/install/). As I mentioned earlier, in the case of the official Cloudflare WARP app for macOS, this method allows us to access the IPv6 network when the official app fails.

If you want to generate multiple accounts and individual profiles while linking them together, you can do so by using the same licence key. 

After generating your first `wgcf-account.toml`, but before creating the profile, open the file in your preferred editor and copy the `license_key` to your clipboard. Once you have generated the profile, move or rename both `wgcf-account.toml` and `wgcf-profile.toml`. Next, run the `wgcf register` command to create a new account file. Edit this new `wgcf-account.toml` by replacing the new `license_key` with the one you previously copied. Finally, use the `wgcf generate` command to create the linked profile.

### Setting interface

If you don't already have WireGuard installed on your router, do the following from an SSH terminal:

```bash
apk update
apk add luci-app-wireguard luci-proto-wireguard kmod-wireguard wireguard-tools
reboot
```

> Do not proceed unless you have restarted the router with the `reboot` command (third command in the above block).

After installing and restarting our router, we are ready for the next step.

We go to **Network > Interfaces** in our router administration panel via a web browser.

By clicking the **Add new interface...** button, we enter the name (**Name**), select the WireGuard VPN protocol (**Protocol**) and confirm with the **Create interface** button.

[![OpenWrt - Add New Interface - WireGuard VPN](OpenWrt_Add_New_Interface_WireGuard_VPN.png)](OpenWrt_Add_New_Interface_WireGuard_VPN.png)

After creating the interface, additional options will appear. Scroll to the bottom and click the **Load configuration...** button.

[![OpenWrt > Interface > WireGuard VPN - General Settings](OpenWrt_Interface_WireGuard_VPN_General_Settings.png)](OpenWrt_Interface_WireGuard_VPN_General_Settings.png)

In the terminal we read the contents of the file `wgcf-profile.toml`.

```bash
tail wgcf-profile.toml
```

We select and copy the content to the clipboard, paste it into the import field and finish by clicking the **Import settings** button. **Before you do that, read below.**

[![OpenWrt - WireGuard VPN - Import configuration](OpenWrt_WireGuard_VPN_Import_configuration.png)](OpenWrt_WireGuard_VPN_Import_configuration.png)

---

Before we save the settings, let's go to the **Firewall Settings** tab and add our connection to the **wan** group.

[![OpenWrt - Interface - WireGuard VPN - Firewall Settings](OpenWrt_Interface_WireGuard_VPN_Firewall_Settings.png)](OpenWrt_Interface_WireGuard_VPN_Firewall_Settings.png)

In the **Advanced Settings** tab of our new interface, in order to optimize speed we still need to change the default settings for MTU — Maximum transmission unit (**Use MTU on tunnel interface**) to 1280 (from the default 1420).

[![OpenWrt - Interface - WireGuard VPN - Advanced Settings](OpenWrt_Interface_WireGuard_VPN_Advanced_Settings.png)](OpenWrt_Interface_WireGuard_VPN_Advanced_Settings.png)

> The MTU is usually set to the MTU of our network connection minus 20. If our internet connection uses MTU 1500, then we set it to 1480. We can check our MTU for individual interfaces with the **ifconfig** command from the terminal. However, the author of the **wgcf** script recommends setting the MTU to 1280 as the maximum value.

Additionally, go to the **Peers** tab and click on the only configuration available there, the **Edit** button.

Select the **Route Allowed IPs** check button and enter the value **25** for **Persistent Keep Alive**.

[![OpenWrt - Interface - WireGuard VPN - Peer Settings](OpenWrt_Interface_WireGuard_VPN_Peer_Settings.png)](OpenWrt_Interface_WireGuard_VPN_Peer_Settings.png)

> **A small note.** Once we save and apply the changes to the **Route Allowed IPs** option, we will momentarily lose our internet connection, after which all our traffic will be routed through the Cloudflare connection.

---

As I noticed, enabling **Route Allowed IPs** caused [my WireGuard-based VPN server on the router](/en/installing-vpn-server-on-router-openwrt-wireguard/), as well as my [Cloudflare Zero Trust tunnel](/en/adding-cloudflare-tunnel-to-openwrt-router/), to stop working (being accessible from the Internet). This happened because the new interface took over IPv4 and IPv6 support. Editing **Peers** and removing IPv4 traffic routing (0.0.0.0/0) from the **Route Allowed IPs** section allows you to limit the use of the Cloudflare network to IPv6 traffic only. This way, when we do not have an Internet connection with IPv6, we will gain it throughout the network, but more on that in a moment.

---

Now we can save everything by clicking **Save**.

The next step is to click **Save & Apply** to apply the changes.

{{% ads-in-article %}}

### Check the interface

If we did everything correctly, our interface should start generating traffic visible in the **RX** and **TX** values.

> If these values ​​remain at Zero, then the connection is not working.

To make sure the connection is working, we can use **wgcf** on the router:

```bash
./wgcf trace
```

Among the data spat out by the above command, note the line **warp=** which should return the value **warp=on**.

### IPv6 Support

If our service provider does not offer us IPv6 access and the **wan6** interface, although enabled, does not have its own IP address, adding the Cloudflare WARP tunnel using the above method, we have also added IPv6 support to our router.

To check this, simply execute the **ping** command.

```bash
ping ipv6.google.com
```

or

```bash
ping -6 openwrt.org
```

IPv6 routed traffic is sent through the **Cloudflare** interface. If we removed the `0.0.0.0/0` address from **Route Allowed IPs**, then IPv4 traffic will be sent through our main internet connection **wan**. If we have both addresses added in **Route Allowed IPs**, then everything is sent through the Cloudfflare WARP network.

### Using Cloudflare connection in a local network (LAN)

This way our router has access to Cloudflare WARP. It responds to **ping** to addresses (domains) over IPv4, as well as IPv6 (using **ping** or **ping6**).

All that remains for us is to add the ability to support WARP on LAN devices.

Cloudflare assigns us an IPv6 address in the `/128` mask, which means we only get one exit address to the Internet. Unlike my previous post [Adding an IPv6 tunnel to a router with OpenWrt](/en/adding-ipv6-tunnel-router-openwrt/), in which adding an IPv6 tunnel allows you to assign external IPv6 addresses to devices in the LAN, here, in order for users in the LAN to use IPv6 access, we need to use masquerading and NAT66.

> This will work in a similar way to how we have set a default IPv4 address from our service provider. Every user on the internet will be visible under the same IP address, both IPv4 and IPv6.

To do this, we need to make some changes to our system.

#### Enabling IPv6 Masquerading

W sekcji **Firewall**, w panelu sterowania naszego routera OpenWrt, klikamy przycisk **Edit** w sekcji **Zones** przy strefie **wan**.

Przechodząc do **Advanced Settings** zaznaczmy opcję **IPv6 Masquerading** i klikamy przycisk **Save**, następnie potwierdzamy i wprowadzamy zmiany przyciskiem **Save & Apply**.

[![OpenWrt - Firewall - Zone - IPv6 Masquerading](OpenWrt_Firewall_Zone_IPv6_Masquerading.png)](OpenWrt_Firewall_Zone_IPv6_Masquerading.png)

Samo włączenie maskarady po IPv6 nie wystarczy, aby klienci w sieci LAN mogli komunikować się przez ten protoków. Przed włączeniem maskarady, **ping6** do adresu **ipv6.google.com** zwracał błąd, podczas gdy z włączoną maskaradą, odpowiedź pozostaje głucha. W związku z tym musimy dokonać jeszcze jednej zmiany.

#### Enabling IPv6 communication in LAN

Go to **Network > Interfaces** and click the **Edit** button next to the **lan** network.

Go to the **DHCP Server** tab and then to **IPv6 RA Settings**.

Here we change:
- **Default router** to **forced** (from *automatic*).
- **RA Flags** check both **(M)** and **(O)** (default is only *(O)*)

[![OpenWrt - Interface - LAN - DHCP Server - IPv6 RA Settings](OpenWrt_Interface_LAN_DHCP_Server_IPv6_RA_Settings.png)](OpenWrt_Interface_LAN_DHCP_Server_IPv6_RA_Settings.png)

We click the **Save** button, then confirm and make changes with the **Save & Apply** button.

When the settings are saved, clients in the local network automatically received IPv6 address assignments and communication over the IPv6 network was enabled through our router using IPv6 masquerading.

We can check this by executing the following command on a computer in the network:

```bash
ping6 ipv6.google.com
```

Or by going to [ipv6.google.com](https://ipv6.google.com), which should load without problems.

---

If you are having trouble interpreting domains and their IPv6 addresses, make sure that you have added both IPv4 and IPv6 DNS name servers in **Network > DHCP and DNS**, **Forwards** tab, and in **Interface > lan**, **Advanced Settings > Use custom DNS servers** section.

```
1.1.1.1
1.0.0.1
2606:4700:4700::1111
2606:4700:4700::1001
```

---

In this way, we gained IPv6 support in our network without any major problems.

The use of masquerading and NAT66 is not recommended, as it contradicts the ideology of IPv6 addresses, but in the case when we have an IPv6 address in the `/128` mask (i.e. one and only), it is more or less the only solution.

And that would be all.

If you don't want to bother with configuring your router for Cloudflare WARP, you can use the available applications by going to [1.1.1.1](https://1.1.1.1) and clicking the appropriate link. You can also configure WireGuard to support Cloudflare WARP using **wgcf**, as described above.

**Best regards.**


---
## Adding an IPv6 tunnel to a router with OpenWrt
- **URL:** https://dariusz.wieckiewicz.org/en/adding-ipv6-tunnel-router-openwrt/
- **Date:** 2020-05-13
- **Tags:** Cloudflare, Free IPv6 Tunnel Broker, Hurricane Electric, IPv4, IPv6, IPv6-in-IPv4, OpenWrt, RFC4213, Securebit AG, tunel IPv6, tunnelbroker

### Content

The UK’s service providers are very much behind the times when it comes to the latest technological developments. Given the somewhat phlegmatic attitude of the British people towards new technologies, it’s no wonder that ISPs are still stuck in the Stone Age (IPv4), even though the stones (the pool of IPv4 addresses) are gone. While I am lucky to have an external IPv4 address, I can forget about a version 6 address (thumbs down for Virgin Media).

**Luckily, there is a solution, and it's free!**

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

<!--more-->

This is an **IPv6 tunnel** using a 6-over-4 Tunnel solution.

If we have a router with OpenWrt, adding IPv6 support is not difficult and I will describe here how to do it.

> In my case, I'm adding an IPv6 tunnel as a curiosity, because I won't be able to use it on a daily basis. Why? You'll read it at the end of the post.

First, we need to add support for the **IPv6-in-IPv4** protocol by installing the appropriate package from the administration panel via a web browser (**System > Software**) or from the terminal using the command:

```bash
apk update
apk add 6in4 luci-proto-ipv6
```

> A small note. There is a **6in4** and **6to4** package available in the system. The names and usage are similar, but they are not the same. In this post I will use 6in4 (**IPv6-over-IPv4 (RFC4213)**), and **not** 6to4 (**IPv6-over-IPv4 (6to4)**).

We may already have the **luci-proto-ipv6** package installed if in the interfaces (**Network > Interfaces**) we see WAN6 already set with the default DHCPv6 client option.

> If you are not sure if your ISP offers IPv6, you can check it here . In the WAN6 interface, you should have an IPv6 address assigned (just like in WAN we have IPv4). If you do not see one, then continue to set it up. However, if your ISP provides an IPv6 solution, you do not need to do anything else.

At this stage I recommend restarting our router (**System > Reboot**), because when we edit our **WAN6** setting, we may not have the **IPv6-in-IPv4 (RFC4213)** option available in the protocol field (**Protocol**).

```bash
reboot
```

After restarting the router, we go to setting our interface (**Network > Interfaces**).

Alternatively, from the terminal:

```bash
/etc/init.d/network restart
```

* * *

Before we start entering any data, we need to set up an account with a service provider who will offer us an IPv6 tunnel service. In this case, we choose **[Hurricane Electric Free IPv6 Tunnel Broker](https://tunnelbroker.net)**.

After creating and confirming the account, log in and on the left side (**User Functions**) select (**Create Regular Tunnel**).

[![HE main page](01_he_main_page.png)](01_he_main_page.png)

In the next step we insert the external IP address of **our** router (**IPv4 Endpoint**) and choose which server in the world we will connect to to create a tunnel (**Available Tunnel Servers**). In my case I chose London, but in your case you may choose different.

[![HE Create new tunnel 1](02_1_he_create_new_tunnel.png)](02_1_he_create_new_tunnel.png)
    
[![HE Create new tunnel 2](02_2_he_create_new_tunnel.png)](02_2_he_create_new_tunnel.png)

At the end we will receive the addresses that we will enter on our router side.

[![HE Tunnel details](03_he_tunnel_details.png)](03_he_tunnel_details.png)

* * *

So going to the router (**Network > Interfaces**) we **Edit** our **WAN6** interface.

From the default **protocol** option we select **IPv6-in-IPv4 (RFC4213)** and confirm everything with the **Switch protocol** button.

[![wan6 default dhcpv6 client](04_wan6_default_dhcpv6_client.png)](04_wan6_default_dhcpv6_client.png)
    
[![wan6 ipv6 in ipv4 rfc4213](05_wan6_ipv6-in-ipv4_rfc4213.png)](05_wan6_ipv6-in-ipv4_rfc4213.png)

In the next step, in the **General Settings** tab, we leave the **Local IPv4 address** empty, as it will be automatically read from the WAN connection.

In the field **Remote IPv4 address** enter the address from the HE page, section **IPv6 Tunnel Endpoints** > **Server IPv4 Address**.

In the field **Local IPv6 address** enter the address from the HE page, section **IPv6 Tunnel Endpoints** > **Client IPv6 Address**. This is an address ending usually with **::2/64** as highlighted in the configuration form.

In the **IPv6 routed prefix** field we have the choice of entering from the **Routed IPv6 Prefixes** section. We can choose **Routed /64** or **Routed /48**.

> /64 will use a single IPv6 network, while /48 will use a larger pool of addresses on the IPv6 network. As a rule of thumb, /64 is recommended for the end client (home user), while /48 is recommended for the extended business client.
> 
> In short, in a /64 address pool, the router has one subnet in IPv6, and within that subnet, IPv6 addresses are allocated. This is similar to a standard LAN, where the router is 192.168.1.1 and users have .1.2, .1.3, and so on. In the case of /48, there can be more address pools and subnets. As with IPv4, you can have user 192.168.1.12 on one subnet and user 192.168.2.12 on a second subnet.
> 
> Depending on the sophistication of your configuration and the number of users, you should decide what is best for you. Personally, I recommend leaving /64.

So we copy the value from **Routed /64** to **IPv6 routed prefix** and click the (**+**) button.

If our external IP address changes, then it is also recommended to add an automatic refresh of the IP address (**endpoint**) (we can skip this step in the case of a static IP address).

[![wan6 ipv6-in-ipv4 rfc4213 dynamic tunnel](06_wan6_ipv6-in-ipv4_rfc4213_dynamic_tunnel.png)](06_wan6_ipv6-in-ipv4_rfc4213_dynamic_tunnel.png)

Let’s select **Dynamic tunnel** and fill in the following fields.

In **Tunnel ID** we enter the value from the HE page. This is the first value in the tunnel details (**Tunnel Details**) that we received after its creation.

In **HE.net username** we enter our username which we use to log in to the [tunnelbroker.net](http://tunnelbroker.net) website.

[![HE tunnel details advanced](07_he_tunnel_details_advanced.png)](07_he_tunnel_details_advanced.png)

In **HE.net password** we need to enter the generated key, which is used to update the IP address. Therefore, we go to the HE page and in the Advanced tab of our tunnel, we copy the value from the **Update Key** field and paste it on the router side.

The penultimate step is to save our configuration (**Save**) and confirm by **Save & Apply** on the next screen.

* * *

Theoretically everything should work now, but in practice this is not always the case.

Even though we added network configuration, after saving and applying changes, only the network configuration is refreshed, not necessarily the **Firewall**.

Therefore, we need to go to the terminal and execute one command:

```bash
/etc/init.d/firewall restart
```

Or restart your router and you're good to go.

> On the router side, in the Advanced Settings tab of our WAN6 interface, to optimize speed we can change the default settings for **Use MTU on tunnel interface** to 1480 (from 1280).
> 
> We set the MTU according to the MTU of our network connection reduced by 20. If our Internet connection uses MTU 1500, then we set it to 1480. We can check our MTU for individual interfaces with the **ifconfig** command from the terminal.

* * *

{{% ads-in-article %}}

## Check

If we did everything correctly, our router should gain an IPv6 connection.

To check this, from the terminal level we perform **ping** (or **ping6**).

```bash
ping ipv6.google.com
```

From a computer on your home network, go to [https://ipv6test.google.com](https://ipv6test.google.com/) or [https://ipv6.google.com](https://ipv6.google.com)

Both **ping** and web pages should be accessible.

The final step is to go to [https://test-ipv6.com](https://test-ipv6.com/) to confirm that everything is working.

We should get a score of **10/10**.

* * *

If we have also set **[Secure DNS](/en/secure-dns/)** on our router according to my description, with IPv6 support, then when we go to [https://one.one.one.one/help](https://one.one.one.one/help/) we will see in **Connectivity to Resolver IP Addresses** the response from our DNS by IP address in the form IPv6 .6:4700:4700::1111 and.6:4700:4700::1001).

[![Cloudflare 1111 help page](08_cloudflare_1111_help_page.png)](08_cloudflare_1111_help_page.png)

* * *

If you've set up your [**VPN server on your router using WireGuard**](/en/installing-vpn-server-on-router-openwrt-wireguard/) as described in my post and [**added a domain to your router IP address**](/en/setting-domain-for-dynamic-ip-address-openwrt-ddns/), also as described in my post, then it's worth adding an **AAAA** record pointing to your IPv6 address (the one with **::2**). This way, **in theory** you can connect to the VPN via both IPv4 and IPv6.

* * *

Now that's really everything.

Thanks to this procedure, we have added IPv6 support on the side of our router, even though our service provider screwed up and only supports IPv4.

> The negative side of this solution is that ISPs can do everything to prevent IPv6 tunnels from being used in their network. This is the case with Virgin Media in the UK, for example, which, although it allows you to set up a tunnel, its efficiency is at 10%. With a 100/10Mbps connection, we achieve speeds of max. 6-10/3-6Mbps.
> 
> The same tunnel installed on another service provider's connection (CityFibre 100/100) works at its full speed.
> 
> You can read more [here](https://medium.com/@jamesmacwhite/is-virgin-media-traffic-shaping-protocol-41-6in4-ipv6-c1b8b6e645f7).

**Regards.**

***

_Credits_

- [openwrt.org > docs > guide-user > network > ipv6 > ipv6tunnel-luci](https://openwrt.org/docs/guide-user/network/ipv6/ipv6tunnel-luci)


---
## Adding a torrent client to a router with OpenWrt
- **URL:** https://dariusz.wieckiewicz.org/en/adding-torrent-client-router-openwrt/
- **Date:** 2020-05-05
- **Tags:** Blocklist, iBlocklist, OpenWrt, torrent, Transmission, BitTorrent client, Transmission BitTorrent client

### Content

So you want to add a torrent client to your OpenWrt router, so that you can download, for example, a [Raspbian image](https://www.raspberrypi.org/downloads/raspbian/) using this method, save it to a previously [connected and configured USB drive](/en/adding-usb-drive-to-router-openwrt/) and access it [from the local network](/en/sharing-usb-drive-over-the-network-router-openwrt/)?

<!--more-->

Nothing simpler. For this purpose we will use **Transmission**.

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

## Transmission Installation and Configuration

You can install it from the administration panel via a web browser (**System > Software**) or from the terminal:

```bash
apk update
apk add transmission-daemon transmission-web luci-app-transmission
```

The **luci-app-transmission** application will allow us to customize additional options from a web browser without the need to edit files from the terminal.

The **transmission-daemon-openssl** package is a program that will run in the background of our router, and **transmission-web** is a separate access to our program from a web browser to add or remove a downloaded file.

Let's start by configuring the settings.

We go to our router's control panel, then **Services > Transmission**.

[![OpenWrt > Services > Transmission](openwrt_services_transmission.png)](openwrt_services_transmission.png)

Before we mark the configuration as enabled (**Enabled**), let's go through a few settings. The most important of them is where our files are to be saved.

In the **Files and Locations** section we enter the folder locations in **Downloads locations.** In my case it is on a USB drive mounted as `/mnt/sda1`. Additionally, I have enabled saving in-progress (incomplete) files in a separate folder (check **Incomplete directory enabled**).

In the **Miscellaneous** settings I changed the encryption from Preferred and **Forced**.

I also set up a blacklist (**Blocklist**) by selecting **level1** or **Bluetack** from [iBlocklist](https://www.iblocklist.com/lists.php).

The rest I leave to your discretion.

Let's check the **Enable** option at the beginning of the settings and click **Save & Apply**.

---

If your **luci-app-transmission** application returns information about missing `Run daemon as user` and `Run daemon as group` fields, which makes it impossible to save the settings, as shown below, you need to use terminal to fix it.

[![luci-app-transmission 21.02 non-empty value](transmission_21_02_non-empty_value.png)](transmission_21_02_non-empty_value.png)

```bash
sed -i '/"file": {/a\\t\t\t\t"/etc/passwd": [ "read" ],\n\t\t\t\t"/etc/group": [ "read" ],' /usr/share/rpcd/acl.d/luci-app-transmission.json
service rpcd restart
```

---

## Transmission Startup

Unfortunately, at the moment, even though **luci-app-transmission** has the **Enabled** option set and should start **transmission-daemon** by default, it does not.

To run our program, from the terminal we put the command:

```bash
/etc/init.d/transmission start
```

Then we go to the transmission panel, by default **http://192.168.1.1:9021/transmission/web/** where we add our torrent.

[![Transmission downloading raspbian buster full](transmission_downloading_raspbian-buster-full.png)](transmission_downloading_raspbian-buster-full.png)

To stop Transmission we can kill the process from the router administration panel **System > Processes** or from the terminal:

```bash
/etc/init.d/transmission stop
```

If you have any problems getting it to work, I recommend running the `logread` command from the terminal to analyze the errors.

If we want to manually change the settings in the file from the terminal, **after stopping the daemon** just edit `/etc/config/transmission`. Sometimes it can be necessary if we mess up the settings too much.

> In the **Config file directory** section from the browser, or `option config_dir` in the configuration file, I recommend changing `/tmp/transmission` to `/root/transmission`. This will save the transmission daemon's working folder in a permanent location, not a temporary one. This is important for the **Blocklist** file, which will remain on the router after it is restarted.

{{% ads-in-article %}}

## OpenWrt 22.03+ (23.05, 24.10, 25.12) problem

As with any update, sometimes something breaks or stops working in the system.

Transmission versions **3.00** (OpenWrt 22.03) and **4.00** (OpenWrt 23.05) use something like `procd_ujail` and `seccomp` in their startup script. Without going into detail about what these packages are useful for, I'll just focus on the fact that they cause a problem with Transmission ([Issue #19376](https://github.com/openwrt/packages/issues/19376)).

Open the configuration file does not save correctly. When saving files, an error related to lack of disk space is displayed or the torrent does not pass the final verification after downloading. In a word, a mess.

To fix this problem, you can remove the `procd_ujail` and `procd_seccomp` packages, however this is not always a good solution, as other packages on the system may require them to work, so they may be installed inadvertently or uninstallation (`apk del ...`) may fail.

Another solution, unfortunately also short term, is to modify the transmission start script. Fortunately (or not), transmission is not updated that often, so this solution may become a kind of long term solution.

First we need to stop the transmission.

```bash
/etc/init.d/transmission stop
```

Then we start editing the initialization file. For this purpose I use `nano` but you can also use the built-in `vim`.

```bash
nano /etc/init.d/transmission
```

Scroll down the file until you see the `secomp_path` and `procd_add_jail` sections, then comment (`#`) the appropriate lines as shown below.

> OpenWrt 22.03, Transmission 3.0

```bash
#       seccomp_path="/etc/seccomp/transmission-daemon.json"
#       if [ -f "$seccomp_path" ]; then
#               procd_set_param seccomp "$seccomp_path"
#       fi

        if [ -z "$USE" ]; then
                procd_set_param limits core="0 0"
        else
                procd_set_param limits core="0 0" as="$USE $USE"
                logger -t transmission "Starting with $USE virt mem"
        fi

        [ -d "$web_home" ] && procd_set_param env TRANSMISSION_WEB_HOME="$web_home"
        [ "$ca_bundle" -gt 0 ] && procd_set_param env CURL_CA_BUNDLE="$ca_bundle_file"

#       procd_add_jail transmission log
#       procd_add_jail_mount "$config_file"
#       procd_add_jail_mount_rw "$config_dir/resume"
#       procd_add_jail_mount_rw "$config_dir/torrents"
#       procd_add_jail_mount_rw "$config_dir/blocklists"
#       procd_add_jail_mount_rw "$config_dir/stats.json"
#       procd_add_jail_mount_rw "$download_dir"
        web_home="${web_home:-/usr/share/transmission/web}"
#       [ -d "$web_home" ] && procd_add_jail_mount "$web_home"
#       [ -f "$ca_bundle_file" ] && procd_add_jail_mount "$ca_bundle_file"
        procd_close_instance
}
```

> OpenWrt 23.05+ (24.10, 25.12), Transmission 4.00

```bash
#       seccomp_path="/etc/seccomp/transmission-daemon.json"
#       if [ -f "$seccomp_path" ]; then
#               procd_set_param seccomp "$seccomp_path"
#       fi

        if [ -z "$USE" ]; then
                procd_set_param limits core="0 0"
        else
                procd_set_param limits core="0 0" as="$USE $USE"
                logger -t transmission "Starting with $USE virt mem"
        fi

        [ -d "$web_home" ] && procd_append_param env TRANSMISSION_WEB_HOME="$web_home"
        [ "$ca_bundle" -gt 0 ] && procd_append_param env CURL_CA_BUNDLE="$ca_bundle_file"

#       procd_add_jail transmission log
#       procd_add_jail_mount "$config_file"
#       procd_add_jail_mount_rw "$config_dir/resume"
#       procd_add_jail_mount_rw "$config_dir/torrents"
#       procd_add_jail_mount_rw "$config_dir/blocklists"
#       procd_add_jail_mount_rw "$config_dir/stats.json"
#       procd_add_jail_mount_rw "$download_dir"
#       [ "$incomplete_dir_enabled" = "1" ] && procd_add_jail_mount_rw "$incomplete_dir"
#       [ "$watch_dir_enabled" = "1" ] && procd_add_jail_mount_rw "$watch_dir"
        web_home="${web_home:-/usr/share/transmission/public_html}"
#       [ -d "$web_home" ] && procd_add_jail_mount "$web_home"
#       [ -f "$ca_bundle_file" ] && procd_add_jail_mount "$ca_bundle_file"
        procd_close_instance
}
```

Make sure to comment out both `seccomp` and `jail`, because leaving `seccomp` will cause our transmission daemon to hang constantly.

We save our file and run transmission again.

```bash
/etc/init.d/transmission start
```

This way transmission will work correctly.

Regards.


---
## Sharing a USB drive over the network from an OpenWrt router
- **URL:** https://dariusz.wieckiewicz.org/en/sharing-usb-drive-over-the-network-router-openwrt/
- **Date:** 2020-05-05
- **Tags:** OpenWrt, Samba, USB, USB 3.0, WRT3200ACM, Windows 10, Windows 11

### Content

Continuing my post [Adding a USB drive to a router with OpenWrt](/en/adding-usb-drive-to-router-openwrt/) using the USB port (using the Linksys WRT3200ACM as an example), we move on to sharing our drive on the local network.

<!--more-->

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

We start by installing two packages. We can do this from the administration panel via a web browser or from the terminal. The first package installs the Samba server, while the second adds the ability to operate it from a graphical interface via a web browser.

```bash
apk update
apk add samba4-server luci-app-samba4
```

The installation will take a while because in addition to the two main packages, it is necessary to install companion packages.
    
```
Package samba4-server (4.11.6-1) installed
Package luci-app-samba4 (git-20.105.64099-eeba108-1) installed
```

Next, we log into our administration panel from a web browser. We go to **Services > Network Shares**.

[![OpenWrt - Services > Network Shares](openwrt_services_network_shares.png)
](openwrt_services_network_shares.png)

In the **General Settings** tab we make several settings.

[![OpenWrt > Network Shares > Samba > General Settings](openwrt_network_shares_samba_general_settings.png)](openwrt_network_shares_samba_general_settings.png)

Even though we don't have to, we set the interface (**Interface**) on which Samba will run to LAN (the default, if not specified, is LAN). If we want, we can set the name of our home network (**Workgroup**) and a description (**Description**).

As for the remaining settings, as a user of an Apple computer, I checked **Enable macOS compatible shares**.

> **However, if we experience problems with unmounting our disk in macOS, we should leave this option unchecked.**

Before we go any further, I click **Save & Apply**.

In the **Shared Directories** item, click the **add** button, which will give you a short form to fill out.

[![OpenWrt > Network Shares > Samba > Shared Directories](openwrt_network_shares_samba_shared_directories.png)](openwrt_network_shares_samba_shared_directories.png)

In the **name** field, enter the name of our share as we want it to be seen from the network level.

In the **path** field, we enter the location of our mounted disk, in my case `/mnt/sda1`.

We leave the **Browseable** and **Allow guests** options selected by default.

If we want to use our disk for backup purposes, from a computer with macOS we select **Apple TimeMachine share** and define (optionally) a disk limit for backups.

I confirm everything by clicking **Save & Apply**.

For a standard user, these settings are sufficient. However, if you want to change advanced sharing options, you can always go to the **Edit Template** tab.

* * *

At this stage we need to check if our sharing is working.

In the case of macOS, we open a new **Finder** window, go to the Network tab and search for our router. Then intuitively click one by one until we open our shared folder.

We can also select **Go > Connect to server** from the Finder menu, where we enter the address **smb://192.168.1.1/** (where 192.168.1.1 is the address of our router) and click **Connect**.

And that's it. Our disk should be working and visible on the network.

If you added the disk according to my [previous post](/en/adding-usb-drive-to-router-openwrt/), you can unmount the disk from the router (`block umount`) at any time and connect it to a macOS or Windows computer. Thanks to the use of exFat partition, there is no problem with visibility of the disk's contents regardless of where the device is running.

{{% ads-in-article %}}

## Problem in Windows and its solution

While accessing a shared drive using a user account available on our router is not a problem, many of us would prefer to have access using a guest account.

In the latest versions of Windows, for security reasons, changes have been made to access network resources.

Access using the Guest account is not possible and results in an error when accessing resources. Entering the username **Guest** and leaving the password field blank also does not help much.

![Entering Guest Network Credentials](Wprowadzenie-poswiadczen-sieciowych-Guest.png)

![Access denied](Odmowa-dostepu.png)

However, we can easily change this.

Just run **Command Prompt** in administrator mode (otherwise you will get an **Access Denied** message) and execute the command below, which will add the appropriate entry to the system registry.

```
reg add HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters /v AllowInsecureGuestAuth /t reg_dword /d 00000001 /f
```

After making the change, we restart our system.

Now, when we try to access the network resource again, we will also receive a message asking us to enter a username and password. This time, however, we can easily enter the **Guest** username and confirm the whole thing with the **OK** button without having to enter a password.

![Shared folder usb0](Udostepniony-folder-usb0.png)

Regards.


---
## Adding a USB drive to a router with OpenWrt
- **URL:** https://dariusz.wieckiewicz.org/en/adding-usb-drive-to-router-openwrt/
- **Date:** 2020-05-05
- **Tags:** block-mount, hd-idle, hdparm, mount, OpenWrt, USB, USB 3.0, usbutils, WRT3200ACM

### Content

Today's solution is a bit unusual - my network drive (NAS) recently stopped working, and to sort it out I need to do some digging in it. In the meantime, I would like to use the USB 3.0 port built into my WRT3200ACM router with OpenWrt software to share a USB drive on the network.

<!--more-->

For this purpose, I use a 2TB WD My Book Essential (3.5” with external power) with a USB 3.0 port. I formatted the drive in exFat (from the computer I started with) for compatibility with both Windows and Mac. When I want to disconnect it from the network, I will always have access to the data by connecting the USB cable directly to the computer.

So here we go...

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

Most steps are performed from the terminal.

In this post I will focus on how to add a drive to a router. In a separate post (link at the end) I will describe how to share this drive on a local network.

## Installing USB Drive Support

First, we update the packages.

```bash
apk update
```

Next we add support for USB devices.

```bash
apk add kmod-usb-storage kmod-usb-storage-uas
```

In my case I need to add exFat support as well. Depending on which file system you choose, you need to install it according to [this guide](https://openwrt.org/docs/guide-user/storage/filesystems-and-partitions).

```bash
apk add kmod-fs-exfat libblkid1
```

In addition, we will need tools to check if our USB device is working properly. We install them using the following command:

```bash
apk add usbutils
```

Now we can connect our drive.

If we did everything correctly, by executing the command below, we will see our disk in the list of devices connected to USB.

```bash
lsusb -t
```

We should see something like this:

```
root@OpenWrt:~# lsusb -t
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
    |__ Port 1: Dev 4, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
```

or in case of supported protocol [UASP](https://en.wikipedia.org/wiki/USB_Attached_SCSI):

```
root@OpenWrt:~# lsusb -t
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
    |__ Port 1: Dev 4, If 0, Class=Mass Storage, Driver=uas, 5000M
```

## Checking disk visibility

We check whether our disk and partitions are visible in the system.

```bash
ls -l /dev/sd*
```

We should see something like this:

```
root@OpenWrt:~# ls -l /dev/sd*
brw-------    1 root     root        8,   0 May  1 21:20 /dev/sda
brw-------    1 root     root        8,   1 May  1 21:20 /dev/sda1
```

In the next step, we will install an additional tool that we will use to mount the partition.

```bash
apk add block-mount
```

We execute the command:

```bash
block info | grep "/dev/sd"
```

We should see something like this:

```
root@OpenWrt:~# block info | grep "/dev/sd"
/dev/sda1: UUID="5EAC-6F27" LABEL="2TB" TYPE="exfat"
```

{{% ads-in-article %}}

## Mounting the disk

We prepare the configuration file:

```
block detect | uci import fstab
```

Enabling automatic mounting based on the generated configuration file:

```bash
uci set fstab.@mount[-1].enabled='1'
uci commit fstab
```

We mount our disk:

```bash
block mount
```

_(Optional)_ If we want to make sure that automatic disk mounting works at system startup, we execute:

```bash
reboot
```

We check if our disk is visible using:

```bash
df
```

We should see something like this:

```
root@OpenWrt:/mnt# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1            195341.     10368 1953408896   0% /mnt/sda1
```

And:

```bash
uci show fstab
```

We should see something like this:

```
root@OpenWrt:~# uci show fstab
fstab.@mount[0]=mount
fstab.@mount[0].target='/mnt/sda1'
fstab.@mount[0].uuid='5EAC-6F27'
fstab.@mount[0].enabled='1'
```

If you have any problems, make sure that the **@mount[0].enabled** field is set to **1**.

If we have any data on the disk, we can see it:

```bash
ls -l /mnt/sda1
```

We make sure that everything works properly by executing the command:

```bash
block info
```

We should see something like this:

```
root@OpenWrt:~# block info
/dev/sda1: UUID="5EAC-6F27" LABEL="2TB" MOUNT="/mnt/sda1" TYPE="exfat"
```

We finish it all with the command:

```bash
service fstab boot
```

* * *

## Disk Sleep - SpinDown (Optional)

My WD caddy has built-in software that suspends/puts the drive motor to sleep after a period of time. The drive is still accessible, but when not in use, it won't spin up unnecessarily. When the drive is needed, it will spin up again.

If we do not have the software option, then we can use an additional solution that will allow us to program the disk directly to do the same thing.

To do this, we install **hdparm**:

```bash
apk update
apk add hdparm
```

Assuming (from the above steps) that our disk is available as **/dev/sda1**, the following command sets the time after which the disk will go into suspend mode. We set this time as a multiple of 5 seconds. A minute is the value of 12, if we want to set 15 minutes, we need the value of 180.

```bash
hdparm -S 180 /dev/sda1
```

The above option is a hardware option. It introduces changes to the disk settings, so that they are preserved even when we connect our disk to another device / computer. Unfortunately, it does not always work. Some enclosures refuse to accept the above command, returning an error. In this case, there is an additional software solution called **hd-idle**, which can be integrated with our router administration panel from a web browser.

The **hd-idle** package, after a specified period of time (defined in the administration panel), sends the **spindown-now** command to turn off disk spin-up and enter standby mode.

We install it using the command:

```bash
apk add luci-app-hd-idle
```

Then we go to our web control panel, **Services > HDD idle**, where we set whether this software option should be enabled, for which disk and the time.

[![OpenWrt Service hdd idle](openwrt_service_hdd_idle.png)](openwrt_service_hdd_idle.png)

[![OpenWrt hdd idle](openwrt_hdd_idle.png)](openwrt_hdd_idle.png)

I recommend first checking whether the hardware option works (whether built-in or programmed), as it does not require any additional packages that must be enabled on our router, and only then choose a software solution.

* * *

And that would be it, when it comes to adding a disk, we can move on to sharing our disk on the local network. However, I described this step in a separate entry: **[Sharing a USB drive over the network from an OpenWrt router](/en/sharing-usb-drive-over-the-network-router-openwrt/)**

* * *

Credits[^1]  

[^1]:[https://openwrt.org/docs/guide-user/storage/usb-drives](https://openwrt.org/docs/guide-user/storage/usb-drives)



---
## OpenWrt Firmware Update (without losing installed packages)
- **URL:** https://dariusz.wieckiewicz.org/en/firmware-update-openwrt/
- **Date:** 2020-04-24
- **Tags:** firmware, Backup, OpenWrt, software, packages, OpenWrt Update, OpenWrt Firmware Update

### Content

Whether you have reinstalled OpenWrt or updated it, even though you have backed up your settings, any additionally installed packages have not (will not) been preserved, so restoring the settings will not make everything as it was. For now, this is normal behavior with OpenWrt. Therefore, you need to think about how to approach this so that the update and restore of settings will proceed as expected, **i.e. together with the packages**.

<!--more-->

Therefore, **before updating the router, you need to generate a list of installed packages** that we will need to restore (install) before restoring our settings from a backup.

Installing a clean OpenWrt firmware is not a problem. The trouble begins when we want to update the currently installed one to the latest available version. In this case, we have the option of installing the latest software along with preserving the settings (but not the packages) or restoring the default settings.

**I personally encourage you to install (update) without saving the settings and start from scratch**. This is because if we have installed a package, even the one described here: [DNS over HTTPS](/en/secure-dns/), after restarting, our internet will not work, because the current settings in the router will try to redirect traffic through a package that is not in the system and everything will start to fall apart.

So how do we do everything correctly? Well, we'll do it in the following steps.

Since I recently managed to replace my ASUS RT-AC57U router with the very powerful Linksys WRT3200ACM, I wanted to transfer everything I already have set up on the ASUS to the Linksys. Unfortunately, the differences in hardware and configuration files mean that everything is not so easy. There is no way to make a copy on one and restore (after uploading packages) on the other. The solution is to make a copy on two routers and compare the files from the old one and add what is missing to the new one. A laborious solution, but it also works.

**Within the same device, everything will proceed according to the below diagram.**

> **A small note.**
> If you are using only the pure OpenWrt firmware and do not add any additional packages, you do not need to go any further into my post. Then you install the new firmware while preserving the current settings or simply restore the settings from a saved backup and everything works. The next steps are primarily for people who use OpenWrt in its extended capabilities.

Let's begin.

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

---

Even though **22.03** is based on Firewall4, we can successfully upgrade from 21.02.x to 22.03.x using the following method. The Firewall package will be skipped (along with other incompatible packages) and replaced by the existing Firewall4. You don't have to worry about getting any errors while restoring packages.
 
Due to the change of the cryptographic package in version **23.05** from `wolfssl` to `mbedtls`, when upgrading from version 22.03 to 23.05 with restoring packages from the previous version, I recommend making a few changes to avoid unnecessarily installing this package in our system.

In the case of a software version jump, such as from **23.05** to **24.10** (and to **25.12**), in theory everything should go smoothly, however, as with any major change, there is a possibility that our router will not turn on. As I had with my Askey RT4230W REV6 (RAC2V1K) router. Although from version 21.02 to 22.03 and 23.05, there were no problems, the project maintainers introduced a lot of changes in 24.10, which may be incompatible with the current settings.

In my case, I had to reset the router to factory settings and start from scratch. Fortunately, the generated backup file allowed me to save my settings, which, step by step, I was able to restore.

> After a deeper analysis, I noticed that my interfaces (network ports) had changed their name, for example `option device 'eth0.2'` changed to `option device 'wan'`. In the future, this makes sense when transferring package configurations between different devices. There were more changes, so I decided to restore everything manually and at the same time check the validity of my posts regarding OpenWrt.

In the `my_installed_packages` file, which we will generate before starting the update and which we will create a backup copy of on our computer, I recommend opening it in Notepad (or another such program) and searching for all entries with `wolfssl` and deleting them. If any package needs it, it will install it automatically anyway.

We install the packages as described below, and then restore the configuration.

Since each major update brings a lot of changes, I recommend taking some time and manually installing the packages we use, freshly loading OpenWrt and then using a backup restore. Then, updating from version 23.05.0 to the next in the series, which will be released in the future, should be problem-free as described.

---

## Backup of current settings

First, go to the administration panel via a web browser.

There we select **System > Backup / Flash firmware**

[![OpenWrt - System Backup - Flash Firmware](01-openwrt-system-backup-flash-firmware.png "OpenWrt > System > Backup / Flash Firmware")](01-openwrt-system-backup-flash-firmware.png)

To make a backup copy of your settings, simply click the Generate archive button in the Backup section.

[![OpenWrt - System Backup - Flash Firmware - Generate Archive](02-openwrt-system-backup-flash-firmware-generate-archive.png "OpenWrt > System > Backup / Flash Firmware > Generate Archive")](02-openwrt-system-backup-flash-firmware-generate-archive.png)

Before we do that, I personally recommend changing the settings to extend the backup scope to additional folders. If you have used my guide, including [how to add a VPN server to your router](/en/installing-vpn-server-on-router-openwrt-wireguard/), in the **Configuration** tab we add additional folders.

```
/etc/ssl/
/etc/wireguard/
/etc/config/
/root/
```

[![OpenWrt - System Backup - Flash Firmware - Configuration](03-openwrt-system-backup-flash-firmware-configuration.png "OpenWrt > System > Backup / Flash Firmware > Configuration")](03-openwrt-system-backup-flash-firmware-configuration.png)

Although by default the backup copies modified files to the **/etc/config** folder, I personally prefer to have a complete copy of this folder.

> What we have defined at this stage is stored by default in the **/etc/sysupgrade.conf** file during a standard software update.

Next, we click the **Save** button and go back to the **Actions** tab and generate our backup archive (**Generate archive**).

* * *

## Generating a list of installed packages

With the settings backed up, it's time to generate a list of packages that we have installed on the system. Notice that in the previous step I added the **/root/** folder to include in the settings backup scope. In this folder I have a file saved that contains, among other things, a list of packages, which we will save in a moment.

If we are transferring settings from one router to another, it is worth copying and writing down this list, which I will also write about.

So, to generate a list of installed packages, we execute the command in the SSH terminal:

```bash
apk info > /root/my_installed_packages
```

It is also a good idea to save this list to your local computer.

I will not describe here how to do it using various methods (different for different operating systems), because it is a waste of time.

The file you need will be saved in the freshly generated backup from earlier step. Go back one step and you're done. Just unpack your **backup** with **Keka** (for macOS) or **7Zip** (for Windows) and look for it in the **/root/** folder. Easy!

We can also execute the command:

```bash
cat /root/my_installed_packages
```

And using the copy/paste method, copy the contents to a file on our computer.

* * *

## OpenWrt Firmware Update with Restoring Default Settings

At this stage I will not go into detail on how to install the OpenWrt software on your router, as it depends on the hardware you are using (I refer you to [here](https://openwrt.org/toh/start)). I assume that your router already has the OpenWrt software installed - either clean or a different version that you will want to update.

The software update is performed from **System > Backup / Flash firmware**, in the **Flash new firmware image** section.

[![OpenWrt - System Backup - Flash Firmware](04-openwrt-system-backup-flash-firmware.png "OpenWrt > System > Backup / Flash Firmware")](04-openwrt-system-backup-flash-firmware.png)

Of course, we choose the software prepared for our version of the router.

We upload the file to our router and at the appropriate step we choose **WHETHER** we want to keep our router settings or not (**Keep settings and retain the current configuration**). Personally, I prefer NOT to keep them, because in my case, [with DoH set](/en/secure-dns/), my DNS will not work, so I will not be able to perform the next steps.

[![OpenWrt - System Backup - Flash Firmware - Uploading file](05-openwrt-system-backup-flash-firmware-uploading-file.png "OpenWrt > System > Backup / Flash Firmware > Uploading file")](05-openwrt-system-backup-flash-firmware-uploading-file.png)

[![OpenWrt - System Backup - Flash Firmware - flash image](06-openwrt-system-backup-flash-firmware-flash-image.png "OpenWrt > System > Backup / Flash Firmware > flash image")](06-openwrt-system-backup-flash-firmware-flash-image.png)

You can experiment with keeping your settings and restoring packages (next step), but keep in mind that after restoring previously installed packages, you may need to restore a backup anyway.

* * *

{{% ads-in-article %}}

## Restore packages from previously generated list

Upewniając się, że nasz router posiada działające połączenie z internetem, łączymy się z naszym routerem za pomocą terminala SSH (domyślnie musimy to zrobić na kablu LAN, gdyż WiFi z reguły jest wyłączone):

```bash
ssh root@192.168.1.1 -p 22
```

First of all, I would recommend updating the packages that are currently on the system before we attempt to restore them. We do this with the command:

```bash
apk update; apk upgrade
```

> In some cases, the above command will display a download error (*Failed to download*) or return information that we do not have an internet connection (*Check your network settings and connectivity*).
>
> Then you should run the command: **`apk update`** separately, install the latest version of **wget** using **`apk add wget`** and download the latest CA certificates:

```bash
wget  --no-check-certificate -O /etc/ssl/certs/ca-certificates.crt http://curl.se/ca/cacert.pem
```

> Then, repeating the above command should make everything work.

Time to restore packages.

If we are starting from scratch, we need to generate the file **my_installed_packages**

```bash
touch /root/my_installed_packages
```

Then we move on to editing it.

```bash
vim /root/my_installed_packages
```

By clicking the "**i**" key we enter the editing mode. Now, using Copy/Paste we transfer the contents of our file from the backup copy (or in the file to which we saved the contents of **my_installed_packages** from the previous steps). After successfully pasting the contents, click the **Esc** button and then execute "**:w**" to save the contents, and "**:q**" to exit editing.

And so we have everything ready to restore the packages. The command below will compare what is already in our system with what we have in our file and install what is missing. If there is one in our package list that is incompatible with the current OpenWrt software, it will be automatically skipped.

```bash
apk update && apk add $(cat /root/my_installed_packages)
```

* * *

## Uploading files via SFTP

It would be nice to connect to our router so that we could easily restore individual files. This is especially useful when we set up our router from scratch and restore individual files from a backup.

For this purpose, I recommend the **SFTP** protocol (SSH File Transfer Protocol).

However, before we can connect, we need to install an SFTP server from the terminal.

```bash
apk update
apk add openssh-sftp-server
```

Then, using an application such as **Cyberduck** on macOS or **Filezilla**, we can establish a connection and transfer the files we need.

* * *

## Restoring settings from backup

The final step will be to restore our settings from a saved backup.

[![OpenWrt - System Backup - Flash Firmware - firmware restore](07-openwrt-system-backup-flash-firmware-restore.png "OpenWrt > System > Backup / Flash Firmware > firmware restore")](07-openwrt-system-backup-flash-firmware-restore.png)

We go again to **System > Backup / Flash firmware** and from the **restore** item we select **Upload archive**, where we indicate our file saved on our computer, then confirm everything when we are asked whether to apply the changes (**Apply backup?**) by clicking **Continue.**

We restart the router (if this does not happen after restoring the settings) and check if everything works.

This way, everything should work 99% of the time. There is always a chance that something won't work as it should. If anything, let me know in the comments.

* * *

Credits: [forum.openwrt.org/t/how-to-keep-packages-settings-after-upgrading/38998](https://forum.openwrt.org/t/how-to-keep-packages-settings-after-upgrading/38998)



---
## Setting domain for dynamic IP address (OpenWrt and DDNS)
- **URL:** https://dariusz.wieckiewicz.org/en/setting-domain-for-dynamic-ip-address-openwrt-ddns/
- **Date:** 2020-04-08
- **Tags:** Cloudflare, DDNS, NAT, NoIP, OpenWrt, domain for dynamic IP address

### Content

Today I am going to discuss a topic that causes problems for people who have an Internet connection without a permanent external IP address if we want to run a VPN server on our connection, as I described in the post [Installing a VPN server on a router with OpenWrt (WireGuard)](/en/installing-vpn-server-on-router-openwrt-wireguard/).

<!--more-->

The number of IP addresses in version 4 of this protocol is practically exhausted, so expecting a permanent IP address from our operator will become increasingly difficult, especially for home users.

Therefore, I would like to solve this problem by running DDNS on our router. This way we will assign it (our external IP address) a domain that will point to our router. When our IP address changes, it will be automatically refreshed to point to the current, new IP address.

For this purpose, I would like to use a domain that I own, whose DNS entries I manage through Cloudflare.

Personally, I didn't think Cloudflare had such an option, especially for free users. I searched, read, and decided to try. Of course, if you don't have a domain managed (DNS entries) by Cloudflare, there are also other sites that offer this type of service, such as [NoIP.com](https://www.noip.com/support/knowledgebase/how-to-configure-ddns-in-router/).

Before we start, it is worth noting that if we have an internet connection via 4G/LTE and the like, our router usually does not receive an external IP address. In this case, we are behind the so-called operator NAT or double NAT, which prevents us from properly redirecting incoming connections to our router. Although we will be able to set a domain, we will still not be able to connect to our VPN.

Not every operator uses this type of solution (almost every one in the UK), so it's worth checking. For this purpose, we can use an online solution, i.e. [Port Forwarding Tester](https://www.yougetsignal.com/tools/open-ports/). On our router, we need to open any port in the firewall rules and check whether this page sees it as open. If so, there is a good chance that everything will work.

Here we go...

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

---

## Installing the necessary packages

To do this, we can do it from the browser (**System** > **Software**), refreshing the package list (**Update lists**) and installing **luci-app-ddns**.

From the SSH terminal we can do this as follows:

```bash
apk update
apk add luci-app-ddns
```

By installing the **lubi-app-ddns** package, the basic package for DDNS support, i.e. **ddns-scripts**, will be automatically installed.

Next, we need to install the Cloudflare DDNS support package **ddns-scripts-cloudflare**. We do this from a browser in a similar way or from the terminal:

```bash
apk add ddns-scripts-cloudflare
```

In addition to Cloudflare, there are packages available for various services. You can find a list of those available [here](https://openwrt.org/docs/guide-user/services/ddns/client).

After successful installation and refreshing of our administration panel in the web browser, in the Services section we will see the dynamic DNS option, which we go to.

[![OpenWrt > Services > Dynamic DNS](openwrt-ddns-screen01.png)](openwrt-ddns-screen01.png)

Since currently all communication, including IP address refresh, is done via a secure HTTPS (SSL) connection, and the default built-in options on our router do not fully support this, you should also install the external **wget** or **curl** package. It may turn out that you already have **curl** in your system (the **ddns-scripts** package installs it by default), so there is no need to install **wget** (which is usually also available in the system).

* * *

## Set your domain in Cloudflare

At this point we will set up our domain for our router. Assuming we have a domain of **mydomain.something**, our router will use the subdomain of **vpn.mydomain.something**.

[We log in to our Cloudflare account](https://dash.cloudflare.com/login) and select our domain.

In the DNS tab we add a new record (+ Add Record).

[![Cloudflare > DNS Management > Add record](openwrt-ddns-screen02.png)](openwrt-ddns-screen02.png)

We choose the **A** type record, enter our subdomain name **vpn** and insert the IP address. Here we can set whatever we want.

I recommend **NOT** putting our current IP address, because we need to make sure that our application is working and after finishing the setup, the IP address will be given by our router. Then it will be correct.

We also click on the Cloudflare cloud icon and set **Proxied** to **DNS only**.

[![Cloudflare > DNS Management > Add record > A](openwrt-ddns-screen03.png)](openwrt-ddns-screen03.png)

When we **ping** our domain, we will see a response from the assigned IP address, not the Cloudflare IP address. For VPNs, I recommend leaving this in **DNS only** mode.

That's not all…

Before we proceed to configuring our router, we need data for communication and authentication between the router and Cloudflare. In this case, we do not use a username and password, but API. For this purpose, we will need our API key (**API keys**), which can be found in our profile settings (**My Profile**), in the API tokens section (**API Tokens**).

[![Cloudflare > My Profile](openwrt-ddns-screen04.png)](openwrt-ddns-screen04.png)

[![Cloudflare > API Tokens > Global API key](openwrt-ddns-screen05.png)](openwrt-ddns-screen05.png)

Then click on the **View** button next to **Global API key** (we will need to re-enter the Cloudflare password). In the next window we will get the key, which we copy and write down on the side, because we will need it later.

Back to our router…

* * *

## Configuration

We move on to configuration. For convenience, it will be done via a web browser (**Services > Dynamic DNS**).

[![OpenWrt > Dynamic DNS > Edit](openwrt-ddns-screen06.png)](openwrt-ddns-screen06.png)

At this stage we will focus on setting our IPv4 address, so we will start editing with **myddns_ipv4**.

Of course, Cloudflare also supports DNS over IPv6 and if our service provider also provides us with this address pool, it is worth adding the appropriate domain with a **AAAA** record.

Click the **edit** button next to **myddns_ipv4** or create a new configuration by entering its name and clicking the **add** button.

In my case I created **cloudflare_ipv4**.

In the first step, we go to the **DDNS Service provider** section and select **cloudflare.com-v4**. We may be asked to confirm the change (**Really change DDNS provider?**), which we confirm by clicking the **Change provider** button.

[![OpenWrt > Dynamic DNS > details for cloudflare_ipv4](openwrt-ddns-screen07.png)](openwrt-ddns-screen07.png)

Next, let's mark our service as **enabled**.

In **Lookup Hostname** we enter our domain **vpn.mydomain.something**

In the domain section (**Domain**), enter the same as above, except instead of the dot separating the main domain from the subdomain, enter the **@** symbol as in the email address, i.e. **vpn@mydomain.something**

In the **username** field we enter our Cloudflare email address.

In the **password** field we paste our API key (**Global API key**).

Setting the secure HTTPS connection (**Use HTTP Secure**), **for now** we leave it **not** enabled.

[![OpenWrt > Dynamic DNS > details for cloudflare_ipv4 - Basic Settings - Part 1](openwrt-ddns-screen08-1.png)](openwrt-ddns-screen08-1.png)

[![OpenWrt > Dynamic DNS > details for cloudflare_ipv4 - Basic Settings - Part 2](openwrt-ddns-screen08-2.png)](openwrt-ddns-screen08-2.png)

Moving on to the **advanced settings** of our configuration, we need to set how the program will check our external IP address and how the external IP address will be determined.

> There are several options here.
>
> If our router sees the external IP address from the interface (**Network > Interfaces**), then it is enough to select the interface option (**Interface**). In the case when the interface has a private IP address assigned, for example 192.168.8.2, then we need to use other options to specify the IP address. Below I will describe the method with the **URL** option.
>
> For those who use DDNS with mwan3 (see the post: [Adding a second internet connection to a router with OpenWrt](/en/adding-second-internet-connection-router-openwrt/)), I refer you to [another point of this article](#support-for-multiple-internet-connections-with-ddns-when-the-above-solution-does-not-work), where I describe another method of getting the external IP address using a script (**Script**).

In the example with the **URL** option we will use the website [**checkip.dyndns.com**](http://checkip.dyndns.com).

In the **IP address source** section select **URL** and in **URL to detect** enter: [http://checkip.dyndns.com](http://checkip.dyndns.com) (if it is not already entered by default).

> Make sure the address is **http** and not **https**.

In the **Event Network** section we select which network interface the communication will take place through to discover the external IP address. In my case, when I have two connections (**wan** and **4g** fallback), I selected **wan**.

[![OpenWrt > Dynamic DNS > details for cloudflare_ipv4 - Advances Settings](openwrt-ddns-screen09.png)](openwrt-ddns-screen09.png)

We leave the rest unchanged and click **Save & Apply**.

Now all you need to do is enable our service using the **Start** button.

[![OpenWrt > Dynamic DNS > Overview](openwrt-ddns-screen10.png)](openwrt-ddns-screen10.png)

When our service is up and running, we will receive information in the **Last update** position when the address was refreshed. We set the refresh rate in the **Timer Settings** section in our configuration settings (we adjust it as needed).

[![OpenWrt > Dynamic DNS > Overview - service started](openwrt-ddns-screen11.png)](openwrt-ddns-screen11.png)

To check if everything is working, we can execute the **ping** command

```bash
ping vpn.mydomain.something
```

Or log in to the Cloudflare admin panel and check what IP address is listed next to our record.

Now, when our address changes, our script will automatically check our external IP address. When it is the same as the one listed in Cloudflare settings, it will wait for the next attempt. When the IP address is different than the one in Cloudflare, it will be automatically refreshed.

But that's not all...

* * *

{{% ads-in-article %}}

## Communication via secure HTTP (SSL) connection

When setting up our configuration, I skipped the **Use HTTP Secure** section.

If we want our IP address refresh and all configuration between our router and Cloudflare to be secure/encrypted (highly recommended!), we still need to set up a few things.

First of all, we stop our service that we enabled above by clicking on the **PID: xxxx** button.

> When the service is stopped, I recommend going to Cloudflare and changing our current IP address in the DNS settings, again to some invented one, i.e. 123.123.123.123. Then, after correctly applying the steps below, we will be able to easily verify that everything works and the IP address is being refreshed.

In the next step we can install the **ca-certificates** package from the control panel or terminal, **however this does not always work** as it should, so we will use another method.

From the terminal we execute the following command:

```bash
mkdir -p /etc/ssl/certs
curl -k -o /etc/ssl/certs/ca-certificates.crt https://curl.se/ca/cacert.pem
```

W przypadku gdy na początku zdecydowaliśmy się na wykorzystanie **wget** zamiast **curl**, powyższa komenda powinna zostać zastąpiona następującą:

```bash
mkdir -p /etc/ssl/certs
wget  --no-check-certificate -O /etc/ssl/certs/ca-certificates.crt http://curl.se/ca/cacert.pem
```

> Curl is a good method for updating certificates. If you run it for the first time and don't have any certificates on your system, it may return an error. Therefore, it is worth using `wget` at the beginning and then relying on `curl`.

Then we check if everything works and we have no errors using the command:

```bash
curl -I -v https://google.com
```

If we have an error like:

```
* Error reading ca cert file /etc/ssl/certs/ca-certificates.crt - mbedTLS: (-0x2180) X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected
curl: (77) Error reading ca cert file /etc/ssl/certs/ca-certificates.crt - mbedTLS: (-0x2180) X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected
```

It is likely that the certificates were not correctly retrieved by **curl**. In this case, I recommend downloading them using the method with **wget**.

* * *

We proceed to configure our previously set **cloudflare_ipv4** configuration in **Dynamic DNS**.

Click the **edit** button.

In the **basic settings** select **Use HTTP Secure** and click **Save & Apply**.

We run our configuration using the **Start** button (as before).

We check if our IP address has refreshed as in the previous step. If we did everything correctly, everything should work and we should see our IP address.

**You can stop at this point.**

* * *

If you have set up an additional Internet connection, as per my  post [Adding a second internet connection to a router with OpenWrt](/en/adding-second-internet-connection-router-openwrt/), read on to learn how to correctly set the rules so that the IP refresh only takes place via the connection we have designated for this purpose.

* * *

## Support multiple internet connections with DDNS

If you have configured your router to support two (or more) internet connections, especially in a mode where the primary fails over (4G in my case) and is automatically started, you may not want the **DDNS** domain assigned to the IP address from the second connection, especially if the second one does not have a direct, external IP address.

In this case we need to slightly modify our **Policies** and **Rules** in **mwan3**.

First we add a **Policy** policy that will only use the main connection. In my case I named it **wan_only** and set **Members used** to only **wan_m1_w1**.

[![OpenWrt DDNS - supplement - MWAN Policies](openwrt-ddns-screen-supp1.png)](openwrt-ddns-screen-supp1.png)

Next in **Rules** I added a rule called **ddns**.

In its settings I only specified **Destination address** to **checkip.dyndns.com** and **policy assigned** to **wan_only.**

All that's left is to move the **ddns** rule to the very top of the list so that it's used first.

[![OpenWrt DDNS - supplement - MWAN Rules](openwrt-ddns-screen-supp2.png)](openwrt-ddns-screen-supp2.png)

* * *

## Support for multiple internet connections with DDNS (when the above solution does not work)

In mwan3 version on OpenWrt 22.03 and newer, it is not possible to set the domain address in the rule (**Rule**) (here **checkip.dyndns.com**).

In this case the configuration returns a problem (**Expecting: valid IP address or prefix**).

Therefore, we cannot use the above method, but there is a solution.

Assuming that our connection has a permanent private IP address (in my case 192.168.8.2), by setting an appropriate rule (**Rule**) in mwan3 and preparing a simple script that will read our external IP address through a given interface (in my case 4G), we configure **ddns** appropriately to bypass these restrictions.

> In the example with the **Script** option we will use the website [**icanhazip.com**](http://icanhazip.com).

First, let's check if we can correctly read the IP address from the terminal with the following command:

```bash
curl --interface 192.168.8.2 'http://icanhazip.com'
```

In response, we should read our IP address, just as if we had visited this site directly from a browser using the above link.

If everything works, it's time to prepare our script, which we will call **getIP_4G** and save directly to the **/root** folder.

```bash
printf "curl --interface 192.168.8.2 'http://icanhazip.com'" > getIP_4G
```

To make it run, we add execution permissions and run it for verification.

```bash
chmod +x getIP_4G
./getIP_4G
```

Now we are ready to configure the rest on the router side from a web browser.

First, in the mwan3 settings (**Network > MultiWAN Manager**) we add a rule (**Rule**), in which the address from which we will communicate is the private address of our interface (in my case 192.168.8.2). We leave the rest blank by default, and as a policy we select communication only through our target interface (in my case **4Gbackup_only**).

[![MultiWan mwan3 Rule 4G interface](MultiWAN_mwan3_Rule_4G_interface.png)](MultiWAN_mwan3_Rule_4G_interface.png)

Now we move on to configuring our domain (**Services > Dynamic DNS**).

When editing (**Edit**) our configuration, we go to the **advances settings** tab and change the source of our IP address (**IP address source**) from the previously selected **URL** to a script (**Script**).

In the **Script** field below we enter the location of our script that we created earlier.

```
/root/getIP_4G
```

[![DDNS > Advances Settings > Script > getIP_4G](ddns_advances_settings_script_getIP_4G.png)](ddns_advances_settings_script_getIP_4G.png)

We save the changes (**Save**) and confirm everything with the **Save & Apply** button.

If our configuration was already running, then we click the **Reload** button to reload it, or the **Start** button to run it.

And so we should get our external IP address using the **Script** method.

To check this, by clicking the **Edit** button, going to the **Log File Viewer** tab and reading the log (by clicking **Read / Reread log file**) we should see something like this:

```
 104831       : #> /root/getIP_4G >/var/run/ddns/cf_dynamic.dat 2>/var/run/ddns/cf_dynamic.err
 104832       : Local IP '188.30.29.121' detected via script '/root/getIP_4G'
 104832       : Update needed - L: '188.30.29.121' <> R: '123.123.123.123'
 104832       : parsing script '/usr/lib/ddns/update_cloudflare_com_v4.sh'
...
 104835  info : Update successful - IP '188.30.29.121' send
 104835       : Waiting 600 seconds (Check Interval)
```

* * *

## Automatic certificate update

Just like OpenWrt software, certificates also need to be refreshed from time to time. Therefore, it is worth adding a command to the schedule (**Scheduled Tasks**) that will do it for us from time to time (once a month).

Going to **System > Scheduled Tasks** we add the following line:

For **curl**

```
00 3 1 * * /usr/bin/curl -k --silent --remote-name --time-cond /etc/ssl/certs/ca-certificates.crt -o /etc/ssl/certs/ca-certificates.crt https://curl.se/ca/cacert.pem >/dev/null 2>&1
```

For **wget**

```
00 3 1 * * /usr/bin/wget -q --timestamping --no-check-certificate -O /etc/ssl/certs/ca-certificates.crt http://curl.se/ca/cacert.pem >/dev/null 2>&1
```

This will cause **curl**/**wget** to compare file to the file being downloaded, and if the file being downloaded is newer, it will be downloaded and updated. If the file is the same, the download will be ignored until the next time.

The OpenWrt built-in **wget** does not have an option to check the time (_--timestamping_) for files, to do this you need to install the latest version:

```bash
apk update
apk add wget
```

The whole thing will go live **on the first day of every month** at **3am**.

* * *

I hope the above post was useful. I encourage you to add a comment if you have any problems.

Best regards.

* * *

_Credits_

- [https://openwrt.org/docs/guide-user/services/ddns/client](https://openwrt.org/docs/guide-user/services/ddns/client)  
- [https://www.alphairo.com/2019/09/18/openwrt-18-06-4-ddns-for-cloudflare/](https://www.alphairo.com/2019/09/18/openwrt-18-06-4-ddns-for-cloudflare/)  
- [https://curl.se/docs/caextract.html](https://curl.se/docs/caextract.html)



---
## Adding a second internet connection to a router with OpenWrt
- **URL:** https://dariusz.wieckiewicz.org/en/adding-second-internet-connection-router-openwrt/
- **Date:** 2020-03-21
- **Tags:** 4g, ASUS RT-AC57U, luci-app-mwan3, mwan3, OpenWrt, SMARTY, ZTE MF823

### Content

Depending on where we use our router, we may be in a situation where we need to have a backup plan in case our primary internet connection goes down.

<!--more-->

Personally, I was in a situation where my main internet connection became unreliable. Despite the fast speed, its lack of reliability drove me crazy (it was Virgin Media at the time of the pandemic), so I thought about introducing an additional backup connection. This additional connection is via a 4G modem connected via a USB port to my router and is based on the principle that when the primary connection stops working, all traffic is redirected to the emergency connection automatically.

For this purpose, I will use my **ASUS RT-AC57U** router (at the time of updating this post, I am using a GL-MT6000 Flint 2) with OpenWrt software and a **ZTE MF823** USB modem (originally from BT, but with modified firmware and fully unlocked).

What's more, since this modem has the ability to connect external antennas, I've also equipped it with them to boost the signal a bit. The whole thing will use the operator [SMARTY](https://smarty.co.uk/), which is based on the **3** network infrastructure in the UK.

And, although the 3 network and its coverage are not the best (never have been), if it works in my location and provides unlimited data for a decent price, then it is not so bad.

**So here we go…**

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

* * *

## Connecting a 4G modem via USB to our router

First, we need to install the necessary packages. We can do this using the graphical interface from a web browser (**System > Software**) or from an SSH terminal using the following command:

```bash
apk update
apk add kmod-usb-net-rndis kmod-usb-net kmod-usb2 usb-modeswitch kmod-usb-net-cdc-ether
```

Then we insert the activated SIM card into our modem and connect the modem to the USB port of our router.

Using the **dmesg** command we check if the system has detected a new device, in my case:

```
[1383.238310] usb 1-2: new high-speed USB device number 2 using xhci-mtk
[1388.676158] usb 1-2: USB disconnect, device number 2
[1389.358290] usb 1-2: new high-speed USB device number 3 using xhci-mtk
[1389.586108] rndis_host 1-2:1.0 usb0: register 'rndis_host' at usb-1e1c0000.xhci-2, RNDIS device
```

From a web browser, go to **Network > Interfaces** on our router and click **Add new interface** button.

In the case of my modem, which is detected as a network card via USB, I enter the name **4G**, select the **protocol**, **DHCP client** and the **interface** as **usb0**.

> Some modems may show up as **eth2** network card instead of **usb0**.

![OpenWrt Add Interface](4g-screen01-openwrt-add-interface.png)

In the next step we will leave everything default and focus only on the **Firewall Settings**, where we will add our **wan**, **wan6**. Then we save the changes and in the next step click **Save & Apply**.

![OpenWrt Interfaces Firewall Settings](4g-screen02-openwrt-interfaces-firewall-settings.png)

If we did everything correctly, our connection should be active.

![OpenWrt Network Interfaces 4G](4g-screen03-openwrt-network-interfaces-4g.png)

At this stage, you can set in the firewall rules which connections, ports, IP addresses should use this and not another Internet connection (interface).

In my case, as I mentioned at the beginning, I want to set up the ability to use two connections, of which the **4G** one will be activated when the primary one drops out.

Before we go any further, let's check if our connection is working:

```bash
ping -c 1 -I usb0 1.1.1.1
```

And we move on...

* * *

## Using multiple internet connections

For this purpose we need the **mwan3** package and an application that adds the ability to manage via a web browser **luci-app-mwan3**.

As above, we can install them from **System > Software** or from SSH terminal:

```bash
apk update
apk add mwan3 luci-app-mwan3
```

The basic function of **mwan3** is not only the ability to use both internet connections in parallel (**load balancing**), but also to monitor each of the connections. When one of the connections goes down, the internet traffic is redirected to the one that is working, and this is the option that it needs the most.

After installing the above packages we will receive an additional option in the **Network > Load Balancing** (or **MultiWAN Manager**) menu.

![OpenWrt Network Load Balancing (MultiWAN Manager)](4g-screen04-openwrt-network-load-balancing.png)

First we need to configure our interfaces (**Interfaces**) by adding **4G** (here we use the name set in **Network > Interfaces**).

![OpenWrt Load Balancing (MultiWAN Manager) Interfaces](4g-screen05-openwrt-load-balancing-interfaces.png)

After adding **4G**, in the new interface tab (**Interface**), we mark our interface as enabled (**Enabled**) and in the **Tracking hostname or IP address** fields we enter the DNS addresses 1.1.1.1 and 1.0.0.1. Thanks to this, our router will check if our interface is working. When it is not working, traffic will not be directed to it.

![OpenWrt Load Balancing (MultiWAN Manager) Interfaces 4G](4g-screen06-openwrt-load-balancing-interfaces-4g.png)

It is also worth editing our **wan** and **wan6** interfaces, which by default have Google and Cloudflare servers set to check activity.

![OpenWrt Load Balancing (MultiWAN Manager) Interfaces](4g-screen07-openwrt-load-balancing-interfaces-wan.png)

In case of **wan** we set

```
1.1.1.1
8.8.8.8
1.0.0.1
8.8.4.4
```

In case of **wan6** (optional) we set

```
2606:4700:4700::1111
2001:4860:4860::8888
2606:4700:4700::1001
2001:4860:4860::8844
```

In addition to the sections described above, the options also include:

**Tracking method** — The way to determine if an interface is up or down. We leave it at **ping** by default.

**Tracking reliability** — specifies how many addresses defined in the **Tracking hostname or IP address** section must respond positively for the interface to be considered up. We leave it at **1** by default.

**Ping count** — specifies how many **ping** requests to send in one test. We leave it at **1**.

If the response to **ping** takes a very long time, after what time it should be interrupted - this is determined by **Ping timeout**. On the other hand, how often **ping** should be repeated is determined by **Ping interval**. In the case when **ping** is successful, after what time the query should be repeated is determined by **Failure interval**. In my case, I set these three options to **2/5/1** for **wan** and **4G**, respectively. In the case when the interface is marked as down (**Offline**), after what time the attempt to check activity and restore the state if it turns out that the interface is up is determined by **Recovery interval** - in my case I set **3** seconds.

There are two more options left to consider, namely **Interface down** and **Interface up**.

**Interface down** will determine after how many errors when performing **ping** the interface is considered down (**Offline**), similarly **Interface up** after how many correct answers **ping** will be considered up. In my case, since **wan** is considered more stable (sic!), and **4G**, even when it works, can report an error, even when everything is working, I set 4/6 (**wan**) and 6/8. 

In addition, we still need to specify which interface is primary and which is secondary (emergency). We do this using the **Metrics** option in the primary interface settings. In my case, I set **wan** to **10** and **4G** to **50**. We make this change from the **Network > Interfaces** level by editing the settings of the individual interfaces.

Confirm everything by clicking **Save & Apply**.

* * *

As you probably noticed, **Load Balancing** (**MultiWAN Manager**) also contains **Members**, **Policies** and **Rules** tabs, which we need to set appropriately, depending on what we want to achieve.

### Members

Here we set our interfaces with an additional division into which one is more important than the other (similar to what we set earlier). So in my case, when I want to achieve automatic use of **4G** when my primary connection goes down, I added two entries:

![OpenWrt Load Balancing (MultiWAN Manager) Members](4g-screen08-openwrt-load-balancing-members.png)

### Policies

Here we combine our above settings the way they are supposed to work - i.e. **wan** first and in case of problems **4G**.

![OpenWrt Load Balancing (MultiWAN Manager) Policies](4g-screen09-openwrt-load-balancing-policies.png)

{{% ads-in-article %}}

### Rules

As the name says it all, here we set the rules for the transfer. Which transfer should be forwarded through which interface. By default we get defined rules for encrypted www traffic (**https**) and everything else.

In my case I will set one **default** rule.

In order not to describe everything too much, we will focus on the **protocol**, which we will set to all (**all**); **Policy assigned** we set to **wan_4G**.

![OpenWrt Load Balancing (MultiWAN Manager) rules](4g-screen10-openwrt-load-balancing-rules.png)

For all options to be entered correctly, we restart our router or execute the following commands in the terminal:

```bash
/usr/sbin/mwan3 restart
/etc/init.d/network restart
/etc/init.d/firewall restart
```

If we want to see how everything is working, check **Status > Load Balancing** (**MultiWAN Manager**).

![OpenWrt Load balancing (MultiWAN Manager) status interface](4g-screen11-openwrt-load-balancing-status-interface.png)

![OpenWrt load balancing (MultiWAN Manager) status detail](4g-screen12-openwrt-load-balancing-status-detail.png)

* * *

The above configuration does not exhaust the possibilities of configuring **mwan3**. We can also set the **wan** and **4G** connections to be used in parallel, or redirect (using the appropriate **Rules** rule) individual network traffic through a specialized interface. There are many applications, and I focused only on my goal.

Please remember that when we decide to connect dynamic DNS (domain to our variable IP) to specify the appropriate rule so that the IP address update takes place only through the interface we use for this purpose.

If you are interested in other examples, I encourage you to visit the entry [braian87b/mwan3-notes.md](https://gist.github.com/braian87b/97a186b2e11b5aa438d8fd17de0eab20) and the detailed configuration example [braian87b/mwan-config.sh](https://gist.github.com/braian87b/.20a920e7aabdd495afc861c2a22c).

* * *

Credits:  
**[Failover to LTE using mwan3](https://doc.turris.cz/doc/en/howto/multiwan)**  
**[Connect 4G USB modem to WRT2200](https://forum.openwrt.org/t/connect-4g-usb-modem-to-wrt2200/43766)**


---
## Securing an OpenWrt Router
- **URL:** https://dariusz.wieckiewicz.org/en/securing-openwrt-router/
- **Date:** 2020-03-08
- **Tags:** Hardware, https, OpenWrt, opkg, passwd, port 22, root, ssh, uhttpd, UPnP

### Content

So you've decided to change the firmware on your router from the one provided by your hardware manufacturer to the more open and secure OpenWrt firmware. **Congratulations!**

<!--more-->

However, just because you have decided to increase the security of your device does not mean that you can rest on your laurels. Like any software, OpenWrt is also updated from time to time, mainly when security holes and problems are discovered that may cause unstable operation of our device.

Like any network device, it requires some initial setup to improve its security.

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

## Root password

Our router uses the account with the highest privileges in the system by default - **root**. Its protection should be a priority for us. When logging in for the first time to the newly installed OpenWrt software, we will be asked to change it, but if we ignored it or set a password like **admin**, let's change it to a unique one, known only to us, as soon as possible. A hacker who has the opportunity to break into your network will first check the most popular and default passwords used on routers.

To change the user password, go to **System > Administration**, where, in the first tab **Router Password** we can set a secure password.

We can also change the password by connecting to our router via SSH and executing the command:

```bash
passwd
```

[![OpenWrt System Administration router password](openwrt-system-administration-router-password.png)](openwrt-system-administration-router-password.png)

* * *

## SSH

While in **System > Administration** it is also worth taking a look at the **SSH Access** tab.

By default, our router listens on port **22** and all available interfaces — including the one used to access the Internet. I don't have to say that having port **22** open, accessible from the Internet, is not a sensible solution. Although the default Firewall rules will protect us from the possibility of connecting to SSH our router from the Internet, it is worth changing the default settings.

And so:
**Interface** we change to **LAN** (our local network)

And:
Change the **Port** (on which the router will listen) to e.g. **9922** or any other port of your choice.

[![openwrt system administration ssh access](openwrt-system-administration-ssh-access.png)](openwrt-system-administration-ssh-access.png)

**Save and Apply** changes.

* * *

## Administration panel (https)

Access to our router settings is done in a user-friendly graphical interface from a web browser. Just go to the page - address of our router (e.g. **192.168.1.1**) and log in to our **root** account.

It's all well and good, provided that no one on the network is listening to what we enter in the browser, especially since when we visit our router's administration panel, the connection is made via unencrypted HTTP, so our password that we enter is also sent in unencrypted form. All you need is WireShark and you can easily find out what we are entering.

Therefore, it is worth establishing a connection to our router via an HTTPS encrypted connection.

Go to **System > Administration**, where, in the **HTTP(S) Access** tab, select **Redirect to HTTPS**.

[![OpenWrt System Administration HTTP(S) Access](openwrt-system-administration-https-access.png)](openwrt-system-administration-https-access.png)

If your router does not have this tab, you need to install the appropriate package.

To do this, in **System > Software** we need to install the **luci-ssl** application (if we do not already have it in our system), or from the terminal:

```bash
apk update
apk add luci-ssl
```

If we perform our installation from the terminal, it is worth restarting our access via a web browser after the installation, which is done using the **uhttpd** package.

```bash
/etc/init.d/uhttpd restart
```

The first time you restart, a secure certificate for access via HTTPS will be generated.

Of course, the certificate that will be generated is not issued by any trusted institution, but signed by our router. For local purposes, this is not a problem at all, but when connecting to our router via HTTPS, we keep a warning about an untrusted certificate.

In the case of **Safari** we can click **Show Details** and click the link **visit this website.**

[![Safari this connection is not private](safari-this-connection-is-not-private.png)](safari-this-connection-is-not-private.png)

With **Edge (Chromium)** and **Chrome** it's not that easy, as these browsers won't let us proceed any further, even if we enter the **advanced options**, under which we should see a link allowing us to go to the page anyway.

[![Edge Chromium your connection isn't private](edge-chromium-your-connection-isnt-private.png)](edge-chromium-your-connection-isnt-private.png)
    
[![Edge Chromium Your connection isn't private advances](edge-chromium-your-connection-isnt-private-advanced.png)](edge-chromium-your-connection-isnt-private-advanced.png)

To do this, we can use an unusual method. After going to the page that returns a certificate problem, we can write (we won't see what we're typing) in the browser window the word **thisisunsafe**. After a while, we'll see that our page will refresh and we'll be able to continue to our panel.

For **Firefox**, simply click the **Advanced** button and at the bottom of the page select the button stating that **Accept the Risk and Continue**.

[![Firefox warning potential security risk ahead](firefox-warning-potential-security-risk-ahead.png)](firefox-warning-potential-security-risk-ahead.png)
    
[![Firefox warning potential security risk ahead advanced](firefox-warning-potential-security-risk-ahead-advanced.png)](firefox-warning-potential-security-risk-ahead-advanced.png)

A small inconvenience, but it also increases security when entering the password into our router.

* * *

## Administration Panel (port)

In addition to introducing an encrypted https connection to our administration panel via a web browser (which is not very convenient due to the issue with certificates), we can also change the port on which our panel listens.

By default, this is port 80 for unencrypted HTTP connections or 443 for encrypted HTTPS.

To change these ports, we can install the **luci-app-uhttpd** package

```bash
apk update
apk add luci-app-uhttpd
```

Thanks to this, in the **Services** options we will receive an additional menu for managing the uHTTPd service.

[![OpenWrt Services uHTTPd](openwrt-services-uhttpd.png)](openwrt-services-uhttpd.png)
    
[![OpenWrt Services uHTTPd general settings](openwrt-services-uhttpd-general-settings.png)](openwrt-services-uhttpd-general-settings.png)

In **HTTP listeners** (and similarly for HTTPS) you need to add a new port through which we will connect to our administration panel. For example, for HTTPS, if we want to change the port from 443 to 8443, we add (and remove the rest) the following lines:

```
0.0.0.0:8443
[::]:8443
```

We confirm everything by clicking the **Save and Apply** button.

If we did everything correctly, we go to our panel using the new address:

```
http://192.168.1.1:8443
```

{{% ads-in-article %}}

* * *

## Software (Packages)

> Please be advised that the [official stance](https://openwrt.org/docs/guide-user/additional-software/apk#updating_packages) of the OpenWrt maintainers is: "Do not use `apk upgrade` to blindly mass-update your packages! Doing so will sooner or later brick your device." **I tend to disagree with that.** I have been doing it successfully for years without any issues; however, that does not mean you will not encounter them. The decision is yours.

Apart from the fact that we have changed the manufacturer's software on our router to a more secure one, it does not mean that everything should remain untouched for ages. We need to make sure that we constantly update the OpenWrt software and packages that we have installed on the router.

While the OpenWrt main firmware itself is not released very often, other software (firmware packages) used within our router are released with updates several times a week.

Therefore, it is worth taking care to update them regularly. To do this, go to **System > Software**, refresh the list with the **Update list** button, and then in the **Updates** tab, click on each software to update it.

[![OpenWrt System software](openwrt-system-software.png)](openwrt-system-software.png)

The above method is somewhat time-consuming. We can also do this from an SSH terminal using a single command. Using this command, the router will retrieve information about current software versions and, based on what's "outdated" on our router, automatically update it:

```bash
apk update; apk upgrade
```

And that would be all.

**Best regards.**


---
## Installing a VPN server on a router with OpenWrt (WireGuard)
- **URL:** https://dariusz.wieckiewicz.org/en/installing-vpn-server-on-router-openwrt-wireguard/
- **Date:** 2020-03-07
- **Tags:** Hardware, ASUS RT-AC57U, OpenVPN, OpenWrt, peer, Private Key, Public Key, tunel IPv6, IPv6, VPN, WireGuard, WireGuard OpenWrt

### Content

If you have a router with OpenWrt, you have probably thought more than once about how to set up a VPN server on it so that you can connect to the network from outside your home or office and have access to local data, such as a network drive or printer.

<!--more-->

In the case of OpenWrt, if you start looking for information about VPNs, you will immediately come across details about **OpenVPN**.

Initially, I thought about creating a post about **installing OpenVPN on a router with OpenWrt**; however, the further into the forest, the more trees.

The configuration can start simple. You can even add an interface from the browser; however, everything is far from simple and clear. Being halfway through my post, I realised that further creation of it would introduce more complications than I initially assumed. At this point, I remembered **WireGuard**.

Both **OpenVPN** and **WireGuard** are not available by default on operating systems (Windows, macOS, as well as Android or iOS). In both cases, you must use a dedicated application to connect.

**WireGuard** won over **OpenVPN** for me because it is much easier to set up and manage. It is also much faster, offers a higher level of security, and, in the case of mobile devices, does not drain our battery like OpenVPN does.

While in the case of OpenVPN, you had to execute a series of commands related to setting up the server from the SSH terminal, in the case of WireGuard, we can set up our server with minimal use of the terminal (or even without it) and do the rest via a web browser. All in a user-friendly way.

**So let's get started...**

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

## Installing WireGuard on OpenWrt (Server)

First, we need to install a few packages for WireGuard itself and those that add the ability to manage it from a web browser.

### From Web Browser

Go to **System** > **Software** and, in the *Actions:* section, click on the green button **Update lists...**.

[![OpenWrt - WireGuard Installation. System > Software](openwrt_system_software.png)](openwrt_system_software.png)

Search for the following packages and click the **install** button next to them.

```
luci-proto-wireguard
kmod-wireguard
wireguard-tools
```

### From Terminal

Run the following commands:

```bash
apk update
apk add luci-proto-wireguard kmod-wireguard wireguard-tools
```

---

Since WireGuard uses kernel-level elements for its functionality, we need to restart our router at this stage to ensure everything loads correctly.

Restart your router.

## Restarting router

### From Web Browser

Go to **System** > **Reboot** and click the **Perform reboot** button.

### From Terminal

Type command:

```bash
reboot
```

> **Do not proceed if you have not restarted your router after installing the above packages.**

{{% ads-in-article %}}

## Setting up WireGuard Server Interface on OpenWrt

Let's set up our **Network** > **Interfaces** by clicking the **Add new interface** button.

[![OpenWrt > Setting up WireGuard Interface. Add new interface](openwrt_network_interfaces_add_new_interface.png)](openwrt_network_interfaces_add_new_interface.png)

Specify a **name** for your interface (like **wg0**) and select the *protocol* **WireGuard VPN**.

[![OpenWrt > Add new interface. Name wg0 and Protocol WireGuard VPN](openwrt_add_new_interface_wg0_wireguard_vpn.png)](openwrt_add_new_interface_wg0_wireguard_vpn.png)

Confirm by clicking the green **Create interface** button.

---

In the next step, you'll see the *Private key* and *Public key* for our server highlighted in red, indicating they're missing. These keys are necessary to establish a connection with clients.

You can add them in two ways.

### From Web Browser

Simply click the **Generate new key pair** button.

[![OpenWrt Wireguard interface. Generate new key pair](openwrt_wireguard_interface_generate_new_key_pair.png)](openwrt_wireguard_interface_generate_new_key_pair.png)

Or use the terminal.

### From Terminal

First, create a folder to store your settings.

```bash
mkdir -p /etc/wireguard
```

To generate the *Private key* and *Public key*, run the following command.

```bash
wg genkey | tee /etc/wireguard/server-privatekey | wg pubkey > /etc/wireguard/server-publickey
```

Read your generated keys and paste them into the corresponding fields in the web interface.

To read the *Private key*, use the command:

```
tail /etc/wireguard/server-privatekey
```

To read the *Public key*, use the command:

```
tail /etc/wireguard/server-publickey
```

---

Next, set the **Listen Port**, which WireGuard will use to listen for incoming client connections.

- **Listen Port**: 1234

Next, enter the local IP address of your server. You don't need to worry about this address conflicting with your local network. Later, we'll configure it to connect to local addresses, which, by default (in an OpenWrt environment), will be in the range of **192.168.1.x**.

- **IP Addresses**:
  - 10.0.0.1/24
  - fd42:42:42:1::1/64

> Here, I set the local IPv4 and local IPv6 addresses for our server.

Next, navigate to the **Firewall Settings** tab.

From the **Create / Assign firewall-zone** item, select your **LAN** network. This allows you to see and connect to devices on the local network.

[![Adding WireGuard to OpenWrt LAN rule](openwrt_wireguard_wg0_firewall_settings.png)](openwrt_wireguard_wg0_firewall_settings.png)

At this stage, click the **Save** button, then **Save & Apply**.

Your server interface is **ready and running**.

Before anyone can connect to it, we need to add specific firewall rules.

{{% ads-in-article %}}

## Adding Firewall Rules for WireGuard Server

To connect to our router via port **1234/udp**, we need to permit it at the **firewall** level.

There are two ways to accomplish this.

### From Web Browser

Go to **Network** > **Firewall** and select the **Traffic Rules** tab.

Scroll to the bottom of the rules and press the green **Add** button. Add the rule as shown in the image below.

[![OpenWrt Traffic Rule](openwrt_wireguard_inbound_firewall_traffic_rule.png)](openwrt_wireguard_inbound_firewall_traffic_rule.png)

Once done, press the **Save** button, then **Save & Apply**.

### From Terminal

Execute the following command in the terminal to add a firewall rule.

```bash
uci add firewall rule
uci set firewall.@rule[-1].src="*"
uci set firewall.@rule[-1].target="ACCEPT"
uci set firewall.@rule[-1].proto="udp"
uci set firewall.@rule[-1].dest_port="1234"
uci set firewall.@rule[-1].name="Allow-Wireguard-Inbound"
uci commit firewall
```

Follow by restarting the firewall using the command below:

```bash
/etc/init.d/firewall restart
```

{{% ads-in-article %}}

## Setting WireGuard Users - Peers

Now we are ready to add users who will be using the service.

Head to **Network** > **Interfaces** and click the **Edit** button.

[![OpenWrt Network Interfaces WireGuard](openwrt_wireguard_interface_wg0.png)](openwrt_wireguard_interface_wg0.png)

From there, go to the **Peers** tab.

[![OpenWrt WireGuard Interface Peers Tab](openwrt_interfaces_wg0_peers.png)](openwrt_interfaces_wg0_peers.png)

Click the green **Add peer** button.

Before filling in the fields for the first user, ensure you have their *Public key* and *Private key*.

There are two ways to add them.

### From Web Browser

Simply click the **Generate new key pair** button.

[![OpenWrt WireGuard Interface Generate Key Pair](openwrt_interfaces_wg0_edit_peer.png)](openwrt_interfaces_wg0_edit_peer.png)

Or use the terminal.

### From Terminal

To create the *Private key* and *Public key* for the first user, run the following command.

```bash
wg genkey | tee /etc/wireguard/user1-privatekey | wg pubkey > /etc/wireguard/user1-publickey
```

Now, read your keys and paste them into your web interface.

```
tail /etc/wireguard/user1-publickey
tail /etc/wireguard/user1-privatekey
```

---

In the **Description** field, specify your username.

Go to the **Allowed IPs** section and enter a static address that will be used by the client, similar to the server's IP address (10.0.0.1/24, fd42:42:42:1::1/64).

- 10.0.0.2/32
- fd42:42:42:1::2/128

> Notice that the user's IP mark ends with /32 (for IPv4) and /128 (for IPv6). Each user is assigned a single IP address, meaning a single credential can only be used to connect one device at a time.

Let's check **Route Allowed IPs**.

> If you have more than one internet connection set up using **mwan3** (as described in the post: [Adding a second internet connection to a router with OpenWrt](/en/adding-second-internet-connection-router-openwrt/)), leave **Route Allowed IPs** unchecked.

In **Persistent Keep Alive**, enter the value **25**, which is the recommended value if this device is behind a NAT.

Press the **Save** button to add the peer configuration.

[![OpenWrt > Wireguard interface - Peers tab - One Peer](openwrt_interfaces_wg0_one_peer.png)](openwrt_interfaces_wg0_one_peer.png)

---

In the same way, you can add another user (peer) to your configuration.

> The next user will have new *keys* generated and allowed IPs in the next order, i.e., `10.0.0.3/32` and `fd42:42:42:1::3/128`.

Once all peers have been added, confirm everything with the **Save** button. In the interfaces section, click **Save & Apply**.

At this stage, you **must** also restart the WireGuard interface to refresh the configurations and peers that have just been added.

[![Openwrt > Interfaces. Restart wg0 interface after amending configuration](openwrt_interfaces_restart_wg0.png)](openwrt_interfaces_restart_wg0.png)

In this way, we have a WireGuard-based VPN server running.

## WireGuard Status

When your WireGuard server is running, you can check its status and manage users and their connection status by going to **Status** > **WireGuard** in the web interface.

On this page, you will see the server's **public key** and the **port (Listen Port)** on which the service is running.

[![OpenWrt > Status > WireGuard with one Peer](openwrt_wireguard_status_with_one_peer.png)](openwrt_wireguard_status_with_one_peer.png)

Now we are ready to set up our client devices and verify that everything is working.

{{% ads-in-article %}}

## Setting up WireGuard User Devices

It's time to set up user **(peer)** devices that will connect to our server.

I'll use the iPhone (iOS) app as an example. The setup is analogous on other operating systems.

Download the **WireGuard** application from the **[App Store](https://apps.apple.com/gb/app/wireguard/id1441195209)**.

For Android devices, download it from the **[Play Store](https://play.google.com/store/apps/details?id=com.wireguard.android)**.

After starting the application, click on the **Add a tunnel** button.

[![Adding a client (peer) in the WireGuard app on iPhone (iOS)](openwrt_wireguard_ios_add_configuration.png)

### Starting from Scratch

Since we are starting from scratch, select **Create from scratch**.

{{% gallery %}}
[![Adding a client (peer) in the WireGuard app on iPhone (iOS) - starting from scratch](openwrt_wireguard_ios_add_configuration_from_scratch.png)](openwrt_wireguard_ios_add_configuration_from_scratch.png)
[![Adding a client (peer) in the WireGuard application on iPhone (iOS) - filling in the new configuration fields](openwrt_wireguard_ios_new_configuration.png)](openwrt_wireguard_ios_new_configuration.png)
{{% /gallery %}}

Now, we begin entering our configuration, starting with:

**Name**: User1

**Private key:** {paste}

This is our _user1-privatekey_ generated at the beginning, either through the web browser or terminal.

> To read the key generated through the web browser, navigate to **Network** > **Interfaces**, click **edit** next to your WireGuard interface (**wg0**), go to the **Peers** tab, click **edit** next to User1, and copy the public key from there.

> To read the key generated through the **terminal**, use the following command on your router: `tail /etc/wireguard/user1-publickey`.

You'll notice that the **Public key** field is automatically pre-filled.

**Addresses:** 10.0.0.2/32, fd42:42:42:1::2/128

> Enter the client IP address here, as configured on the server side.

**DNS servers:** 192.168.1.1

> Where 192.168.1.1 is the local IP address of our OpenWrt router, unless it has been changed.

> If you prefer your device to send DNS requests via your internet connection instead of through your router, you can skip this option.

---

Now, we need to add information about the server we'll be connecting to.

Click **Add peer** to input the server details.

In the **Public key** field, enter the server's key.

> To read the key generated through the web browser, navigate to **Network** > **Interfaces**, click **edit** next to your WireGuard interface (**wg0**), go to **General Settings**, and copy the public key from there.

> To read the key generated through the **terminal**, use the following command on your router: `cat /etc/wireguard/server-publickey`.

**Endpoint:** [externalIP]:[port]

If our router has a permanent, external IP address, we enter it here along with the previously set port for the connection. For example: `123.34.45.56:1234`, where `123.34.45.56` is the IP address and `1234` is the port.

In the **Allowed IPs** field, set: `0.0.0.0/0, ::/0`.

This configuration allows visibility of devices on the local network.

Set **Persistent keepalive** to `25`.

Afterward, **save** the configuration.

At this point, your phone will prompt you to add the VPN configuration to the settings, which you should **allow**.

If everything is configured correctly, you only need to establish the connection, and it should work. To verify, go to the **Settings** of the WireGuard app on your device and click **View log** to check if everything operates smoothly.

[![Checking the status of our connection in the Logs of the WireGuard application on iPhone (iOS)](openwrt_wireguard_ios_logs.png)](openwrt_wireguard_ios_logs.png)

Additionally, open your browser, search for **myip** on Google, and verify if it matches your local network's IP address.

---

On our router side, from the browser, we can also see in **WireGuard Status** that our connection is working and data is traveling between devices.

[![Visible client connection on WireGuard server side on OpenWrt router](openwrt_wireguard_status_connected_peer.png)](openwrt_wireguard_status_connected_peer.png)

If something is not working, check whether the **Firewall** on the router is configured correctly (see earlier) and verify that the correct keys have been entered everywhere.

> To avoid re-entering everything from scratch each time we set up our device to connect to WireGuard, save the configuration to a file from the **Settings** level. When reconfiguring, you can import these settings.

---

However, not every app allows setting everything up from scratch. For [WireGuard on macOS](https://apps.apple.com/us/app/wireguard/id1451685025?mt=12), the options are limited to importing settings or adding an empty tunnel via **Add empty tunnel**.

[![Added WireGuard client from the application level on macOS](wireguard_macos_import_tunner_or_start_from_scratch.png)](wireguard_macos_import_tunner_or_start_from_scratch.png)

After clicking **Add empty tunnel**, a configuration file will appear containing the generated **public key** and **private key**.

[![Added client configuration in WireGuard app on macOS](wireguard_macos_scratch_default.png)](wireguard_macos_scratch_default.png)

None of these settings are useful, as we need to retrieve everything from our server's configuration.

For the **iOS** app, we introduced the server's **Public key**, client IP address **(Addresses)**, name server **(DNS servers)**, **Endpoint**, **Allowed IPs**, and **Persistent keepalive**, all of which are missing here.

We need to configure it more manually.

Our configuration will look like this:

[![WireGuard Client Configuration for macOS](wireguard_macos_scratch_full.png)](wireguard_macos_scratch_full.png)

After pressing the **Save** button, macOS will prompt you to add the appropriate VPN profile to the configuration.

Finally, test whether everything works by clicking the **Activate** button.

[![We save the added client in the WireGuard application on macOS and activate it using the Activate button](wireguard_macos_activate_connection.png)](wireguard_macos_activate_connection.png)

If everything is configured correctly, you should connect without any issues, and everything should work.

{{% ads-in-article %}}

### Starting from QR Code

As you may have noticed, during the earlier configuration, there are options to use a generated QR code to add configurations on our client (peers) devices.

To enable this, you might need to add the `qrencode` package to your router if it wasn't added when you installed WireGuard in the first steps.

```bash
apk add qrencode
```

Go to your router, **Network** > **Interfaces**, and click **edit** next to your WireGuard (wg0) interface. Head to the **Peers** tab.

Click the **Edit** button next to the freshly created peer. At the bottom of the page, you will see **Configuration Export** with a button to **Generate configuration** that you can use to add your client configuration to the WireGuard app on the device you will be using to connect.

[![OpenWrt > WireGuard - Configuration Export with QR code option](openwrt_wireguard_peer_configuration_export.png)](openwrt_wireguard_peer_configuration_export.png)

This will generate the **content of the config file** (as seen above in the macOS configuration) that you can use in the client app.

[![QR code and config file generated on the OpenWrt router side](openwrt_wireguard_peer_configuration_export_config.png)](openwrt_wireguard_peer_configuration_export_config.png)

It will also create a handy QR code, which you can use to import the config file quickly to your client device.

However, there is one issue with it.

By default, the configuration will include this part:

```
...

[Peer]
...
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 100.70.131.4:1234
PersistentKeepAlive = 25 
```

> This refers to the **WireGuard Server**, not the user connecting to it. The term [Peer] can be a bit confusing. For the server, a peer is a client connecting to it. For the user, the peer is the server to which they are connecting.

> I am behind CG-NAT, and the IP `100.70.151.3` refers to a local IP address, which is incorrect. On your end, it may display the correct IP if you have an external IP provided directly.

Rather than providing an IP address, it's better to set a connection domain. Even if the IP changes, [the IP can be dynamically updated](/en/setting-domain-for-dynamic-ip-address-openwrt-ddns/) without needing to update each user (peer) configuration.

The problem is that in the web configuration, there is no option to specify a domain.

Because of this, using the QR code is **partly** pointless.

We can use it to import all configs, keys, etc., but we need to make sure to change our Endpoint IP to a domain name like:

```
Endpoint = vpn.wieckiewicz.org:1234
```

* * *

{{% ads-in-article %}}

[![Logo WireGuard oraz IPv6](wireguard_ipv6.png)](wireguard_ipv6.png)

## WireGuard and IPv6 Tunnel

If you've added an IPv6 connection to your Internet connection (which doesn't natively support it) via a tunnel using **Hurricane Electric Free IPv6 Tunnel Broker**, as I did in the post [Adding an IPv6 tunnel to a router with OpenWrt](/en/adding-ipv6-tunnel-router-openwrt/), you're probably wondering how to configure the WireGuard server to support this solution.

The above description adds support for local IPv6, which works within the router, but does not support outgoing traffic (to the Internet), even when IPv6 is available. All traffic is therefore carried out exclusively using IPv4.

You can check this by visiting [https://test-ipv6.com/](https://test-ipv6.com/) from your local network after connecting to WireGuard.

**Yes, there is a possibility of adding IPv6 support! Which of course we will do!**

The advantage of this solution is that not only will we be seen on the Internet using the router's external IP address (IPv4), but we can also assign an external, individual IPv6 address directly to our device connected to the VPN!

Although each WireGuard client on the Internet will be seen under one IP in version 4 (IPv4), in version 6 (IPv6) each device will have an individual address! All the magic of IPv6 (no need for port forwarding, etc.).

First we need to change the IPv6 settings we have entered, so where we have **fd42::** we need to replace it so that it matches our WAN6 interface prefix. We need to do this both on the router side, in the WireGuard server configuration and in the Peer settings, as well as on the client side (configuration file).

In the case of the server (including client settings - Peers - on the server side), we make changes via a web browser and then restart our **wg0** interface.

In the case of clients (Peers), we make changes in the configuration file and then import it to the application, or we edit each profile separately on each device.

To maintain consistency with the current IP address configuration, i.e. 10.0.0.1 for the server and subsequent numbers for clients, we will build the IPv6 address on the same principle.

Using [IPv4 to IPv6 calculator](https://www.ultratools.com/tools/ipv4toipv6) for 10.0.0.1 we get for example:

```
0:0:0:0:0:ffff:a00:1
```

We will change the first 4 zeros (**0:0:0:0:**) to the network prefix we received [for our tunnel](https://tunnelbroker.net/).

For example, if we received in **Routed IPv6 Prefixes** something like this:

```
2001:470:____:5cb::/64
```

Start - The prefix **2001:470:____:5cb:** will be constant, and each local address will get **0:ffff:a00:1**, with the last digit changing. 1 for the server, 2 for the first client, and so on.

And so, we change the server settings
**fd42:42:42::1/64** to **2001:470:____:5cb:0:ffff:a00:1/64**

For the first Peer
**fd42:42:42::2/128** to **2001:470:____:5cb:0:ffff:a00:2/128**

On the client side, in the WireGuard application, for the first client where we have:
**10.0.0.2/24, fd42:42:42::2/64** change to **10.0.0.2/24, 2001:470:____:5cb:0:ffff:a00:2/64**

> Item **:____:** has been censored of its full (current) prefix.
> 
> **0:ffff:a00:1** is an example address and I recommend not using it, but choosing your own unique one. If you are not sure whether the address you have chosen is correct, validate it along with the prefix using, for example, [this tool](https://www.helpsystems.com/intermapper/ipv6-test-address-validation).

If we did everything correctly, then **after connecting to the VPN** and going to the website [https://test-ipv6.com](https://test-ipv6.com/) we will get a result of **10/10**.

Additionally, if we have **[Secure DNS](/en/secure-dns/)** set, the [https://one.one.one.one/help](https://one.one.one.one/help/) page will also return in **Connectivity to Resolver IP Addresses** the availability of DNS addresses from the IPv6 level.

[![Cloudflare 1.1.1.1 Secure DNS Connection Status with IPv6 Active](cloudflare_1111_help_page.png)](cloudflare_1111_help_page.png)

> If you wish to backup your Wireguard interface configuration, please consider adding the '/etc/config/network' file to your backup configuration (**System** > **Backup / Flash Firmware** > **Configuration** tab).

**Regards.**

* * *

Credits: **[Birkhoff Lee](https://birkhoff.me/articles/setting-up-a-wireguard-server-on-openwrt)**


---
## Secure DNS (in browser and on OpenWrt router)
- **URL:** https://dariusz.wieckiewicz.org/en/secure-dns/
- **Date:** 2020-03-05
- **Tags:** Hardware, 1.1.1.1, ASUS RT-AC57U, Secure DNS, Certificate, SSL Certificate, Cloudflare, Private Relay, dns, DNS over HTTPS, DNS over TLS, DoH, DoT, IPv6, Firefox, Google, https, mozilla, OpenWrt, WireShark

### Content

You are probably aware that it is very important that the website you visit, especially the one where you enter any data (including **login** and **password**) is secured with a **so-called green padlock**, i.e. served by **https://** before the name of the website.

<!--more-->

**HTTPS** is a norm. More and more browsers now warn you if you're visiting a site over an unencrypted connection, and in the future, most won't even let you access it.

Thanks to **HTTPS**, websites are equipped with a **certificate** that allows us to encrypt our connection. The data we enter on the website, whether it is forms or simply the password to our account, is sent in an unreadable way to an outsider.

In the case of unencrypted **HTTP** connections, anyone between you and the target site can "eavesdrop" on what you do on that site. This doesn't require much knowledge, just the right software.

The person who can eavesdrop on you, whether you want them to or not, is primarily your Internet service provider. Depending on what obligations local law imposes on them, whether they want to or not, they are forced to pass on “your” information to the appropriate state authorities.

And so a global surveillance program is created, which, in conjunction with individual regimes around the world, decides what its citizens can and cannot see on the internet.

Hence, the **HTTPS** connection was presented, thanks to which all data sent to the website is encrypted beyond recognition. While it started with banking institutions, it has gained momentum and websites such as mine are served via a secure connection. A few years ago, certificates were an expensive investment and unprofitable for the average person. As the standard became more popular and users were oriented towards their own security, everything began to get cheaper. **A certificate for a website can now be obtained practically for free** and issued by very trusted institutions. On my website, I described how you can obtain a certificate in a very simple way, for free, and serve your website by default via HTTPS ([SSL Certificate for your WWW, in Polish)](/certyfikat-ssl-dla-twojej-strony-www/)).

When you visit a site through an encrypted connection, a potential eavesdropper won't see anything else besides a string of characters — **well, almost**.

A website and its address are one thing, but on the Internet everything starts with numbers. These numbers are IP addresses that correspond to servers located behind them. There can be many websites under one IP address, on one server (or more than one). To get to the website we want, we need to provide the appropriate name — **website name** — domain. Based on the name, the server will forward us to this website, not another.

For example, if we want to go to the **Google** website, we enter **google.com** (name, domain), not **216.58.206.110** (IP).

The server on the other side of the numbers, based on the name — domain we entered, forwards us to where we want.

And so, using an encrypted connection, you land on the page **https://www.google.com** and you can safely search for what you want. What you type into the search engine is not easily accessible to people eavesdropping on you. However, this does not mean that these people do not know what you are doing and what page you are visiting.

Well, when you type **google.com** in your web browser, the appropriate query goes to the so-called name servers (**dns**), which read the text (**name — domain**) and inform which server (**IP address**) you should be connected to.

When you query a name server, and before you land on a landing page, **anyone who can eavesdrop on you can see where you are going and what page you are visiting**. While they won't be able to tell what you do next on the page, what you visited is what they can use to determine what to do next.

> You've probably heard of a person being accused of terrorism simply because they accessed (knowingly or unknowingly) a website that was deemed unauthorized.

**Why?**

Namely, the query to the name server is sent **in an unencrypted form**. Any encryption slows down Internet traffic (this was the case a few years ago), so in order to quickly redirect to the target server, all queries are sent in clear text, which can be easily read by proxy servers, **as well as others** on the way to the destination.

A few years ago, the connection with the green padlock (**HTTPS**) was not so popular among ordinary users and owners of small websites. This was associated not only with costs, but also with the fact that slightly more computing power was needed to handle such a connection. Pages via HTTPS on weak servers **loaded significantly longer** than pages served via the standard HTTP protocol.

**Everything has changed, fortunately.** The difference in the speeds of unencrypted (HTTP) and encrypted (HTTPS) connections is really marginal. And despite the fact that the server on which the site is located still plays a significant role, even companies such as Google have announced that in 2020, it is **secure sites** that will lead in search results.

Despite the great leap in technology and user awareness, most of us are still unaware of the fact that the websites we visit - the addresses - are visible to everyone, because the name servers (**DNS**) have been working in a "simple" way for years.

Regardless of whether you choose the one provided by your operator as your name server, or as a conscious user you change it to **[Google](https://developers.google.com/speed/public-dns/docs/using)** (_i.e. 8.8.8.8_), **[Cloudflare](https://1.1.1.1/dns/)** (_1.1.1.1_) or **[OpenDNS](https://www.opendns.com)**, it is still all visible to prying eyes. Hence, user awareness is being created by large companies, introducing encryption to the level of name servers, thus increasing user security.

**User security is all the rage these days, and rightly so!**

At the beginning of 2020, **Mozilla** released information that was quickly picked up by all portals. Namely, in their **Firefox** web browser, they enabled by default (**officially will come in the next weeks**) encryption of DNS nameservers using a similar method to pages served over HTTPS. That is why it was called **DNS over HTTPS**, or **DNS name server served over a secure HTTPS connection**, in short **DoH**.

Therefore, from the moment you type in **google.com** until you land on the target page, **everything is encrypted** (well, almost everything). Snoopers will see that you are visiting something on the Internet, but it will be limited only to the IP address of the server. As a rule, one IP address can host a multitude of websites, so determining exactly which page you are visiting is not so easy.

The fact that **Firefox** has been enriched with this feature, which has also been enabled by default for all sites we type in the address bar, does not mean that we should abandon our **dangerous** browsers en masse and install the **safe Firefox** browser.

Over the years, other browsers have also gained support for encrypting DNS queries. **Firefox** has this feature enabled by default, while in others we have to do it manually.

In Firefox, the entire service will initially rely on nameservers provided by **Cloudflare**.

**Cloudflare** nameservers are some of the fastest on the market today, and they come with a few extra perks.

But what if we want to use **DoH** today and keep our browser safe from prying eyes, especially in countries that are starting to track users at every step?

I am not talking only about Poland, but also about Great Britain. After leaving the European Union and the end of the transition period, many things can change.

**Well, we can enable DNS encryption today in our browser on our computer.**

{{% ads-in-article %}}

## Mozilla Firefox

As I mentioned earlier, Firefox currently has DNS encryption enabled by default, however, as we can see, it doesn't always work right away. The software's creators point out that whether the service works by default depends on the region of the world in which we are located.

To check this, go to **Settings** > **Privacy & Security** and scroll down to the **DNS over HTTPS** section.

As you can see below, in my case (UK), with **Default Protection** selected, the status above returns **Off**.

[![Firefox - Settings - Privacy & Security - DNS over HTTPS settings](mozilla_settings_privacy_security_dns_over_https_default.png)](mozilla_settings_privacy_security_dns_over_https_default.png)

By choosing the **Increased Protection** option we can change this. At this stage we also have a choice of other service providers, in addition to Cloudflare.

[![Firefox - Settings - Privacy & Security - DNS over HTTPS - Increased Protection](mozilla_settings_privacy_security_dns_over_https_increased.png)](mozilla_settings_privacy_security_dns_over_https_increased.png)

## Google Chrome & Microsoft Edge (Chromium)

For Google Chrome, go to **Settings** > **Privacy and Security**, and in the **Advanced** section, make sure the toggle next to **Use secure DNS** is turned on.

The default option that is checked is to use secure DNS from the current service provider, but it is not specified which one, and it is noted that sometimes this option may not be available (_Secure DNS may not be available at all time_).

Therefore, it is better to choose the next option and select Cloudflare or another service provider from the list.

[![Google Chrome - Settings - Privacy and Security > Secure DNS](chrome_settings_privacy_security_secure_dns.png)](chrome_settings_privacy_security_secure_dns.png)

Similarly, in the case of Microsoft Edge, we go to **Settings** > **Privacy, Search, and Services**, where in the **Security** section, we check the option next to **Use secure DNS...** (_Use secure DNS to specify how to lookup the network address for websites_). By choosing the second option, as in Google Chrome, we can choose our service provider, e.g. Cloudflare.

## Safari

Here, unfortunately, we can't enable anything — set it to start using encrypted DNS. Apple has built protection for our DNS server queries into the system (macOS, iOS or iPadOS), provided that we have purchased the iCloud+ package, which will provide us with the **Private Relay** service.

The positive side of this solution is that all our DNS server queries, including those from other applications, are encrypted. Then we are not limited to just the web browser. The negative side is the fact that we have to pay Apple for this type of service.

If, however, we do not want to pay, and we want to receive protection for our entire system for Apple systems, but also Windows and Android devices, all we need to do is install the application [**WARP (1.1.1.1) by Cloudflare**](https://1.1.1.1), which will provide us with what Apple offers within Private Relay. More on this below.

---

If we did everything correctly, we go to the page [https://one.one.one.one/help](https://one.one.one.one/help) to check if our **DoH** works or not. However, this is not a 100% interpretation, especially if you use another method of implementing **secure DNS** in your home network, which I will write about in a moment.

Before you go any further, you will ask how to enable **DNS over HTTPS** on your tablet or mobile phone.

Well, nothing could be simpler! Just install the dedicated **WARP** application from **[Play Store](https://play.google.com/store/apps/details?id=com.cloudflare.onedotonedotonedotone)** (Android) or **[AppStore](https://apps.apple.com/us/app/1-1-1-1-faster-internet/id1423538627)** (iOS) and follow the instructions.

[![Cloudflare App 1.1.1.1 Connected](1_1_1_1-cloudflare-app-connected-min.png)](1_1_1_1-cloudflare-app-connected-min.png)

[![Cloudflare 1.1.1.1 Connection Information](1_1_1_1-cloudflare-checking-min.png)](1_1_1_1-cloudflare-checking-min.png)

[![Cloudflare 1.1.1.1 Connected with DNS over HTTPS (DoH)](1_1_1_1-cloudflare-ok-cloudflare-doh-min.png)](1_1_1_1-cloudflare-ok-cloudflare-doh-min.png)

In addition to DNS security, the Cloudflare app also offers **WARP (1.1.1.1)** to speed up internet surfing, but I won't go into detail about that, as that's a topic for another post.

> Windows 11 also has the ability to enable system-wide DNS server encryption from your network card settings. I personally don't use this because it causes problems in my corporate environment, but that doesn't mean it can't be done. I refer you to the post [Enable DNS over HTTPS (DoH) in Windows 11](https://www.elevenforum.com/t/enable-dns-over-https-doh-in-windows-11.280/).

---

**Moving on...**

If you've reached this point, you may have had a light bulb go on above your head that has turned into a question mark.

If we have set **secure DNS** in the browser, what happens if other programs connect using the name server. Unfortunately, these are **not secured** (except for mobile applications using the **WARP (1.1.1.1)** application).

So you ask how to protect the entire network and all programs on the network using DNS from nosy outsiders, or people from our home network who do not use our Internet for the purposes they should (they spy on us).

**Now this matter is not so simple, but possible.**

The best solution would be to enable **DoH** on our router side. **And I'm not just talking about setting Cloudflare DNS addresses on your router** for your entire network (which you should enable anyway), as the name server queries will still be sent in clear, unsecure text.

**Unfortunately,** routers that are standardly received from operators and Internet service providers do not have the ability to enable **DNS over HTTPS** as standard and there is (usually) nothing we can do about it.

However, if we have our own router that we have chosen not only to do its job, but also to offer additional, advanced options, [**OpenWrt**](https://openwrt.org) can come to our aid.

**OpenWrt** is an alternative firmware for our router that turns it more into a Linux-based box. It opens up options for advanced configurations.

To check if your hardware supports OpenWrt, just go to: **[https://openwrt.org/toh/views/toh_fwdownload](https://openwrt.org/toh/views/toh_fwdownload)** and search.

---

{{% ads-in-article %}}

## DNS over HTTPS (OpenWrt)

> Optimised for OpenWrt 25.12 using `apk` instead `opkg`

So, if we decided to run **DoH** on our OpenWrt router, we start as follows.

First, we need to update the information regarding our software packages on the router.

We log in via **SSH** and execute the following command:

```bash
apk update
```

Then:

```bash
apk upgrade
```

This will update the packages currently installed on the router to the latest versions.

We then proceed to install the DNS encryption package.

```bash
apk add https-dns-proxy luci-app-https-dns-proxy
```

To check if our router is acting as an encryption proxy, we execute the following command:

```bash
nslookup openwrt.org localhost
```

After which we should receive an answer.

This is how DNS encryption works at the router level.

By default, the package on the router uses Cloudflare servers (as primary) and Google (backup), depending on which one is currently available.

---

After these actions in **DHCP and DNS** we will notice that our DNS servers that we entered earlier have changed to **127.0.0.1#5053** (Cloudflare) or **127.0.0.1#5054** (Google).

In the administration panel, in the **Services** tab **>** **DNS HTTPS Proxy** we can check which port is responsible for Cloudflare and which for Google.

By going to [https://one.one.one.one/help](https://one.one.one.one/help) we will see that we are using Cloudflare as our default name server (DNS) **and that our DNS queries are encrypted over HTTPS** (**DoH**).

We quickly and relatively painlessly secured our entire local network and forced it to use **DNS over HTTPS** for every DNS server query.

---

**Moving on...**

On a router with OpenWrt we can also run DNS encryption over TLS, however, this requires a lot of system resources and a decent router, which is why I decided not to describe this method.

> As an aside, everyone is adopting **DNS over HTTPS** as the standard, which pushes away the option of encryption over TLS. Similar to what happened with HD DVD and Blu-ray. As I know, Blu-ray was much better received, and HD DVD died a natural death. I suspect that will happen with **DNS over TLS** as well.

A quick comparison of the differences between **DNS over HTTPS (DoH)** and **DNS over TLS (DoT)**.

Both methods aim to achieve the same thing, which is **encrypting our name server (DNS) queries**.

**DoT** uses the **TCP** protocol (basic connection protocol) with an encryption and authentication layer (layers over TLS encryption and authentication). **DoH** uses the **HTTP/2** protocol to connect. **HTTP/2** is responsible for communication between the server and the browser to ensure fast loading of websites, and it is not without reason that it is important in the case of the name server (DNS). The connection to the DNS must be fast, because this is the first step when we enter a given website on the Internet.

In addition, **DoT** uses port **853** (or 53), while **DoH** uses port **443**, the same port used to go to the page with the green padlock (**HTTPS**). This means that visiting a secure page (via port 443) and a query request to the name server look the same and it is difficult to distinguish them and, above all, block them. In the case of a dedicated port, blocking **853/tcp** is much easier than **443**.

Another difference is that in the case of **DoT** on the router, we are not 100% sure that everything works by going to the [https://one.one.one.one/help](https://one.one.one.one/help) page, without running packet tracking with **[WireShark](https://www.wireshark.org)**. Only then can we confirm that DNS queries are indeed encrypted. In the case of correctly entered **DoH** on the router, the above page should confirm to us that everything works.

Of course, it is also worth using the **[DNS Leak](https://www.dnsleaktest.com/)** page to analyze the leak of queries to name servers (DNS). By running the **advanced test (Extended test),** we can check whether the answers come from only one source (one type of server).

---

The **https-dns-proxy** package uses authentication unit certificates to function correctly, so these certificates need to be renewed from time to time. I recently encountered a problem where **DNS over HTTPS** suddenly stopped working (it was when I was making the post: [**Setting domain for dynamic IP address (OpenWrt and DDNS)**](/en/setting-domain-for-dynamic-ip-address-openwrt-ddns/)). It turned out then that the file storing the certificates in the system was corrupted and had to be downloaded again:

With **curl**

```bash
curl -k -o /etc/ssl/certs/ca-certificates.crt https://curl.se/ca/cacert.pem
```

By default, OpenWrt (on devices with low storage) does not have **curl** installed (or has a stripped down version). To add it, run the following command:

```bash
apk update
apk add curl
```

> Curl is a good method for updating certificates. If you run it for the first time and don't have any certificates on your system, it may return an error. Therefore, it is worth using `wget` at the beginning and then relying on `curl`.

Using **wget**

```bash
wget  --no-check-certificate -O /etc/ssl/certs/ca-certificates.crt http://curl.se/ca/cacert.pem
```

It was an unusual situation, but at the same time it gave us something to think about, because the certificates in our system should be refreshed from time to time. To do this, we can add a rule to the schedule (**Scheduled Tasks**), which will do it for us on the **first of every month** at **3 am.**

Going to **System > Scheduled Tasks** we add the following line:

For **curl**

```
00 3 1 * * /usr/bin/curl -k --silent --remote-name --time-cond /etc/ssl/certs/ca-certificates.crt -o /etc/ssl/certs/ca-certificates.crt https://curl.se/ca/cacert.pem >/dev/null 2>&1
```

For **wget**

```
00 3 1 * * /usr/bin/wget -q --timestamping --no-check-certificate -O /etc/ssl/certs/ca-certificates.crt http://curl.se/ca/cacert.pem >/dev/null 2>&1
```

**A minor note.**

The OpenWrt built-in **wget** (in some versions) may not have the option to check the time (_--timestamping_) for files. To do this, you need to install (update) the latest version of it:

```bash
apk update
apk add wget
```

## Package Tracking

To check whether our internet requests are actually sent in easy-to-read text, we can extend the **tcpdump** packet.

```bash
apk add tcpdump
```

And on our computer we install the program [WireShark](https://www.wireshark.org), which will be used to capture packets directly from the router.

In the case of macOS, simply launch the terminal and execute the following command to start capturing packets on our router and pass them on for analysis in WireShark on our computer.

```bash
ssh root@192.168.1.1 tcpdump -i eth0.2 -U -s0 -w - 'not port 22' | sudo wireshark -k -i -
```

Of course, **192.168.1.1** is the address of our router, which we need to adjust if it is different.

At this point you will be required to enter your router's SSH password and your macOS admin password. Since this process can be a bit confusing as to which password to enter when, it is best to fire up Terminal and run **sudo su** before doing the above.

Now, in the WireShark window, we should see the traffic we are generating.

And that would be all.

**Regards.**


---
## Backup Plan
- **URL:** https://dariusz.wieckiewicz.org/en/backup-plan/
- **Date:** 2020-02-27
- **Tags:** Blog, 1Password, 2FA, LastPass, password manager, backup plan, SMS, two-step verification

### Content

We live in a time where information is worth more than money. Information that may seem worthless to us (trivial) may turn out to be crucial to our security. I am talking about information in electronic form, i.e. our email and passwords.

<!--more-->

The first thing that will come to your mind is - my email is worthless. It won't do anyone any good if someone hacks into it. What good is my email to him? I'm not some businessman who spends who knows how much money and has to worry about the security of his information. I'm just an average person.

However, few people realize how wrong they can be at the beginning of what they claim. Our information, i.e. e-mail, is often used to communicate with the bank. Starting from this, for example, someone who gets into our mailbox will continue to dig. Starting with money, through social media, they will dig and dig. Until at some point we understand how important information about an ordinary person is, because it can lead us to the edge from which there is no return. Therefore, even being an ordinary person, we must take care of the security of our information as if our and others' lives depended on it.

In the era of two-step verification ([2FA](https://en.wikipedia.org/wiki/Multi-factor_authentication)) and password managers (i.e. [1Password](https://1password.com) or [LastPass](https://www.lastpass.com)) we try to secure our data as much as possible.

If we are already at the stage where we enable two-factor authentication (ourselves, of our own free will), we are more aware than others of the danger lurking. If we also use a password manager and try to use a unique password for each site we log in to (using a password generator), we become the percentage of the community that takes security issues very seriously.

**But is that really true?**

**I recently asked myself that question.**

Well, in my case, I put everything aside - my phone, computer, smart watch and looked at what I would do if I had to start from scratch. Having nothing, I would restore everything to the way it was and access to everything that is important to me.

And so I listed 10 services that are critical to me and from which I would start restoring.

The two basic services that I would need to regain access to are my phone number and email address.

And here I asked myself what my backup plan is.

Starting with the email, assuming I know the password, without having access to my phone number and the phone itself, there is no need to ask for an SMS password, a code from the authenticator or confirmation in the application that it is us. And so the first difficulties begin.

I remembered at the same time that Gmail (because that is where I have my primary email), in the security options, when I turned on two-step verification, asked me to generate security passwords in case of such a situation. And here is the first question, what did I do with them?

**Well, Google, it asks to save or print the passwords. So I saved them...**

I saved the passwords in _(sic!)_ my password manager, which I don't have access to. I need the email and password. Additionally, a good password manager also requires two-step verification. Now, standing empty-handed, we have nothing. We locked the security passwords that would allow us to regain access to the email in a safe that we don't have access to.

**It's like locking your car with the keys inside, except in this case there's no way to break the window as a last resort.**

A simple example shows that my security plan has fallen apart. That is why it is important to think about where we save passwords, and what is even more important, how we will gain access to them. Here, seemingly old-fashioned methods will prove to be the best. Writing down passwords in a safe place or printing them out and hiding them somewhere safe for a rainy day turns out to be a better, although, it would seem, not the safest solution.

Printed security passwords, hidden somewhere deep in the closet, in the attic, in a bank vault, with family, become the key to everything.

Without access to passwords and a phone number to receive an SMS with a code, you try other methods, i.e. an alternative email address provided for just such an emergency situation. And the funniest thing is that the emergency email you provided is secured in the same way as the main email. And so once again, without a physically saved or printed security code, our elaborate plan fell apart.

You start thinking further. Phone number.

Well, you can ask the operator to issue a replacement card with our number and block the old one. Thanks to this, you can, within a few hours to days, recover one key element to restore access to your email.

In my case, when I use GiffGaff, I can transfer my number from the old card (which I could lose access to if I lost my phone) to a new card (a spare one that I always have somewhere to hand) without unnecessary fuss. All I have to do is log in to my account and start the appropriate process.

**Ha!**

{{% ads-in-article %}}

If I can remember the username, taking care of my security, I will generate a "safe" password, which I have saved in the password manager, to which I do not have access yet. And here I have another example of how my security plan is falling apart. And it is enough, together with the passwords for e-mail, to write it down, so that in an emergency I have access to it. 

Who would have thought that the old-fashioned, dangerous method of writing down passwords on a piece of paper would be the key to regaining control over our data.

Of course, this is not about creating a notebook entitled Passwords, hidden in the first drawer at home. Here, a bit of finesse and thought is needed. Using a simple cipher in our notes can help with this. The only problem may be our memory, but we have little influence over that.

And so it may seem that "only e-mail" and "only phone number" are nothing important, but starting from them, we can regain access to our money - bank; memories - photos or public information, i.e. social media.

I mentioned earlier that I personally prepared a list of 10 services that are critical to me and that I would need emergency access to if I had to start from scratch. Therefore, so that my awareness of the threat and the use of "advanced" security tools do not cause my emergency plan to fall apart the first time I try to run it, it is worth thinking the whole situation over from the beginning. Personally, I have prepared a piece of paper that will be my emergency plan in the event of my digital catastrophe.

Of course, you can think of additional ways to avoid being blocked by the sophisticated security systems that were supposed to protect us. One way is to add additional phone numbers, email addresses of people we can trust and who, when we are in need, will lend a helping hand.

Like everything, our emergency plan is unique. There is no way to do it right or wrong, one way or another. What is important is that one day, when we sit in an empty room, without access to everything we had every day and think about how to start everything over, or rather, how to restore everything to the way it was, start acting and so that our plan works to our advantage.

Best regards


---
## How to Switch Mobile Network in the United Kingdom
- **URL:** https://dariusz.wieckiewicz.org/en/how-to-switch-mobile-network-in-the-united-kingdom/
- **Date:** 2019-07-30
- **Tags:** GiffGaff, Ofcom, notice period, PAC, PAC Code, porting authorization code, STAC, STAC Code, service termination authorisation code, Mobile Network, SIM CARD, SMS, text message, United Kingdom, Switch Mobile Network

### Content

Have you seen Sky Mobile's "_It's not me, its you_" ads on billboards lately?

Well, in recent weeks there has been quite a change to the benefit of consumers, especially mobile phone users.

Mobile phones are everyday life. In the UK, this sector is a huge business, especially since the island pays a little differently and you can afford slightly better phones on a monthly subscription.

Personally, I am not and never have been a supporter of subscriptions in the UK. Therefore, the introduction of the requirement of easy operator change and even easier number portability using only text messages (SMS) became something groundbreaking, so I decided to take a look at it.

<!--more-->

> Some operators, such as Three UK, despite Ofcom's requirement, require you to log into your account via the website in order to receive the transfer code.

I don't know about you, but I spent, or rather lost, a lot of time every time I wanted to port my number to another operator. In almost every case, the customer service, with their broken English, tried hard to convince you to stay, sometimes using nonsense arguments, promising pears on willow.

**Times have changed…**

If it's easier to make a decision now, why not upgrade to a better mobile network?

As far as you may know, I am a GiffGaff (O2) user and in this post I will encourage you to consider moving to a network built and run by its users.

**So let's see what this is all about.**

## Text-to-Switch

Due to the problems that consumers experience when switching operators, the British regulator Ofcom announced at the end of **June 2019** that from now (**July 1st 2019**) **just a text message is enough to change operator** .

This does not mean that we can change it just like that, even if we are bound by a contract. Everything we have agreed to and signed the contract must be settled before we can move forward.

But that doesn't mean we can't start the process now.

We start by checking what we can do by sending a text message to the number\
**85075** with the content **INFO**

In response, we will receive information whether we are still bound by any contract with our current operator. If so, the operator will inform us in a reply message for what period the contract is concluded and how much it would cost us to terminate it early.

> If we have more than one SIM card in our account (e.g. Sky, O2), then in order to transfer the number, you also need to log in to the account via the website, as we will not be able to do anything via SMS.

And here Ofcom has something to be proud of. With the introduction of the possibility of completing formalities with the operator via text message (in Poland it is called **SMS**), operators have been deprived of the possibility of additional punishment of consumers for the so-called **notice period** which you supposedly have to give to your operator, before you can move (usually 30 days).

Currently, if we want to terminate our contract, the operator will inform us how many subscription fees we have left, and their sum is the amount we must pay if we want to end our obligation earlier. Of course, depending on the contract, the operator may charge additional fees - penalties. There is nothing you can do about this, so check your contract.

In the case of the subscription on the island, the majority of the amount that users pay monthly are installments for the phone, and only a fraction is the value of added services. Simple math and the fact how much we can gain by switching to another operator ([GiffGaff](https://giffgaff.com/orders/affiliate/itdarek?ggSMS=app)) will help us quickly compensate for the costs incurred.

* * *

In the case of prepaid (PAYG), we will receive information about our tariff plan and account balance, which we will lose (unless we use it before) when we switch to a new operator.

* * *

![Text-to-switch](text-to-switch-process-ofcom-org-uk-bg.png "Text-to-Switch - Source: Ofcom")

If we are informed how much it will cost us and we are determined to change, to start the number porting process we need the so-called **PAC Code** (porting authorization code). We provide this code to our new operator if we decide to transfer our number.

{{% ads-in-article %}}

To get this code, we send a message to the number\
**65075** with the text **PAC**

This message will start the number porting process.

In the return message we will receive our code (valid for 30 days) along with information on how much we need to pay to end our current obligation with the operator (as described in the step above).

Remember that some operators use catches in the contract. If you end the obligation earlier, although you don't have to give them 30 days' notice, they may have clauses with an additional fee, as I mentioned - a penalty - which unfortunately we will have to pay. So once again, **read the contract!**

After receiving the code, we can start the number porting process.

* * *

![giffgaff logo](giffgaff.png)

In the case of the GiffGaff network, I recommend that you start porting your number by ordering a free SIM card. [Order a card from this link and get an extra £5 on your first top-up](https://giffgaff.com/orders/affiliate/itdarek?ggSMS=app).

You must activate your card before transferring your number. You will initially be given a temporary number. By completing the form, the so-called [transfer form](https://www.giffgaff.com/support/transfer/pac) you will start the whole process. After the number is transferred, the current number on the card will be replaced with the correct number.

* * *

Of course, if you are not too attached to your number, you can start the process of disconnecting from your operator by sending a message to the number\
**75075** with the text **STAC**

This code is responsible for terminating our service with the current operator (**service termination authorization code**).

The whole process is similar to that of transferring a number, but you can start using the new number - informing your friends about the new number - when you select the offer and activate the card.

Here you can also order a card from **GiffGaff for free** and receive an **extra £5** on your first top-up using [this link](https://giffgaff.com/orders/affiliate/itdarek?ggSMS=app).

* * *

The whole process, in theory, should go smoothly. However, we should remember that the last bill from our current operator should not be a surprise for us, let's start by finding out how much it will cost us (**INFO** at **85075**).

As for the GiffGaff network itself, I encourage you to read some useful links related to changing your operator via text message.

* [https://www.giffgaff.com/help/articles/how-do-i-keep-my-current-mobile-number-when-i-join-giffgaff](https://www.giffgaff.com/help/articles/how-do-i-keep-my-current-mobile-number-when-i-join-giffgaff)
* [https://www.theguardian.com/money/2019/jun/28/mobile-phone-switch-network-text-pac-code](https://www.theguardian.com/money/2019/jun/28/mobile-phone-switch-network-text-pac-code)

Regards.


---
## In a Search of a Favorite Start Page
- **URL:** https://dariusz.wieckiewicz.org/en/in-search-of-a-favorite-start-page/
- **Date:** 2019-03-27
- **Tags:** Blog, Bookmarks, chrome, Fast Dial, Favorites, Incredible StartPage, macOS, New Tab Page, Safari, Speed Dial, Windows

### Content

For years, various **speed dials** or **fast dials** have been popular among users who wanted to start browsing the internet with something other than the Google search engine.

Trends have changed, along with the browser add-ons people used. Since Chrome became the dominant force on computers, **fast dials** haven't evolved enough to fit into society.

<!--more-->

A serious problem with **fast dials** was that their settings were lost after reinstalling the system or browser. While they had export options (if someone remembered in time) or synchronisation (usually paid), you had to set them up again every time.

When I switched to macOS and Safari as my default browser, I really liked Apple's **fast dial** solution.

[![Fast Dial Safari](fast_dial_safari.png)](fast_dial_safari.png)

Safari offers the display of tiles, thumbnails of our sites saved in bookmarks. This is good because the bookmarks synchronise with the Apple account, just like with Chrome and a Google account. There's nothing to set up here and everything looks like a single entity.

As a Chrome user on Windows, I stopped using **fast dials** that didn't offer similar functionality and stuck with **[Incredible StartPage](https://chrome.google.com/webstore/detail/incredible-startpage-prod/ncdfeghkpohnalmpblddmnppfooljekh)**. It wasn't a perfect solution, but it fulfilled the idea of having bookmarks in the cloud, which were then displayed (independently) as a start page after installing the add-on.

However, I kept searching for a solution on Chrome that I liked from Safari, and **I finally found it**.

{{% ads-in-article %}}

Recently, I discovered **[Favorites - New Tab Page](https://web-accessories.com)**, which uncannily resembles the Safari solution.

[![Fast Dial Chrome](fast_dial_chrome.png)](fast_dial_chrome.png)

It integrates perfectly with our bookmarks and allows us to organise and manage them by dragging icons or using the menu hidden under the right mouse button. We have complete freedom to organise bookmarks into folders and choose which folder should be displayed by default as our **fast dial**.

Moreover, although it's not essential, the add-on allows us to specify the icon density and grid layout to maximise space, especially on high-resolution screens.

Finally, something light and functional has been found. You can download **Favorites - New Tab Page** for your Chrome browser **[here](https://chrome.google.com/webstore/detail/favorites-new-tab-page/kjkbcegjfanmgocnecnngfcmmojheiam)**.

As I like to try new things from time to time, including new browsers, I keep a close eye on the development of Firefox. Unfortunately, I haven't found a worthy add-on for this browser. And, although Firefox partly supports (or used to support) Chrome add-ons, the above one unfortunately doesn't work, so I'm still searching. If you know of any solution similar to the above for Firefox, please let me know in the comments.

Best regards.


---
## Quidco - get your £5
- **URL:** https://dariusz.wieckiewicz.org/en/quidco/
- **Date:** 2019-03-02
- **Tags:** cashback, claim, cookies, referrals, Premium, quidco, refer a friend, trustpilot

### Content

I have never been too convinced about websites that offer the so-called **Cashback**, i.e. partial refund of costs incurred for purchases from selected sellers. When I moved to [Monzo](https://join.monzo.com/c/qbqgltl), I started following their forum ([community](https://community.monzo.com)), reading the opinions of other users whether it works and if so, how much money can you get back on this by making purchases that you would do anyway.

<!--more-->

And so, at the end of **January 2019** I decided to check out Quidco, one of the two main players on the market in the UK. As the basic membership costs nothing (Premium is only **£5** per year deducted from the cashback earned), I don't risk anything.

If you shop, for example on eBay or Argos, order a pizza from Dominos, plan to change your electricity company, or plan to buy a Disney+ package, why not get extra money for something you will be doing anyway.

[![Quidco - Example](quidco-przyklad-2023.png "Quidco - Example")](quidco-przyklad-2023.png)

According to Quidco, their members receive on average **£300 per year**. Personally, after only a month of use, I have no doubt that this is real unless you refer a lot of people. Additionally, on [TrustPilot](https://uk.trustpilot.com/review/www.quidco.com) over 125,000 people gave Quidco a rating of **4.3 out of 5** (74%, 5-stars), which is also impressive.

In the first month, I only made a few planned purchases, some of which did not qualify for Cashback, but it was not Quidco's fault but the way I made these purchases, so first of all I want to share my experience with you.

* * *

First of all, you must be aware that for everything to work, Quidco needs to track the transaction from start to finish, and for this purpose it primarily uses **cookies**. Quidco is not a charity. They also receive cashback from sellers who cooperate with them. They share a portion of their cashback with their users.

Once you have searched for the seller (on the Quidco home page) from whom you want to make a purchase, using the link you will be taken to the seller's website where you will be able to make your planned purchase.

You will find out how much refund we will receive (in **%** or **£££**), how quickly the purchase is tracked and when the funds will be released to us on the Quidco website before you start purchasing.

And here, if we made the purchase correctly (that is, we did not do anything that could invalidate our Cashback, i.e. we used an additional discount code unrelated to Quidco), our transaction should appear in the **Tracked** section. It usually takes from several minutes to several hours or days. Now all we have to do is wait the period after which these funds will be released and will be available for withdrawal (**Account balance**).

Well, the funds we collect are not paid immediately. Quidco verifies transactions with sellers and if there are no comments, e.g. you made a purchase and later cancel it and return the goods, the funds are released and you can withdraw them. Depending on the type of transaction, the amount of cashback and the seller himself, the funds may be available after a few days, and sometimes only after a few months (e.g. when changing electricity suppliers).

## Not all transactions are tracked correctly

Everything is beautiful when everything works. Nowadays, especially when we shop from a mobile phone, when we go to the seller's website, we can be redirected to a dedicated application installed on our phone, where we can make a purchase in a convenient way.

This _"convenient"_ method means that Quidco has no way of tracking this type of transaction. They talk about it at every step, so it is better to make a purchase in the web browser in which the link from Quidco was opened.

I personally experienced this myself when I lost several cashbacks. This is what "learning" how to use it is all about. I didn't actually lose anything, because if I made the purchase traditionally, I wouldn't have received anything extra.

## Even purchases from your browser may not be tracked correctly

_The struggles continue._

Even if we used the link on the Quidco website correctly and went to the seller's website, the transaction cannot always be tracked. Various extensions and privacy settings in the browser are to "blame" here.

If you use **AdBlock** or another similar browser add-on (or block cookies in your browser) designed primarily to block ads, you may notice that in addition to blocking ads, they also block tracking codes/cookies that are necessary to pay you cashback.

Personally, I don't recommend browsing the web without **AdBlock Plus**, but in the case of Quidco, I had to change the way I shop on my computer to make sure I got the cashback I deserved. I also found this out when my purchases were not picked up and everything went through the roof.

Since I use Safari every day, I have Chrome installed on the side and I used this browser (_without Adblock Plus_) for purchases with cashback.

## What to do if the transaction has not been tracked?

Fortunately, when our transaction has not been traced, all is not lost, we can always file a _“complaint”_ (**Claim**), during which we will select the seller (he will be available when we used the link from the Quidco website), the date of the transaction and we will provide some additional details that will allow both parties to identify the transaction. If everything went as we planned, we will soon see the missing transaction and cashback on our **Tracked** page.

{{% ads-in-article %}}

## Premium Membership

Quidco also offers **Premium** membership. However, you don't have to pay for it. A fee of **£5** is deducted from the first cashback earned **once every 12 months**. Thanks to premium membership, the user is offered a portal without advertising and with additional options that allow you to increase the cashback value that you can receive from selected sellers. Personally, I decided that I would try this option and after a year I would check whether it is profitable.

> Although the first year was intense and I got a lot out of my purchases, I did not decide to continue the premium package for the following years.

## Get £5 from your referral

Now coming to the point, which is **£5 for you**.

Well, in addition to the possibility of getting cashback on purchases, Quidco offers a referral program. By encouraging a friend to join Quidco using the referral link (below), they receive £5 added to the first confirmed £5 cashback. Since it's free, why not take advantage?

> [https://www.quidco.com/raf/8982863/](https://www.quidco.com/raf/8982863/)

The person you refer gets **£5** and you, as the referrer, get **£15**.

[![Refer your friends. You get £15. Your friend gets £5.](quidco_refer_your_friends_2023.png)](quidco_refer_your_friends_2023.png)

Once you join Quidco, you can refer your friends using your individual link in [**"Refer a friend"**](https://www.quidco.com/referrals/) so you can start earning money yourself.

Nothing but use.

**Regards.**



---
## My Antivirus - Windows Defender
- **URL:** https://dariusz.wieckiewicz.org/en/my-antivirus-windows-defender/
- **Date:** 2018-09-30
- **Tags:** Windows, antivirus, antywirus, av-test, Avast, Google Chrome, malwarebytes, Microsoft, security, windows defender, windows defender browser, Windows Update

### Content

**Hell has frozen over once again.**

I have been using [**Avast**](https://www.avast.com) on my Windows computers for years and it has worked wonders. I have not encountered any infections and it has protected me from several threats that I have encountered.

<!--more-->

Since the release of **Windows 10 (1607) Anniversary Update**, the built-in protection system has taken on a completely different meaning. The constantly updated list of viruses and file scanning without the need to be connected to the Internet have begun to question other free antivirus solutions. What's more, we are notified of all types of threats in the Windows notification center.

**At some point I began to wonder to what extent Windows Defender has become a decent antivirus.**

A few years ago, if someone mentioned **Windows Defender**, you could hear laughter in the audience. However, now, a program perfectly integrated with the system that protects not only against viruses, but also other types of threats. Incidentally, it has more options than the free version of Avast and made people stop laughing.

Of course, it is not easy to erase the negative opinion that this program deserved in the past (which also stuck with me), so I am also trying to overcome it. Microsoft has transformed the entire program into **Windows Defender Security Center** (Windows Defender security center), but the initial part still calls for solutions that were not entirely successful in the past.

Renowned companies evaluating antivirus programs give this solution very high marks, outclassing other, sometimes very expensive solutions (in the company's test [**AV-Test** Windows Defender achieved a very good result as for December 2017](https://www.av-test.org/en/antivirus/home-windows/windows-10/december-2017/microsoft-windows-defender-4.12-174847/)). A result close to 100% in virus protection is no longer an exception, but has become the rule. What's more, the protection against spyware built into the system itself, solved with automatic updates from Windows Update, calls into question the need to use other antivirus programs, especially on home computers, although it works just as well in a small company.

My decision when choosing **Avast** was the fact that it did not use excessive computer resources, especially those not equipped with at least 4 GB of RAM and SSD drive. However, why install something that has fewer options in the free version (free) compared to the solution built into Windows.

It is not without significance that I recommend this solution to anyone whose computer I "look" at for a moment.

![Malwarebytes](Malwarebytes_Logo_and_Wordmark_2016.png)

What's more, live virus protection works in cooperation with solutions from **Malwarebytes**, which is somewhat of a leader when it comes to solutions for other platforms, such as **macOS**.

Taking a step forward, Microsoft is still trying to convince people to use EDGE (which is a lousy browser) and has decided to protect all those who use the **Google Chrome** browser, [**providing an add-on**](https://chrome.google.com/webstore/detail/windows-defender-browser/bkbeeeffjjeopflfhgeknacdieedcoml), which will expand the protection possibilities when browsing websites. I sincerely recommend installing it.

However, let's be honest. Even the best, most expensive and most reputable solution will not protect us from viruses, hackers or data stealers, because the weakest element here is **the computer user himself**.

We are the ones who thoughtlessly install programs from untrusted sources, click without reading, on everything that comes our way, and then complain that something is wrong. Somehow, I have not been infected with any virus in the last 15 years at least. This does not mean that I have not encountered them in my daily work. Antivirus programs have protected me from this, as well as prudence and logical thinking in what I do on the computer and what sites I visit.

If you have your **"favorite"** antivirus program installed, I'm not telling you to change it. However, if you're paying for a solution that you don't know if it's fully up to the task, consider using what you have available right away.

Remember, however, that your Windows must be updated to the latest version (**[currently version 1803 from April 2018](https://support.microsoft.com/en-us/help/4099479)**).

However, if you decide that it's worth investing in a paid antivirus solution, consider the **Premium** solution from **Malwarebytes** ([available for Windows and macOS](https://www.malwarebytes.com/pricing/)).

Best regards.

{{% ads-in-article %}}


---
## Google Photos - a place for your photos
- **URL:** https://dariusz.wieckiewicz.org/en/google-photos/
- **Date:** 2017-12-26
- **Tags:** Articles, 2FA, 4K, android, backup, movies, Google Photos, Google Takeout, iOS, backup, Lightroom, Mac, macOS, Picasa, Windows, photos

### Content

Some time ago [on my blog](/en/my-alternative-to-picasa/) I touched on the topic of storing and managing a collection of photos. With the development of **Picasa** coming to an end, I decided to use **Lightroom**.

My adventure with Lightroom lasted for some time, but I always felt insecure when it came to storing photos.

<!--more-->

Hard drives can fail, just like computers. Thefts are also common, and no one wants to lose a valuable collection of photos from the last 15 years. At the same time, having photos only on one computer creates another problem if you want to show or share them with someone.

Here, **[Google Photos](https://photos.google.com)** (**Google Photos**) became an almost perfect solution.

Before I switched to **Google Photos**, I faced a **very important question**. What do I need my photos for and how much do I need their original resolution.

It may seem like a trivial question, but the choice of the final solution will affect the entire future of photo storage.

**Google Photos** offers two options for storing photos. **The first** is, of course, storing them as they were uploaded — i.e. in full, **original resolution**. Each photo takes up space in our Google account. With my collection of **200GB of photos and videos**, the 15GB basic package left no illusions that I would have to pay.

**Portable drives also cost money**. And despite the fact that it is a one-time expense, they are not the safest form of data storage. In particular, they should not be the only form of backup.

**I am not a photographer**. I do not take photos to earn money from them. In my life I have had fun with a semi-professional SLR camera, but it is not my way of life. When children appeared in my life, the number of photos began to grow logarithmically, and the basic camera became a mobile phone.

My family and grandparents are hundreds of kilometers apart, so easy sharing of photos of my grandchildren became a priority. Sending photos by e-mail became very inconvenient.

After thinking a bit more about **Google Photos' second option** - **unlimited storage** for high-resolution photos - I decided that **this is what I needed**.

{{% ads-in-article %}}

**Google Photos** in high resolution gives us **unlimited space for our photos and videos** along with the ability to quickly share with others. However, the lack of a limit comes with a price. Our photos and videos are additionally compressed.

This is not a bad thing, because in this package, photos up to **16Mpix** will not be reduced, which will allow us to print them later on A4 paper or in a larger format without any problems. **However, the photos are compressed** using a special algorithm. **Compression is practically invisible** when it comes to visible space. However, if we need to store the originals, we can always do it using other media. **Our videos are compressed to a maximum resolution of 1080p**. If our phone, camera or camcorder records photos in **4K**, unfortunately, we will lose something here.

Despite the benefits of unlimited space for photos and videos, I’ve found that **95% of users will actually be more than happy with it**.

**Google Photos** also has an app for **Android**, **iOS**, and dedicated programs for **Windows** or **macOS** to easily back up from your computer and mobile device.

**Our photos are always available online**. If we decide to change phones or computers, there’s no need to transfer them — just **log in to your Google account** and we have everything we’ve sent.

**And so I transferred my 200GB to Google Photos**. What’s more, I occasionally make an independent copy of my photos and videos from Google Photos using **[Google Takeout](https://takeout.google.com/)**, which I store on an external USB drive. And so, the first time I did it, my **200GB took up just over 85GB**. As you can see, compression does its job, but the visual quality doesn't suffer.

Although I personally decided to buy an additional **100GB package** for my Google Drive, which I also use for other purposes, most users will be able to use this solution without having to spend extra money.

However, it is important to remember that **our photos are as safe as our Google account**. In this case, having a simple password does not guarantee us security and we should consider using [**two-factor authentication (2FA)**](https://support.google.com/mail/answer/185839), which Google provides. Additionally, we should set an **alternative email address**, **phone number** and **write down (or print out) and store in a safe place the security passwords (related to 2FA)** that will allow us to regain access to the account in case something goes wrong.

I hope I can help you make a good decision when it comes to photos and videos.

**Of course, nothing in life is free**. Google's service, although free, will not allow us to store, for example, movies downloaded from the Internet, so that Google does not become a tool for spreading piracy. At the same time, something that is free must be compensated to some extent in the form of user Privacy.

Let's not leave ourselves any illusions - **nothing is free**, and in this case our payment is our Privacy. And, although **our photos and movies are ours**, let's remember that companies like Google need this type of data for their own purposes for something - for example, for internal training of their own AI algorithms for facial recognition, etc.

Despite this, Google's solution is what I have been looking for for a long time.

**Best regards.**


---
## How to download Windows 10 image (ISO)
- **URL:** https://dariusz.wieckiewicz.org/en/image-iso-windows-10/
- **Date:** 2017-10-22
- **Tags:** chrome, Developer tools, firefox, Developer tools, User-Agent, Windows, ISO, Microsoft, ISO image, Windows 11, Windows 11 ISO

### Content

How to download an ISO image directly from Microsoft servers, officially, without risk and unnecessary fiddling.

<!--more-->

One method of updating is to go to Microsoft's website to download software that will make the process easier.

> However, what if we want to install the latest version of Windows 10 from scratch, or we want to download an ISO image to burn on a DVD?

If we have a computer with **Windows**, this process is **slightly difficult** _(sic!)._

While on **Mac, Linux or Chromebook** there is no problem after going to the page below, in the case of **Windows we will not see the option to download the ISO image**, but only a tool that will allow us to update the system to the latest version.

[![Download Windows 10](01-Pobierz-Windows-10.png "Download Windows 10 page with Update now (Zaktualizuje teraz) and Download tool (Pobierz narzędzie) buttons only")](01-Pobierz-Windows-10.png)

> [https://www.microsoft.com/software-download/windows10ISO](https://www.microsoft.com/software-download/windows10ISO)

The situation is slightly easier if we have a computer with an operating system **other than Windows**, because then the page looks like this:

[![Downloading Windows 10 ISO Image](02-Pobieranie-obrazu-dysku-systemu-Windows-10-pliku-ISO.png "Downloading Windows 10 page with ISO Image option on non-Windows device")](02-Pobieranie-obrazu-dysku-systemu-Windows-10-pliku-ISO.png)

**What if we don't have a computer with a different operating system and we still want to download the ISO image?**

Nothing could be simpler, just use the **trick** below and start downloading.

**Microsoft**'s website recognizes by default what operating system we use to visit their website (including language). In this case, we should inform you that our operating system is not an updateable Windows system (Windows 7 or later). It is even easier to inform that our operating system is macOS or Linux and the matter is solved.

**How ​​to do it?**

## Google Chrome / Microsoft Edge (Chromium)

**Until now, it was enough** to install an extension in the browser, enabling a virtual change of the Operating System whose information is sent when visiting the Microsoft website.

The best tool **was** this straight from Google ([**User-Agent Switcher for Chrome**](https://chrome.google.com/webstore/detail/user-agent-switcher-for-c/djflhoibgkdhkhhcedjiklpkjnoahfmg )) changing the identification of our browser to **Safari > Mac Safari 7**.

**Unfortunately** Microsoft recently changed its website a bit and therefore browser extensions no longer work. **But nothing is lost**, because **the "User-Agent" change method still works** and can be used directly from the browser using the built-in developer options. **I already describe how to do it**.

Once on the Microsoft website, we activate developer options:

* Using the keyboard shortcut **Ctrl+F12** (or **Ctrl+Fn+F12**).
* Using the keyboard shortcut **Ctrl+Shift+I**
* From the browser menu (**three horizontal dots**) > **More tools** > **Developer tools**

A window will open on the right side of the browser, containing various elements that will seem like black magic to a layman. **But without hesitation, this is nothing complicated!**

In the developer options window:

* click on the **three dots** icon
* select **More tools** > **Network conditions**

At the very bottom of the development window, a tab with **Network conditions** will open, where:

* uncheck the checkbox next to **Use browser default**
* choose from the list **Firefox - Mac**

**Without closing** the developer tools yet, we are **refreshing** our Microsoft website. Thanks to this, we should see a page with the option to download the Windows 10 ISO image. At this point, we can close the development tools and follow the instructions on the screen.

You don't have to worry about restoring the settings in the development tools to the state they were in before the change. After closing them and refreshing the page, everything returns to the default settings.

**And now some pictorial writing - i.e. screenshots of how to perform the above activities.**

{{% ads-in-article %}}

{{% gallery %}}
[![Edge Chromium Menu more tools developer tools](01_edge_chromium_menu_more_tools_developer_tools.png)](01_edge_chromium_menu_more_tools_developer_tools.png)
[![Edge Chromium developer tools more tools network conditions](02_edge_chromium_developer_tools_more_tools_network_conditions.png)](02_edge_chromium_developer_tools_more_tools_network_conditions.png)
[![Edge Chromium network conditions user agent](03_edge_chromium_network_conditions_user_agent.png)](03_edge_chromium_network_conditions_user_agent.png)
[![Edge Chromium user agent Firefox Mac](04_edge_chromium_user_agent_firefox_mac.png)](04_edge_chromium_user_agent_firefox_mac.png)
{{% /gallery %}}

![Edge Chromium Windows 10 iso download](05_edge_chromium_windows_10_iso_download.png)

* * *

## Mozilla Firefox

**Fortunately**, in **the case of Firefox, extensions still do their job**. Just download the extension below.

[![Firefox: User-Agent Switcher (revived)](06-1-firefox-user-agent-switcher.png)](https://addons.mozilla.org/en-GB/firefox/addon/user-agent-switcher-revived/?src=search)

Then, from the upper right corner, select an Operating System other than Windows. Refresh the Microsoft website and it's ready.

[![firefox user agent switcher 2](06-2-firefox-user-agent-switcher.png)](06-2-firefox-user-agent-switcher.png)

* * *

If we have done everything correctly, we will see the option to choose the system version, language, and at the end we will get download links as below (valid for 24 hours).

[![Download links](07-Odnosniki-do-pobrania-Windows-10-Polski.png "Download links for 64-bit and 32-bit Polish Windows 10")](07-Odnosniki-do-pobrania-Windows-10-Polski.png)

Most importantly, the whole thing is completely legal, and we can burn the downloaded image on a DVD or create a USB installer using [Rufus program](https://rufus.ie).

> As of version **1803** (_Windows 10 April 2018 Update_), the ISO image downloaded from the above page can also be used for educational keys (**Windows 10 for educational customers**). There is no need to download an image from an educational institution (university) for installation.

**Regards.**


---
## How to run an app from an unidentified (unverified) developer on macOS
- **URL:** https://dariusz.wieckiewicz.org/en/run-app-from-unverified-developer-macos/
- **Date:** 2017-08-11
- **Tags:** Mac, App Store, macOS, plik dmg, Big Sur, Monterey, unidentified developer, developer cannot be verified, macOS cannot verify the developer

### Content

**macOS**, like Windows, is not limited to installing applications solely from the App Store (Windows Store in Windows). While the App Store is the primary source for finding programs for our computer, some software is only available for download directly from their developers' websites (or from GitHub), in the traditional format of a **.dmg** (or **.pkg**) file.

<!--more-->

Similarly to how it's already implemented in Windows, macOS checks applications downloaded outside the App Store for their origin and whether they are signed with a valid digital signature.

Some developers, due to limited budgets, do not place their applications in the App Store, or do not want to deal with digital signatures approved by Apple, as everything costs money. For a developer of a free application, even $99 a year is a significant amount, especially when creating it as a hobby, and not as a means of living.

{{% gallery %}}
[![Unidentified developer in macOS Big Sur](cannot_be_opened_notice_mac.png "Unidentified developer in macOS Big Sur")](cannot_be_opened_notice_mac.png)
[![Unverified developer in macOS Monterey](cannot_be_opened_because_the_developer_cannot_be_verified.png "Unverified developer in macOS Monterey")](cannot_be_opened_because_the_developer_cannot_be_verified.png)
[![Unverified developer in macOS Sequoia](Not_Opened_macOS_Sequoia.png "Unverified developer in macOS Sequoia")](Not_Opened_macOS_Sequoia.png)
{{% /gallery %}}

When you **download** an application, **open** the .dmg file, and **drag** the prepared file to your Applications folder, you encounter a problem when you first try to run it. For security reasons, macOS will prevent you from running it. While this is a good solution, if you know where the program came from (a trusted source), you still want to run it, but you can't.

## First things first

First, we need to enable the ability to run applications from **identified developers**. Yes, you read that right - **identified**.

As I mentioned above, applications can be, but don't have to be, signed with a trusted certificate. It's best to enable this option first, and then, if we still have problems, move on to the next step.

To enable the installation of applications from **identified developers**, go to **System Preferences** > **Privacy & Security**.

{{% gallery %}}
[![Privacy & Security — macOS Big Sur](security_privacy_mac.png "Privacy & Security — macOS Big Sur")](security_privacy_mac.png)
[![Privacy & Security — macOS Sequoia](security_privacy_macOS_Sequoia.png "Privacy & Security — macOS Sequoia")](security_privacy_macOS_Sequoia.png)
{{% /gallery %}}

There, after unlocking the ability to make changes (the padlock in the lower left corner in older versions of macOS), change **Allow applications from** to **App Store & Known Developers**.

## Secondly

> For macOS Sequoia, this approach won't work — [read more](#macos-sequoia).

When the system still claims that the application you downloaded is from an **unidentified developer** (or unverified, in macOS Monterey), and system settings only allow running applications from the **App Store and identified developers**, all is not lost, although we need to do a few more clicks.

You need to **open your Applications folder**.

[![applications folder](applications_folder_mac.png)](applications_folder_mac.png)

*   In the new **Finder** window, select the **Applications** folder from the left menu (this is where you moved the application from the .dmg file).
*   Find your program (in this example, **Epichrome**) and right-click on it (of course, you need to have the right-click enabled in the system - _System Preferences > Trackpad > Click & Tap_).

[![secondary click trackpad](right_click_open_mac.png)](right_click_open_mac.png)

*   Select the **Open** option.
    *   When you clicked on our application normally, you didn't have any other button besides **Cancel**, this time you also have an **Open** button.

{{% gallery %}}
[![Unidentified Developer Open Button](cannot_be_opened_notice_open_button_mac.png "Unidentified developer in macOS Big Sur with Open button")](cannot_be_opened_notice_open_button_mac.png)
[![macOS cannot verify the developer Open Button](macOS_cannot_verify_the_developer_open_it.png "Unverified developer in macOS Monterey with Open button")](macOS_cannot_verify_the_developer_open_it.png)
{{% /gallery %}}

*   And that's it. Your application should open.
    *   And the best thing about all this is that you only need to do the above steps once, because later, a normal click on the application will open it without any unnecessary messages or warnings.

{{% ads-in-article %}}

### macOS Big Sur

> November 14, 2020

In **macOS Big Sur**, application checking is done even before opening the .dmg file. If your system cannot verify the author of the application or scan it for malware at this stage, the attempt to open it will fail.

[![macOS Big Sur Opening DMG file](macOS_Big_Sur_Open_DMG_file.png)](macOS_Big_Sur_Open_DMG_file.png)

Here again, right-click on our .dmg file and select the **Open** option, then you will see a similar warning with an additional button to open our file.

[![macOS Big Sur Opening DMG file via Open option](macOS_Big_Sur_Open_DMG_file_right_click_Open.png)](macOS_Big_Sur_Open_DMG_file_right_click_Open.png)

After launching our .dmg file and dragging it to the **Applications** folder, when trying to open it, we will encounter another warning. From the available options, we can move the application to the trash or cancel the launch.

[![macOS Big Sur Opening application](macOS_Big_Sur_Open_App.png)](macOS_Big_Sur_Open_App.png)

Similarly to before, if you open your **Applications** folder in a new Finder window and right-click on your program, then select **Open**, you will have an additional option that allows you to run the program.

[![macOS Big Sur Opening application via Open option](macOS_Big_Sur_Open_App_right_click_Open.png)](macOS_Big_Sur_Open_App_right_click_Open.png)

Of course, you do this at your own risk, as these types of security measures were introduced to protect users from potentially harmful software. However, if you are sure of the program's origin, you can simply click the Open button and you're done.

{{% ads-in-article %}}

### macOS Monterey

> March 3, 2022

In addition to the above, similar steps in macOS Monterey, if your application has been blocked due to the inability to verify its creator, from the **Privacy & Security** settings you should have a prompt asking if you want to allow the application to open anyway (Open Anyway).

[![Security & Privacy, Open Anyway, Warning before Opening](security_and_privacy_open_anyway.png)](security_and_privacy_open_anyway.png)

After an additional warning, we confirm that yes, we want to run our application (**Open**).

[![macOS cannot verify the developer Open Button](macOS_cannot_verify_the_developer_open_it.png)](macOS_cannot_verify_the_developer_open_it.png)

And so our application should run without any problems now and on subsequent launches.

{{% ads-in-article %}}

### macOS Sequoia

> October 22, 2024

The next version of macOS, **Sequoia**, has finally removed the ability to right-click to run an unverified application from an unidentified developer.

[![Unverified developer in macOS Sequoia](Not_Opened_macOS_Sequoia.png "Unverified developer in macOS Sequoia")](Not_Opened_macOS_Sequoia.png)

The only option you will have when trying to run it is to confirm (**Done**) or move it to the trash (**Move to Bin**).

[![Privacy & Security — macOS Sequoia](security_privacy_macOS_Sequoia.png "Privacy & Security — macOS Sequoia")](security_privacy_macOS_Sequoia.png)

Again, you need to go to the **Privacy & Security** section in system settings where you can click the **Open Anyway** button to open without checking if the application is free from malware.

Then you will receive another dialog where you select **Open Anyway** again to open your application.

[![macOS Sequoia — Open App Anyway](macOS_Sequoia_Open_Anyway.png)](macOS_Sequoia_Open_Anyway.png)

> If you have TouchID set up, you will need to confirm your action with a fingerprint, or if you don't have one, with a password.

In this way, you can bypass system security and run your application.

**Best regards.**


---
## (My) Alternative to Picasa
- **URL:** https://dariusz.wieckiewicz.org/en/my-alternative-to-picasa/
- **Date:** 2016-06-02
- **Tags:** Software, Adobe Lightroom, Adobe Photoshop Elements, CyberLink PhotoDirector 7, digiKam, LightZone, Magix Photo Manager, Picasa, Windows Photos, Zoner Photo Studio

### Content

_I started writing the following post back in February 2016, when the Internet started screaming about another Google project being killed. This time it was a program that millions use, but Google didn't find a direct source of income from it, so it's doing what it always does... killing it._

<!--more-->

## End of Picasa

Picasa, a program for organizing and basic editing photos. Although it has not been significantly developed for some time, it has always had my approval and I have recommended it to my friends. Unfortunately, Google decided to discontinue its development and remove it - the possibility of downloading - in May 2016.

Although the program itself still works, it is worth looking for an alternative, because if something starts to break, there will be no help from anyone.

Google encourages storing photos in the cloud and using its latest application Google Photos. However, there are still people who want to store photos in a traditional way - and not only photography enthusiasts.

Since it will be difficult to convince anyone in Poland to buy _**Adobe Photoshop Elements**_ or _**ACDSee**_, and using an illegal version is out of the question, I started looking for something else - equally good, which will not be discontinued in development - although we can never be sure of that.

Another equally important option is availability on both **Windows** and **Mac** - however, this is not a necessary option.

So I searched, searched and searched. Unfortunately, but **_good and simple program is not so easy to find_** - especially if you want to transfer a user 60+ accustomed to using **Picasa** and additionally **in Polish**.

I will not write a review here, because it is best to test the program in practice. Some options that will suit me may not appeal to other users, for this reason I leave it to your discretion.

### CyberLink PhotoDirector 7 Essential - Free (Free)

[http://www.cyberlink.com/stat/product/free-zone/enu/free-software-static.jsp](http://www.cyberlink.com/stat/product/free-zone/enu/free-software-static.jsp)

**Minus:**

- No Polish language;
- Fully functional for 30 days, in a limited version, but free after that period.

### digiKam (Windows/Mac/Linux) - Free Open Source

[https://www.digikam.org](https://www.digikam.org/)

**Minus:**

- auxiliary applications running in the background

### LightZone - Free (Windows/Mac) (Free)

[http://www.lightzoneproject.org](http://www.lightzoneproject.org/)

**Minus:**

- registration on the site required to download the program

### Zoner Photo Studio Free (Windows) - Free

[http://free.zoner.com](http://free.zoner.com/)

**Minus:**

- Not a very well-known manufacturer
- Lack of Polish language
- necessary to create a Zoner account to use the program **(sic!)**

### Magix Photo Manager (Windows) - Free

[http://www.magix.com/us/free-download/photo-manager/](http://www.magix.com/us/free-download/photo-manager/)

**Minus:**

- Not a very well-known manufacturer
- Lack of Polish language
- Firebird SQL Server required for the program to work **(sic!)**
- Registration required on the manufacturer's website **(sic!)**

Finally, something I recommend due to the quality, support and available options - **even though it's not free**.

### Adobe Photoshop Elements (Windows/Mac)

[http://www.adobe.com/uk/products/photoshop-elements.html](http://www.adobe.com/uk/products/photoshop-elements.html)

**Minus:**

- price **(sic!)**
- to burn photos to a disc, you need Adobe Premiere Elements **(sic!)**

**And for more advanced users:**

### Adobe Photoshop Lightroom (Windows/Mac)

[http://www.adobe.com/uk/products/photoshop-lightroom.html](http://www.adobe.com/uk/products/photoshop-lightroom.html)

{{% ads-in-article %}}

## My choice (2016)

I tested all of the above programs (as well as a dozen others) and **didn't find an alternative** simple enough to quickly and without unnecessary explanation switch from Picasa.

For my needs I use **Adobe Lightroom**, however for a person 60+ who doesn't need so many options, I would lean towards **Photoshop Elements** if not for the fact that I would also have to buy **Premiere Elements** (_no go!_).

**There is one more option...**

## Microsoft Photos

Photos built into Windows 10, easy to use, but far from the functionality of Picasa. As you could see by looking at previous versions of Windows, here too we can't be sure that the program will make it to the next version, so the learning will be wasted.

**In the end I chose Adobe Lightroom version 5** Despite its price (version 5 is available in quite affordable options), this choice will require me to devote some more time to introduce and transfer people from Picasa. We'll see how it goes.

_Best regards_


---
## GiffGaff - get your £5
- **URL:** https://dariusz.wieckiewicz.org/en/giffgaff/
- **Date:** 2016-01-17
- **Tags:** 4G, 5G, affiliate, free sim card, GiffGaff, goodybags, golden goodybags, o2, pac code, recommendation, roaming, top-up, unlimited, EU roaming

### Content

I have been in the UK since 2010 and so far, I have gone through several mobile networks in search of the one that will suit me best when it comes to calling in the UK, the Internet in a mobile phone, but also calls to the world - and not only to Poland.

Like many Poles, I started with O2, for a short time with Vodaphone, Three UK (3), then moved to GiffGaff (which is based on O2 infrastructure as a virtual operator). As I have never been a fan of subscriptions in the UK, GiffGaff offered me full freedom and more...

<!--more-->

## About the GiffGaff network

I won't write too much about the network itself. In short, I will say that it is a virtual operator operating on O2 network - however, focused on slightly different clients - those who not only use the telephone to communicate in the UK, but also around the world. And those who **believe that they don't have to spend a lot to get a lot in return**.

You can find the detailed offer here: [https://www.giffgaff.com/offer](https://www.giffgaff.com/offer)

## How GiffGaff works - in brief

Once online, your tariff plan is divided into two types - **UK (goodybags)** and rest of the world **(balance)**.

In the UK you use a package - similar to a subscription - called **goodybags**. For the rest you have **balance** in **pounds (£)**, which you use mainly for calling abroad, and in a few cases, when calling or sending messages to additionally peremium numbers.

It's worth mentioning that most of the numbers you call use up the minutes in your **goodybags**, and currently, **all goodybags** have unlimited minutes (even the £6 a month ones). Unlimited minutes include numbers starting with **01**, **02**, **03** (with some exceptions), and **0800** and **0808**.

This is especially useful when you call a government institution, where the connection time with a consultant is not the shortest.

## GiffGaff and goodybags

**Goodybags** start from **£6** where you get unlimited minutes and texts and 1GB of internet - and so on to **£35** where you get 150GB of internet. These are **PAYG** (Pay as you go) plans, **but there are even better deals!**

[![GiffGaff Goodybags Plans](GiffGaff_Standard_Plans_2023-min16.png  "GiffGaff goodybags - Standard tariff plans")](GiffGaff_Standard_Plans_2023-min16.png)

Personally, I'm on the **£10** plan (**golden goodybags**, more on that later), where I have unlimited minutes and texts and **20GB** of internet.

Most importantly, **goodybags** does not work like subscription or **top-up** on other networks. You buy it for a **month**, but that doesn't mean that when you exhaust the package (usually the Internet), you have to tighten your belt and wait until the next month, just like in other networks. At any time **you can buy an additional, new goodybag** if you have used up your basic one in a given month.

**Additionally**, if you are a loyal customer and have your **goodybags** automatically renewed, you can count on the fact that if you use the Internet faster in a given month, you will receive an additional **+1GB** from the network (so-called **emergency**), just in case and completely free of charge. This is especially nice if our **goodybag** is renewed in a few days, then we can make it to the end without any problems.

## GiffGaff and goodybags auto-renewal

Of course, a lot of people praise subscriptions because they don't have to remember to top up their account, etc. At GiffGaff, you can set up **auto renewal on goodybags**, so you don't have to do anything - and every month you will have a new package. Just like a subscription, **but better**, because **you can stop whenever you want**, **change the size of the package** or **buy a new one** during the duration of the previous one, _if, for example, you run out of data_.

What's more, if you are a regular customer who has permanent auto-recurring (**recurring**) set, you have much better **golden** packages (**golden goodybags**) at your disposal, more on that at the end.

### 18 month plan

If you feel that the GiffGaff network is your best choice, you can commit to them for 18 months, thanks to which you will receive even more than in the **golden** plans renewed every month.

Most importantly, there is no fixed cost to your commitment. Depending on your needs, you can switch between plans from **£8** and 6GB internet, up to **£35** where you get unlimited internet. Depending on your needs, each month may be different.

{{% ads-in-article %}}

## GiffGaff - My Balance

Balance is used to top up currency in the same way as a **prepaid phone**, however, in combination with **goodybags** they are used for all paid services or calling other countries:

> Poland - **1p**/min to landlines, **5p**/min to mobile phones, **6p** text message, **30p** mms\
>ps. in the era of instant messaging **who still uses MMS?**

Detailed rates to countries around the world can be found here:\
[https://www.giffgaff.com/international](https://www.giffgaff.com/international)

And here also one advantage over other networks. If you talk to someone on the other side of the world, you don't have to worry about being disconnected when you least expect it. Here you can also set up **auto-top-up** when the amount drops below **£3**.

Of course, the balance will be used to cover our expenses when we exhaust our goodybags and we decide not to buy more before the next billing period.

Then, the following rates come into force:\
[https://www.giffgaff.com/pricing](https://www.giffgaff.com/pricing)

**But it is not everything!**

## £5 for every GiffGaff referral

Every person who joins the network (**by recommendation**) and tops up the account - **balance** - or buys **goodybags** for a minimum of **£10** when activating the card, will receive (immediately) * *£5 free** to use for any purpose in the form of a balance.

If you are interested, use my link and order a **free SIM card with home delivery** and **£5** free with your first top-up:

> [https://giffgaff.com/orders/affiliate/itdarek](https://giffgaff.com/orders/affiliate/itdarek?ggSMS=app)

Or by scanning the QR code below with your phone's camera:

![Free calls to your mates on giffgaff. And £5 free credit. Get in. Scan QR code.](giffgaff-qr-code.png)

**Please note** that if you order the card directly from the website, you will not get **£5**, as you only get it for joining the network **referred by another user**.

**Once you join,** you will also be able to recommend the network to others and both you and the person you referred **will receive £5**.

## Free £5 SIM cards from GiffGaff

Once you are onboard, you can also order cards and give them to your friends along with **£5 free** when they meet the top-up requirement for a minimum of **£10**. Then you don't have to worry about the link, because the cards are assigned from you.

## Transferring your number to GiffGaff

Of course, you can also transfer your number to GiffGaff from another network. Just get a **PAC Code** from your operator ([now you can do it via SMS! without having to call](/en/how-to-switch-mobile-network-in-the-united-kingdom/)) and start the transfer on the GiffGaff website after logging in - set the transfer day and it's ready.

**Not much effort and big savings!**

## Phones from GiffGaff

It is worth adding that GiffGaff also offers phones that **do not bind you with a contract** but only with an **installment plan** not related to your **goodybags**. You pay off your phone independently, and how much you spend on other services depends on you **and not on your contract with the mobile network**.

ps. The phones are **not sim-locked**.

> Yes, yes, I know that in Poland "theoretically" all phones are unlocked, but only "theoretically" and in Europe it is not really a "requirement".

## Roaming on the GiffGaff network

In the past, when I went to Poland, I used a Polish card to make calls. This meant carrying two phones or fiddling with cards - which wasn't pleasant, especially when you were waiting for a phone call from the UK.

Recently, especially when I'm going for a short trip, I stopped worrying about it, because I can use my goodybags for calling, sending SMS messages and the Internet.

### Roaming in the EU and data with goodybags

Until the UK was a member of the European Union, when traveling to an EU country we used the telephone as we would at home. Calls, text messages and internet were included in the goodybags package we purchased (limited after exceeding 20GB).

Unfortunately, all good things come to an end, because **"geniuses"** in the UK voted for Brexit to have plums on the willow. Now, however, they and all of us will have to pay for this "convenience".

From **August 9, 2022** (changed from November 26), within the European Union we will only have a maximum of **5GB** of internet available, even if our goodybag offers much more. If we exceed 5GB, then we will have to pay **10p/MB**, which is not cheap at all!

> The 5GB limit is imposed by the O2 network. Other networks, such as Lyca Mobile (EE network), may offer more bandwidth for similar packages.

If we intend to use data intensively in the target country, it is worth checking out the local pre-paid Internet offer, as it may be more profitable. If you have a relatively modern phone, consider an eSIM card.

---

You can find out [how much it will cost you to use your phone when traveling outside the UK here](https://www.giffgaff.com/roaming-charges).

If you want to find out [how much it costs to call abroad from the UK](https://www.giffgaff.com/index/international), this site will explain everything easily.

## Golden Goodybags

For people who benefit from the monthly renewal of goodybag packages, GiffGaff has prepared a special offer of packages called **golden goodybags**.

![GiffGaff £10 Golden Goodybag](Golden_Goodybag_10.png  "£10, 20GB data, when you repeat your goodybag")

They start from **£10** and offer unlimited calls, text messages and 20GB of internet, up to **£35** where everything is **unlimited** (with the so-called [**Fair Usage Policy**](https://www.giffgaff.com/terms#giffgaff-fair-usage-policy))

> Theoretically, Golden goodybags start at £6 and 2GB of data, but in my opinion the most optimal package is the one for £10.

* * *

I hope that I have encouraged you to try GiffGagg network, which **additionally, without any fees** offers **5G as standard**.

If so, use my referral link and order your card for free with home delivery.

[https://giffgaff.com/orders/affiliate/itdarek](https://giffgaff.com/orders/affiliate/itdarek)

![Free calls to your mates on giffgaff. And £5 free credit. Get in. Scan QR code.](giffgaff-qr-code.png)

## eSIM, WiFi calling and VoLTE

### eSIM

GiffGaff has been offering for some time the option of changing the physical SIM card to a card built into your modern phone, using eSIM technology. Thanks to this, without having to remove and insert the card into the phone, we can fully use the capabilities of our phone to support several SIM cards and switch between them as needed.

If you already have a SIM card, simply switch your physical SIM card to an eSIM via the GiffGaff app (**Account > SIM > Replace my SIM > Switch to a new eSIM**).

If you are a new user, you can order an eSIM before joining the network, after installing the GiffGaff app on your phone. For this purpose, GiffGaff has prepared a video showing how to do it.

{{< youtube acY6suWosq4 >}}

**Please note** that if you order directly from the app and not through [referral link](https://giffgaff.com/orders/affiliate/itdarek), **you will not receive your £5**.

Therefore, it is better to order a physical SIM card, collect your £5 and then move to an eSIM.

> More at: [How do I get an eSIM on giffgaff?](https://www.giffgaff.com/help/articles/how-do-i-get-an-esim-on-giffgaff)

### WiFi calling and VoLTE

GiffGaff has also started offering its users support for calling over WiFi (as well as calling over 4G - LTE). Work has been underway for several months to migrate current numbers to the new technology. According to [a post on the GiffGaff community forum](https://community.giffgaff.com/d/34049108-an-update-on-wifi-calling-and-volte/1114), 50% of numbers have already been migrated, and by the end of September 2024, if nothing stands in the way, the rest of the numbers should be migrated.

I personally was migrated around September 23, 2024 and so far everything is working fine. The new technology is noticeable when starting a phone call thanks to VoLTE. While dialing a number, the signal on the phone dropped from 5G to 3G and applications in the background experienced slowdowns, thanks to VoLTE this no longer happens.

If you are a new user, it is very likely that your card (number, even if temporary) will be prepared to support WiFi calling and when transferring a number from another network, we will also receive this option from the very beginning or within a few days of activation.

Support for WiFi calling (as well as VoLTE) is another reason why it is worth choosing the GiffGaff network.

---

If you have any questions, [**write to me**](/en/contact/), and I can help you a bit in my free time.


---
## AppCleaner - Add/Remove Apps in MacOS
- **URL:** https://dariusz.wieckiewicz.org/en/appcleaner-add-remove-apps-macos/
- **Date:** 2015-11-23
- **Tags:** Mac, AppCleaner, AppTrap, Add Remove Apps, Mac, SmartDelete

### Content

One of the pain points - or, if you prefer, the simplification of the systems with a bitten apple is the simplicity of **installing** and **removing** applications.

<!--more-->

Well, although installing mainly involves moving the program to the **Applications** folder, and removing it, moving the program to the **trash**, unfortunately that's not all.

The lack of a typical way to uninstall an application means that **garbage** from programs, that we no longer need, remains on the disk.

For some time I used the **AppTrap** program, which, working in the background, detected when I moved an application to the trash and asked if I wanted to remove additional remnants of the program.

Unfortunately, it wasn't perfect and I used it alternately with **AppCleaner**.

**Uninstalling a program** using **AppCleaner** is as easy as moving it to the trash. However, in this case, we open the program window and then move the program we want to remove into it.

![AppCleaner Main Window](appcleaner_okno_glowne.png)

AppCleaner analyzes all the leftovers that can be removed along with it. Thanks to this, we can gain valuable disk space by removing **garbage**. This is especially useful when we have an SSD drive, which is not as capacious as mechanical drives.

The latest update of the program added the option offered by **AppTrap**, i.e. SmartDelete.

![AppCleaner SmartDelete](appcleaner_smartdelete.png)

After enabling the **SmartDelete** option, the program will detect when we throw an application into the trash. At this point, the **AppCleaner** program window will appear with a suggestion whether we want to remove the remaining "garbage".

Even though I have this option enabled, I am already used to deleting programs by throwing them into the application window.

The program is **free** and you can [download it from the author's website](https://freemacsoft.net/appcleaner/).

{{% ads-in-article %}}


---
## iPhone Ringtone Converter for Mac
- **URL:** https://dariusz.wieckiewicz.org/en/iphone-ringtone-converter-mac/
- **Date:** 2014-12-11
- **Tags:** Mac, Software, converter, iPhone, iTunes, m4r, Mac, ringtone

### Content

Some time ago I prepared a simple [iPhone Ringtone Converter for Windows](/iphone-ringtone-converter-for-windows/). This time it was a time for a modification na preparation version for macOS.

<!--more-->

**A bit from previous text:**

The conversion from MP3 to M4A and later change of file extension to M4R is not something difficult for myself, however less experienced users this can be challenging.

Because of that, using various methods, I decided to prepare something, that till be working on just dropping MP3 file and double-click on specified file to ret in a short moment ready ringtone for use on our phone.

I have prepared couple COMMAND files and used for this purpose FFmpeg converter. This is the final product  from my work.

Don't worry! Whole method is based on single click on the **init.command** file.

* * *

**iPhone Ringtone Converter**  
Version **1.00** @ 2300-111214

> Change Log:
> * 1.00 - Main version

* * *

**How to use:**

Download 7z file (links below) and unpack it (If you don't have proper software, go [there](http://www.kekaosx.com/en/))

Put all your MP3 files into the main directory with other files. They may be longer than 30 seconds, later they will be cut to meet this requirement.

When MP3 files are in, double-click on the **init.command** file.

When converted, your ringtone files will be in the RINGTONE folder.

Just in case you want to hold original MP3 files, they will be placed in the TMP_MP3 folder. If you don't need them, just delete it.

Run iTunes and add the RINGTONE folder to your collection. They will be automatically detected as a ringtones. Right now, simply drag and drop it to the connected iPhone or enable automatic synchronisation.

**Any problems, just ask.**

{{% ads-in-article %}}

* * *

> If you have a problem with running **init.command** file, right click on `ffmpeg` and select Open in Terminal (doing this just once). We will get informed that the file is not from a trusted developer (do not worry!) - click Open and close the terminal. Next, run our  **init.command** in the same method, by right click and selecting Open in Terminal. Once again, on the warning message select Open.

Thank you for *FFmpeg Binary for Mac* for binaries and makers of [FFmpeg](http://ffmpeg.org) project.

**Downloads:**  
* [Version for macOS](/pobierz/iphone_ringtone_converter_mac_64bit.7z)



---
## iPhone Ringtone Converter for Windows
- **URL:** https://dariusz.wieckiewicz.org/en/iphone-ringtone-converter-for-windows/
- **Date:** 2013-05-04
- **Tags:** Software, Windows, aac, Apple, converter, easy, iPhone, iPhone Ringtone Converter, m4a, m4r, mp3, ringtone, Windows

### Content

Recently  I have been looking for a simple and easy method to convert ringtone or a song from MP3 to M4R, a ringtone format used widely in iPhones.

The conversion from MP3 to M4A and later change of file extension to M4R is not something difficult for myself, however less experienced users this can be challenging.

Because of that, using various methods I decided to prepare something, that till be working on just dropping MP3 file and double-click on specified file to ret in short moment ready ringtone for use on our phone.

I have prepared couple batch files and used for this purpose FFmpeg converter. This is the final product  from my work.

<!--more-->

* * *

**iPhone Ringtone Converter**  
Version **1.01** @ 2220-080513

> Change Log:
> * 1.01 - Fixed wrong ringtone cutting  
> * 1.00 - Main version

* * *

**How to use:**

Download 7z file (links below) and unpack it (If you don't have proper software, go [there](http://www.7-zip.org/)).

Put all your MP3 files in the main directory with other files. They may be longer than 30 seconds, later they will be cut to meet this requirement;

When done with your MP3 files, double-click on **init.bat** file;

When converted, your ringtone files will be in the RINGTONE folder;

Just in case you want to hold original MP3 files, they will be placed in the TMP_MP3 folder. If you don't need them, just delete it;

Run iTunes and "Add folder..." RINGTONE folder to your collection. They will be automatically detected as a ringtones. Right now, simply drag and drop it to the connected iPhone.

You can also drag files directly from your folder to your connected phone inside the iTunes app window.

**Any problems, just ask.**

{{% ads-in-article %}}

* * *

Thank you for Zeranoe FFmpeg for Windows binaries and makers of [FFmpeg](http://ffmpeg.org) project.

**Downloads:**
* [Version for Windows - 64-bit](/pobierz/iphone_ringtone_converter_64bit_v1_01.7z)
* [Version for Windows - 32-bit](/pobierz/iphone_ringtone_converter_32bit_v1_01.7z)



---
## Microsoft Office the old way. Classic Menu in Office 2007-2024 and 365.
- **URL:** https://dariusz.wieckiewicz.org/en/microsoft-office-the-old-way-classic-menu/
- **Date:** 2009-04-12
- **Tags:** addintools, classic menu, Classic Office Menu, Microsoft Office, UBit Schweiz, UBitMenu

### Content

During my adventures with computers, I have gone through various versions of Microsoft's Office suite. I wrote my master's thesis in **Office 2003**.

With **Office 2007**, Microsoft introduced the so-called ribbon menu, which not everyone liked. This menu is still in use in Microsoft Office up to 2024 and the 365 suite.

<!--more-->

A large group of users have become accustomed to the ribbon. New users of the Office suite do not even know that in the past, the suite was navigated completely differently.

A more experienced generation of users remembered where everything was in the "old" menu, and switching to the new ribbon required relearning. However, old habits remain and it would be good to be able to continue using them.

Over the years, various developers have created Office add-ins that restore (add) a tab in the application that allowed access to the "old" menu.

These add-ins still work today.

A large number of these add-ons require a license, however, there is one, **UBitMenu**, which is completely free for home users. Business customers can purchase a license, which ranges from £8.32 for the software and £0.54 per user. This is not an exorbitant price.

Personally, I got used to the ribbon and eventually forgot about the "old" menu, but from time to time, I look for a selected option that I know I had available. Clicking between ribbons (tabs), wasting some time to find it, then the "old" menu comes to the rescue.

All this confusion caused an increase in users of the **LibreOffice** package (LibreOffice is, in short, a slightly better OpenOffice). LibreOffice has remained with the classic menu to this day, and for good reason, because it is faster and more intuitive for my generation and older people.

**UBitMenu**, as I mentioned, allows you to add a **tab** with the classic menu known from **Office 2003** to the Microsoft Office suite. The program is cool in that it does not remove the ribbon menu, so our suite is still fully functional, which cannot be said about solutions from other companies.

{{% gallery %}}
[![Microsoft Word with UbitMenu](Microsoft_Word_with_UbitMenu.png "Microsoft Word with UbitMenu")](Microsoft_Word_with_UbitMenu.png)
[![Microsoft Excel with UbitMenu](Microsoft_Excel_with_UbitMenu.png "Microsoft Excel with UbitMenu")](Microsoft_Excel_with_UbitMenu.png)
{{% /gallery %}}

{{% ads-in-article %}}

To add a classic menu, simply close the Office programs (Word, Excel, etc.), download [**UBitMenu**](https://www.ubit.ch/fileadmin/UBitMenu/UBitMenuSetupUK.exe) from [its creator's website](https://www.ubit.ch/software/ubitmenu-languages/) and install it.

After a short while, we can re-launch Word or Excel and a new tab called Menu will appear before our eyes.

From now on, we can successfully use the Office suite using the classic menu, while also having access to the new one.

Best regards.


---
## Select your language
- **URL:** https://dariusz.wieckiewicz.org/en/language-selector/
- **Date:** 0001-01-01


### Content

If you read in **English**, please head to my **English** site.

🇬🇧 [https://dariusz.wieckiewicz.org/en/](/en/)

> Not all the posts and articles written in English are translated into Polish, hence sometimes is worth heading there and using the auto-translation button into the English language in the right-top corner of the website.

---

Jeżeli czytasz **po polsku**, przejdź na moją **polskojęzyczną stronę**.

🇵🇱 [https://dariusz.wieckiewicz.org/](/)

> Nie wszystkie moje wpisy i artykuły napisane w języku angielskim są tłumaczone na język polski, dlatego czasami warto tam wejść i skorzystać z przycisku automatycznego tłumaczenia na język polski w prawym górnym rogu strony.


---
## Site Search
- **URL:** https://dariusz.wieckiewicz.org/en/search/
- **Date:** 0001-01-01


### Content

{{< search-form >}}

{{< search >}}


---
## Your message has been sent!
- **URL:** https://dariusz.wieckiewicz.org/en/contact/sent/
- **Date:** 0001-01-01


### Content

Thank you for filling my contact form.

I will try to respond when time allows.

Thanks.

[< Back](/en/contact/)


