Mike van Riel https://mikevanriel.com Code, Design and Quality are glorious when in harmony Fri, 07 Nov 2025 06:44:51 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 /wp-content/uploads/sites/4/2016/05/cropped-WeCampAvatar-1-32x32.png Mike van Riel https://mikevanriel.com 32 32 Run PHP & Composer Without Installing Them (Using Docker) https://mikevanriel.com/2025/11/07/run-php-composer-without-installing-them-using-docker/ Fri, 07 Nov 2025 06:34:28 +0000 https://mikevanriel.com/?p=953 Want to run php and composer on any machine—without installing PHP or Composer locally? You can, by launching a disposable container that has everything preinstalled and points at your project folder.

Here’s the command:

docker run -it --rm --name php-shell --user=$(id -u):$(id -g) -v "$PWD":/home --workdir "/home" composer /bin/bash

This drops you into a bash shell inside the official composer image (which already includes PHP and Composer). From there you can run php, composer, framework CLIs, etc., exactly as if they were installed on your machine—except they never touch your host system.


What each flag does (and why it matters)

docker run Start a new container.

-it
Interactive + TTY. Lets you type commands and see output like a normal shell.

--rm
Auto-remove the container when you exit. No leftover containers to clean up. Also makes this command repeatable without having to manually clean up the container first.

--name php-shell
Gives the container a friendly name. Useful if you want to attach, stop, or inspect it later.

--user=$(id -u):$(id -g)
Run processes inside the container as your user and group (not root).
Why: Any files Composer writes (e.g., vendor/, lockfiles) will be owned by your user on the host, preventing annoying permission issues.

-v "$PWD":/home
Bind-mount your current directory into the container at /home.
Why: The container sees your project files; Composer can install dependencies into your working dir.

--workdir "/home"
Set /home as the working directory.
Why: When you land in the shell, you’re already in your project root.

composer
The image name. The official composer image bundles PHP + Composer and is maintained for this exact use case.

/bin/bash
The command to execute in the container.
Why: You get an interactive shell; from there you can run php -v, composer install, or anything else.

Windows users: run this from WSL2

Important: The command above uses $(id -u), $(id -g), and "$PWD", which are Linux shell features. On Windows, the smoothest experience is to:

  • Install WSL2 (Ubuntu, for example).
  • Open a WSL2 shell and run the Docker command from inside WSL2.
  • Ensure Docker Desktop is set to integrate with your WSL2 distro.

You’ll also get significantly better filesystem performance if your project lives inside your WSL2 filesystem (e.g., under /home/…) rather than a Windows-mounted path like /mnt/c/.... Composer touches many files; file-sharing between Windows and Docker can become sluggish with large dependency trees. Running fully inside WSL2 keeps everything fast and responsive.


Quick recipes

1) Open a PHP shell with Composer available

Use the original command and then run anything you like:

php -v
composer --version
composer install

Exit with exit or Ctrl+D.

2) Run a one-off Composer command (no shell)

If you don’t need an interactive shell, just replace /bin/bash with the composer command you want:

docker run --rm --user=$(id -u):$(id -g) -v "$PWD":/home --workdir /home composer \
  composer install --no-interaction --prefer-dist

3) Run plain PHP scripts

Use the same image; it already has PHP:

docker run --rm --user=$(id -u):$(id -g) -v "$PWD":/home --workdir /home composer \
  php your-script.php

4) Access private repositories (SSH keys)

Mount your SSH keys read-only if you need to pull from private Git repos:

docker run -it --rm --name php-shell \
  --user=$(id -u):$(id -g) \
  -v "$PWD":/home \
  -v "$HOME/.ssh":/home/.ssh:ro \
  --workdir /home \
  composer /bin/bash

5) Handy aliases

Add these to your shell profile to make it feel “installed”:

alias dcomposer='docker run --rm --user=$(id -u):$(id -g) -v "$PWD":/home -v composer-cache:/tmp --workdir /home composer composer'
alias dphp='docker run --rm --user=$(id -u):$(id -g) -v "$PWD":/home --workdir /home composer php'

Usage:

dcomposer install
dphp -v
]]>
Using Google Chrome’s Omnibar to Directly Prompt ChatGPT https://mikevanriel.com/2024/10/04/using-google-chromes-omnibar-to-directly-prompt-chatgpt/ Fri, 04 Oct 2024 11:20:39 +0000 https://mikevanriel.com/?p=944 In recent updates, Google Chrome introduced a new shortcut feature in the omnibar (also known as the address bar) to directly prompt Google’s Gemini AI using the keyword @gemini. This innovative addition allows users to interact with AI straight from the address bar without the need to navigate to a separate website.

But did you know that you can configure Chrome to do the same for OpenAI’s ChatGPT? With a small adjustment using Chrome’s SiteSearch settings, you can create your own shortcut to quickly interact with ChatGPT. In this post, I’ll show you how to set up an omnibar shortcut for ChatGPT, similar to the new @gemini feature.

What is the Chrome Omnibar?

The omnibar is Chrome’s versatile address bar, where you can type URLs, conduct searches, and more. With a bit of tweaking, you can use it to query websites or even trigger AI interactions, saving time and enhancing productivity.

Creating Your Own @chatgpt Shortcut in Chrome

By leveraging Chrome’s built-in SiteSearch feature, you can set up a quick-prompt to directly search or interact with ChatGPT. This setup lets you bypass extra navigation and trigger ChatGPT queries by typing @chatgpt -followed by your prompt- directly in the omnibar.

Here’s how to configure this shortcut:

  1. Open SiteSearch Settings:
    • Right-click on the omnibar (address bar) and select Manage search engines and site search from the context menu.
  2. Add a New SiteSearch Entry:
    • Scroll down to the Site Search section and click Add.
  3. Fill in the ChatGPT Shortcut Details:
    • In the dialog box, input the following:
      • Search engine: ChatGPT (or any name you like).
      • Shortcut: @chatgpt (or simply chatgpt if you prefer).
      • URL with %s in place of query: https://chat.openai.com/?q=%s.
    This setup will allow you to type @chatgpt followed by your query directly in the omnibar. For example, typing “@chatgpt What is AI?" will take you straight to ChatGPT, where it will process the question.
  4. Save the Entry:
    • Click Add to save the new ChatGPT entry.

How to Use the New @chatgpt Shortcut

Once you’ve configured the shortcut, using it is simple:

  1. Open a new tab in Chrome.
  2. Type @chatgpt, hit space or tab, and enter your prompt (e.g., @chatgpt What is the difference between AI and ML?).
  3. Press Enter and the browser will open ChatGPT, automatically entering your query into the chat for a quick response.

Final Thoughts

Google Chrome’s introduction of the @gemini feature is a significant step toward integrating AI interactions directly into the browser. However, with a simple SiteSearch configuration, you can also create your own shortcut for ChatGPT using the @chatgpt keyword. This setup will let you prompt ChatGPT straight from the omnibar, making your browser even more powerful.

Configure your own ChatGPT shortcut today, and start enjoying the convenience of quick AI queries from your browser’s address bar!

]]>
When Bluetooth devices won’t connect anymore https://mikevanriel.com/2024/08/16/when-bluetooth-devices-wont-connect-anymore/ Fri, 16 Aug 2024 07:20:21 +0000 https://mikevanriel.com/?p=826 If you’ve ever experienced Bluetooth issues on your Windows PC, you’re not alone. I recently faced a frustrating problem where my Bluetooth devices refused to connect, no matter what I tried. One day it worked, and the next it didn’t. The only difference I could figure out, was that my Bluetooth drivers had updated to a newer version the day before. After some digging, I discovered the solution—and it’s simpler than you might think.

The Hidden Device Problem

Windows has a feature in Device Manager that hides certain devices by default. This can be problematic when dealing with Bluetooth, as your system might still be referencing outdated or old device drivers, which can interfere with your current Bluetooth connections.

Here’s how to fix it:

Step 1: Show Hidden Devices

  1. Open Device Manager: Right-click on the Start menu and select “Device Manager.”
  2. Enable Hidden Devices: In Device Manager, click on the “View” menu at the top and select “Show hidden devices.” This will reveal additional devices that aren’t normally visible.

Step 2: Remove Bluetooth Devices

  1. Locate Bluetooth Devices: Scroll down to the “Bluetooth” section.
  2. Uninstall Devices: Right-click on each device listed under Bluetooth and select “Uninstall device.” Make sure to remove all devices, including the hidden ones.

Step 3: Restart and Reconnect

  1. Restart Your PC: This will allow Windows to reinstall the necessary Bluetooth drivers.
  2. Re-pair Your Devices: After the restart, go ahead and re-pair your Bluetooth devices. They should now work without any issues.

Conclusion

By revealing and removing hidden Bluetooth devices in Device Manager, you can resolve connectivity issues on your Windows PC. It’s a quick fix that can save you a lot of frustration. If you’re experiencing similar problems, give this method a try—it worked for me.

]]>
Resolving ImagePullBackOff with Registry Authentication Issues https://mikevanriel.com/2024/05/17/resolving-imagepullbackoff-with-registry-authentication-issues/ Fri, 17 May 2024 15:26:08 +0000 https://mikevanriel.com/?p=820 Encountering an ImagePullBackOff error in Kubernetes can be a frustrating experience, especially when it’s due to a 401 error from a Docker Registry. This guide will walk you through the steps to diagnose and resolve this issue by updating your registry credentials.

Diagnosing the ImagePullBackOff Error

When a pod fails to pull an image, it often results in an ImagePullBackOff error. To confirm this and get more details, you can inspect the pod using the describe command:

kubectl describe pod <pod_name>

Look for events indicating a 401 error while pulling from Docker Registry. This typically means there’s an authentication issue with the credentials provided in the imagePullSecrets.

Inspecting and Decoding the ImagePullSecrets

The next step is to inspect the secret referenced by the imagePullSecrets variable in the associated Deployment. This secret contains the credentials Kubernetes uses to pull images from the registry. Extract and decode it with the following command:

kubectl -n redirector get secret gitlab-registry -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode

This will output the docker registry’s config content, which you can then review for accuracy.

Manual Testing using Docker Login

Using the credentials from the decoded secret, attempt to log in to -for example- the GitLab registry manually. This helps confirm whether the credentials are valid:

docker login registry.gitlab.com

If the login fails, it’s clear that there’s an issue with the credentials.

Generating a New Personal Access Token

To resolve the credential issue, you’ll need to generate a new Personal Access Token in GitLab:

  1. Go to your GitLab account settings.
  2. Navigate to Access Tokens.
  3. Create a new token with the read_registry scope for registry access.

It is recommended to put an expiration date on the token and make it as narrow as possible using just the read_registry scope, doing this will benefit the security of your system.

Updating and Encoding the Docker Configuration

Once you have the new token, replace the old credentials in the .dockerconfigjson with the new token. Then, base64 encode the updated .dockerconfigjson:

echo -n '{"auths":{"registry.gitlab.com":{"username":"<username associated with access token>","password":"<access token>"}}}' | base64

Updating the Kubernetes Secret

Now, update the Kubernetes secret with the acquired access token. This ensures Kubernetes uses the updated credentials for pulling images:

kubectl edit secret <secret-name>

Once opened, this allows you to set the .dockerconfigjson in the data fields of the secret that we acquired above.

Restarting the Pod

Finally, delete the pod to let Kubernetes recreate it and retry pulling the image with the new credentials:

kubectl delete pod <pod_name>

Normally this step is superfluous as Kubernetes has already picked up on the change and retried the pod before you get the chance to perform the step above.

Conclusion

By following these steps, you can resolve the ImagePullBackOff error caused by a 401 error from a Docker Registry. Kubernetes should now be able to pull the image successfully, allowing your pod to start without issues.

If you want to know more on how you can pull containers from a private registry using kubernetes, you can also check the official support page at https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/.

]]>
More flexible Figma Components: Slotting https://mikevanriel.com/2024/02/15/more-flexible-figma-components-slotting/ Thu, 15 Feb 2024 07:19:53 +0000 https://mikevanriel.com/?p=808 Slotting in Figma is a practical technique that simplifies working with complex designs by equipping components with flexible “slots”. These slots are essentially predefined spaces within a component where other components or elements can be inserted. This is particularly useful for creating customizable and reusable UI elements such as buttons, cards, and navigation menus.

A screenshot showing the “swap instance” action in Figma that is at the core of the slotting technique

The reason for using slotting is that it enables designers to quickly generate design variants without the need to manually adjust each element. It promotes consistency in the design while offering flexibility for adjustments.

To apply slotting in Figma, follow these steps:

  1. Establish a Base Component: Begin by designing a base component that serves as your main template, like a button or card.
  2. Define Slots: Within this base component, identify specific areas for other components that you might want to add or adjust later. Use rectangles or frames as placeholders. It’s crucial that these placeholders are set up as components themselves because you’ll be expected to replace the slot – or placeholder – with another component that represents the actual content later on. In Figma, it’s not possible to add extra child components to an instance of a component, so it’s important to define enough slots in a base component so that you can accommodate all the content you want in each instance.
  3. Develop Component Variants: Create separate components intended to be placed in the defined slots or placeholders. This step is essential for preparing the variable elements you want to be able to swap within your base component.
  4. Use ‘Swap Instance’: Utilize Figma’s “Swap Instance” functionality to easily replace a component within an instance. This facilitates seamless integration of new elements within the structure of your base component, maximizing the flexibility and adaptability of your design.

You can watch the following video -by Figma- on YouTube to see this technique in action:

]]>
Getting a list of week numbers between two dates https://mikevanriel.com/2022/01/08/getting-a-list-of-week-numbers-between-two-dates/ https://mikevanriel.com/2022/01/08/getting-a-list-of-week-numbers-between-two-dates/#comments Sat, 08 Jan 2022 09:41:14 +0000 https://mikevanriel.com/?p=790 Recently, I was working on a PHP application that needed to show weekly summaries in the period of one month. Then, January came and I found myself looking at 48 weeks instead of the expected 4 to 5.

This is the piece of code that I used in a Twig template.

{% set weeks = firstDayOfMonth|date('W') .. lastDayOfMonth|date('W') %}

What the above does, is to use a date called firstDayOfMonth (containing January 1st), get the week number and use Twig’s range operator to count up to the week number belonging to the lastDayOfMonth (January 31st).

Looks good, right? You’d expect January 1st to be in the first week of the year and it would count up to week number 5. Or not?

Unfortunately, and I knew this, January 1st 2022 was in week number 52 of 2021. What happened next was that Twig’s range operator would count down from 52 to 5, which is definitely the opposite of what I would want to show!

The fix? What I should have done was to move the business logic outside of twig, and leverage PHP’s native, and incredible, DatePeriod class. With it, I can get a series of dates for every week between the start of the month and the start of the next month:

$period = new DatePeriod(
    $startOfMonth, 
    new DateInterval('P1W'), $startOfMonth->modify('+1 month')
);

Sidebar: if you are doing some serious Date/Time magic, consider looking into https://period.thephpleague.com/. You’ll thank me later.

And with this list of dates, I can loop through each and convert them to a week number. This will automatically wrap around the year, and thus provide a list matching 52, 1, 2, 3, 4 and 5 (yes, January 2022 is spread across 6 weeks!).

$weekNumbers = array_map(
    static fn(DateTimeInterface $startOfWeek): int => (int)$startOfWeek->format('W'),
    iterator_to_array($period)
)

Sidebar: Please take note of the typecast to int and the use of iterator_to_array to ensure we can map an Iterator of DateTime objects into an array of integers.

And there you have it, a neat list of week numbers as integers given a period!

]]>
https://mikevanriel.com/2022/01/08/getting-a-list-of-week-numbers-between-two-dates/feed/ 1
A new talk in the making? (User) Stories for Developers https://mikevanriel.com/2021/04/15/a-new-talk-in-the-making-user-stories-for-developers/ Thu, 15 Apr 2021 05:21:11 +0000 https://mikevanriel.com/?p=779 At Ingewikkeld, we hold internal presentations to share knowledge between us. Recently, it was my turn; I wanted to tell a story, on stories.

In our field of Software Engineering, one of the hardest things (besides naming) is to break down work into manageable pieces of work. In this presentation, I demonstrated how you take a complex feature request, and break it down into User Stories that are considered SMART.

Writing a good User Story is not as easy as it seems to be, because as an author you need not only write down what you would like, but also:

  1. How it should work
  2. What it should look like
  3. What errors may be presented
  4. Where else it may touch the system (if it does; I recommend not)

All the while, you aim to keep a User Story limited in scope. It’s a nice balancing act.

It proved far too easy to fill a whole hour on this topic; so I decided to write an entire talk and bring it to you at a User Group or other meetup soon.

Meanwhile, if you would like certain content to be included, have questions or just want to share a funny anecdote from your own experience: Use the comments, Luke.

Until next time!

]]>
‘master’ has always been a poor branch name https://mikevanriel.com/2020/07/07/master-has-always-been-a-poor-branch-name/ Tue, 07 Jul 2020 04:45:51 +0000 https://mikevanriel.com/?p=761 Recently I was scrolling through my twitter timeline when I encountered this tweet by Fabien Potencier:

Fabien eloquently describes something that suddenly clicked with me; master has always been a poor choice of name.

With the current state of affairs, people have been reviewing the names that we use on a daily basis. And the word master is contentious depending on the context in which you use it.

In the context of GIT and how the name itself can be considered harmful is much better described in this blog post: https://boleary.dev/blog/2020-06-10-i-was-wrong-about-git-master.html; I am going to zoom in on Fabien his tweet and why I think this alone would be a good enough reason, even while considering the potential harm that the meaning of the name does.

What’s wrong with ‘master’?

Consider your favourite branching strategy, I don’t think it even matters much which one that is, and then consider what the name master means in the bigger picture and how it relates, or doesn’t, to the other branch names.

As an example, I am going to take a look at how we have done it in phpDocumentor. In phpDocumentor, we use trunk-based development and the following branching strategy:

  • we commit everything for the newest release to the mainline, currently still called ‘master’
  • For every minor release, we make a new branch with the name of that release. For example 3.0 (to be released)
  • For every build release, we create a tag with the build number from the mainline.
  • When working on long-living branches for a specific larger feature (try to avoid this!) we prefix the branch with feature/ and provide a describing name for the feature that we are making.

Now, take a step back and let’s look at the names more closely: master, 3.0, 3.0.1 and feature/my-awesome-contribution. Except for master, all these names are expressive and describe what the branch is about.

This is the whole point: master as a term is meaningless in your project.

Ok, then what?

I challenge you to find a better name for that branch, a name that truly expresses what it is in it. Github floats the name main; which, if you ask me, is from a point of expressiveness equally bad. Surely better names are to be had?

For phpDocumentor, we have settled with Fabien’s strategy for Twig. We have started to rename our master branches to match the major version that we are working on followed by a .x to indicate it is the latest for that version. So, as an example: we are now working on phpDocumentor version 3; so master will become 3.x.

Caveat: we are rolling out this change gradually to monitor the effect on various tools that we have and tools used by the community.

There have been various suggestions that came by, including trunk (from the good old SVN days), production for branches to go directly to production, default as a one-to-one replacement and many more. Which you pick is up to you; I can only recommend picking something that is expressive and really describes what is on that branch.

Going forward

I know this change will inconvenience people. Some projects have their tooling based on the master terminology or depend on other packages’ master branch (don’t if you can avoid it!). That is a price that we need to pay for improving our work and our world.

Update: on Twitter Andreas Heigl mentioned that some tools indeed have issues with the absence of a master branch. As for the status of Composer, I can refer to this blog post by Jordi: https://blog.packagist.com/composer-and-default-git-branches/

As from this day, I intend to make an effort to name every branch with clarity and steer away from the name master whenever I have influence over it. I know I will stumble and fail in the future, but I will persevere. As this change will make branch naming clearer, will hurt fewer people and I have good hopes that in the future we will not use a default name anymore but when you start a new repository, you will be asked:

“What is the name of your first branch?”

]]>
Three ways to switch between views in Blender, without using a NumPad https://mikevanriel.com/2020/06/06/three-ways-to-switch-between-views-in-blender-without-using-a-numpad/ https://mikevanriel.com/2020/06/06/three-ways-to-switch-between-views-in-blender-without-using-a-numpad/#comments Sat, 06 Jun 2020 07:23:40 +0000 http://mikevanriel.com/?p=754 I generally work on my laptop a lot, including using Blender, and as most laptops do; this one does not have a NumPad. Most tutorials that you find on the internet presume you do; if you are like me you struggle with not being able to easily switch between views using the NumPad or to Frame the selected element using NumPad+Period.

There are good alternatives for this situation and I will give you three options.

Emulate NumPad

This is the most frequent suggestion that I encounter, and the one I like least. In your blender settings, there is an option called ‘Emulate NumPad’. What this option does is it will allow you to use your regular numerical keys in the top row of your keyboard as if they were your NumPad’s numerical options.

The option to emulate your NumPad is in the Input category of the Blender Settings

Sounds good, doesn’t it? Except that the ‘1’, ‘2’ and ‘3’ are easy ways to switch between Vertex, Edge and Face select! I use these keys all the time to easily switch between these select modes so losing them is not an option for me.

Luckily, there is more.

Using the Mouse

I think I stumbled on this one by accident and it is actually quite a nifty trick. When you hold Alt and then drag with your middle mouse button, the view will rotate to an orthogonal view in that direction. So, if you drag horizontally, it will rotate between Right, Back, Left and Front view. And if you drag vertically it will rotate between Top, Front, Bottom and Back view.

The confusing bit for me, is that which orthogonal view you end up in is dependent on the rotation of your User Perspective; this feels a bit unpredictable to me and frequently I have to make multiple swipes before I end up in the view that I wanted.

But what about Option 3?

Pressing the Backtick (`)

Blender introduced Pie Menus, by default, in version 2.8; and these have been a big game-changer for me. Especially when it comes to using the laptop and switching between views.

When you press the Backtick button (`); blender will open a Pie menu that provides the means to easily switch between different views and allows you to Frame your selected item when you don’t have a NumPad, although it eludes me why it is called View Selected in this menu while NumPad+Period is called Frame Selected.

This is what the Backtick Pie Menu looks like.

This is it, the holy grail of switching betweens views as far as I am concerned. Even when I do have a NumPad available, I have become so accustomed to using this option that I keep using it.

As a last mention, in case you did not figure this out already: do you see the numbers with each item of the Pie Menu? You probably guessed it, it is a shortcut that you can use!

So instead of mousing to the item in the Pie Menu, I frequently just Press Backtick and then 3 instead of NumPad+Period; or, for example, Backtick then 7 instead of NumPad+1.

I hope you enjoyed this tip and happy blendering!

]]>
https://mikevanriel.com/2020/06/06/three-ways-to-switch-between-views-in-blender-without-using-a-numpad/feed/ 1
Designing stories in (roleplaying) games https://mikevanriel.com/2019/08/13/designing-stories-in-roleplaying-games/ Tue, 13 Aug 2019 15:51:26 +0000 http://mikevanriel.com/?p=747 Some time ago my friend Jhon and I spoke through WhatsApp after having spent an enjoyable evening in a café. There we dwelled on various topics including one of our favourites: Dungeons and Dragons, or more specifically: writing good stories for our roleplaying campaigns.

After we parted I recalled two techniques that I particularly like when crafting stories:

  1. The Snowflake Technique
  2. Replacing ‘and’ with ‘therefore’ or ‘but’

The Snowflake Technique

The Snowflake Technique, invented by Randy Ingermanson, is used when writing novels to quickly outline your story’s structure. The basic idea behind this is that you guard yourself against meandering in your storyline. And providing hooks and handles to write your story on through a concise outline.

For a detailed explanation on the Snowflake Technique, you can read more in this blog post: http://selfpublishingadvice.org/writing-how-to-use-the-snowflake-technique-to-write-a-novel/. I will provide a summary so you can determine if it might suit you.

What you want to accomplish is to get a central idea or concept, that grows and branches as a snowflake does. You can follow these six steps to craft your outline:

  1. Write a one-sentence summary, this represents the big picture of your entire story summed up into a single sentence
  2. Expand the summary of your book into a paragraph containing three disasters and one ending. Good examples can be found on the back cover of many books.
  3. Develop your characters; where each main character needs a name, a summary of their storyline, their goal, their conflict, and their epiphany.
  4. In the paragraph you wrote in step 2, you had one sentence for each disaster and a sentence for the ending. Expand each sentence into a paragraph of their own.
  5. Expand each character with every bit of background you would like to give them.
  6. Expand the plot even further, take each paragraph you wrote in step 4 and expand that to fill a page. Here you start describing the scenes for each specific plot point.

 Once you have followed these steps you have 4 pages worth of scenes and major plot points. At this point, you can give those more body and write the events for your scenes. For help with this, check out our second technique.

Replacing ‘and’ with ‘therefore’ or ‘but’

I am not sure whether this technique has a formal name but I encountered it first in the Witcher 3’s side-quest plot structure; I later learned that the TV series South Park used the same technique first.

The premise of this technique is that as an author you run the risk of writing a story as a logical sequence of events. Events happen one after another and can result in a meandering experience for the reader, or player, as the story progresses steadily. Even if you write one interesting event after another, it is still emotionally linear if you can string all events together with the phrases: ‘and’ or ‘and then’.

Now, whenever you are inclined to write the phrase ‘and then’: replace it with ‘therefore’ or ‘but’ and follow that train of thought. What happens now is that with ‘therefore’ you are inclined to write a new event that is a logical consequence of the prior (instead of a continuation). With ‘but’, things become interesting because you introduce a downward beat or conflict.

Especially when you alternate the phrases ‘therefore’ and ‘but’, your scenes become more varied and complex because the emotional range is much wider. The up-beats are more rewarding as the reader is more engaged due to the variation.

I love both techniques and believe one complements the other perfectly. I will be experimenting more with these techniques in my D&D and digital stories I design. I hope you do too and find them equally fulfilling.

]]>