Compare commits

..

1 commit

Author SHA1 Message Date
9f367cb9b2 begin working on animation support 2025-03-12 16:38:23 +01:00
97 changed files with 254 additions and 605 deletions

View file

@ -8,7 +8,7 @@ trigger:
- main
steps:
- name: docker-default
- name: docker
image: plugins/docker
settings:
registry: git.riksolo.com
@ -18,30 +18,4 @@ steps:
- latest
- ${DRONE_COMMIT}
password:
from_secret: dockertoken
- name: docker-rblicht
image: plugins/docker
settings:
registry: git.riksolo.com
username: riksolo
repo: git.riksolo.com/${DRONE_REPO,,}
build_args:
- SITE=rblicht
tags:
- latest-rblicht
- ${DRONE_COMMIT}-rblicht
password:
from_secret: dockertoken
- name: trigger docker-compose release
image: plugins/downstream
settings:
server: https://drone.riksolo.com
token:
from_secret: drone_token
repositories:
- RikSolo/docker-compose
depends_on:
- docker-default
- docker-rblicht
from_secret: dockertoken

View file

@ -1,42 +0,0 @@
name: Build
on: [workflow_dispatch]
jobs:
Deploy:
runs-on: docker
container:
image: ghcr.io/catthehacker/ubuntu:act-latest
steps:
- name: Install LFS
run: |
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
apt-get update
apt-get install -y git-lfs
git lfs install
- name: Checkout
uses: actions/checkout@v4
with:
lfs: 'true'
- name: Docker Login
run: |
docker login -u riksolo -p ${{secrets.CONTAINER_REGISTRY_TOKEN}} git.riksolo.com
- name: Build and push
run: |
docker build -t git.riksolo.com/riksolo/eleventy-riksolo-com:latest -t git.riksolo.com/riksolo/eleventy-riksolo-com:${{github.sha}} .
docker push git.riksolo.com/riksolo/eleventy-riksolo-com:latest
docker push git.riksolo.com/riksolo/eleventy-riksolo-com:${{github.sha}}
docker build --build-arg SITE=rblicht -t git.riksolo.com/riksolo/eleventy-riksolo-com:latest-rblicht -t git.riksolo.com/riksolo/eleventy-riksolo-com:${{github.sha}}-rblicht .
docker push git.riksolo.com/riksolo/eleventy-riksolo-com:latest-rblicht
docker push git.riksolo.com/riksolo/eleventy-riksolo-com:${{github.sha}}-rblicht
- name: Trigger Compose Deploy
uses: https://github.com/fjogeleit/http-request-action@v1
with:
url: ${{ vars.DOCKER_COMPOSE_DEPLOY_URL }}
method: 'POST'
customHeaders: '{"Content-Type": "application/json", "Authorization": "token ${{secrets.FORGEJO_TOKEN}}"}'
data: '{"ref": "${{forgejo.ref}}"}'

View file

@ -0,0 +1,65 @@
name: Build
on: [workflow_dispatch]
jobs:
Deploy:
runs-on: ubuntu-latest
steps:
- name: Start webhook
if: ${{always()}}
continue-on-error: true
uses: fjogeleit/http-request-action@v1
with:
url: ${{vars.NODE_RED_WORKFLOW_STARTED_URL}}
data: '{"job": ${{toJSON(job)}}, "gitea": ${{toJSON(gitea)}}}'
- name: Install LFS
run: |
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
apt-get update
apt-get install -y git-lfs
git lfs install
- name: Checkout
uses: actions/checkout@v4
with:
lfs: 'true'
- name: Docker install
run: |
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -yqq ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -yqq docker-ce docker-ce-cli containerd.io
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker Login
uses: docker/login-action@v3
with:
registry: git.riksolo.com
username: riksolo
password: ${{secrets.CONTAINER_REGISTRY_TOKEN}}
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: git.riksolo.com/riksolo/eleventy-riksolo-com:latest , git.riksolo.com/riksolo/eleventy-riksolo-com:${{github.sha}}
- name: Completion webhook
if: ${{always()}}
continue-on-error: true
uses: fjogeleit/http-request-action@v1
with:
url: ${{vars.NODE_RED_WORKFLOW_COMPLETE_URL}}
data: '{"job": ${{toJSON(job)}}, "gitea": ${{toJSON(gitea)}}}'

View file

@ -1,9 +1,6 @@
FROM node:22
WORKDIR /usr/src/app
ARG SITE=default
ENV SITE=$SITE
COPY package*.json ./
RUN npm install
ADD . .

View file

@ -1,8 +0,0 @@
export default function () {
return {
title: process.env.SITE === "rblicht" ? "RBLicht" : "Rik Berkelder",
url: process.env.SITE == "rblicht" ? "https://rblicht.nl" : "https://riksolo.com",
author: "Rik Berkelder",
site: process.env.SITE || 'default'
};
}

5
content/_data/site.json Normal file
View file

@ -0,0 +1,5 @@
{
"title": "Rik Berkelder",
"url": "https://riksolo.com",
"author": "Rik Berkelder"
}

View file

@ -2,7 +2,7 @@
slug: "grandma3-fader-feedback-2024-05-04"
title: "GrandMA3 Fader Feedback Plugin"
date: "2024-05-04"
modified: "2025-12-05"
modified: "2024-05-04"
description: "A free MA3 LUA plugin to provide per-fader feedback over OSC"
---
You might have used the new OSC features in GrandMA3 to connect a MIDI controller to get some extra faders on your system. In my experience, this works quite smoothly. You then might have wanted to go extra fancy and tried to hook up the OSC that MA3 sends you back to make your motorized faders work, only to find out that, for some reason, it doesn't send feedback per fader, only per sequence, which is difficult to map to physical faders as you move things around.
@ -13,7 +13,7 @@ The plugin worked, but was kind of messy, so I rewrote the plugin to a point whe
It's not the fanciest thing out there. there's no fancy GUIs for your settings, just a couple of variables to tweak and then never think about again. The upside of this is that the plugin is very small and light-weight.
You can download the plugin (along with any others I've made) [over here](https://git.riksolo.com/RikSolo/GrandMA3-Plugins/releases/tag/latest).
You can download the plugin [over here](https://git.riksolo.com/riksolo/GrandMA3-Plugins/releases).
# Installation & Usage
1. Download the plugin from the link above.
@ -35,7 +35,7 @@ You can download the plugin (along with any others I've made) [over here](https:
7. Open the plugin back up, select the first (and only) line in the table, and hit the Edit button on the bottom of the window.
8. Change the variables at the top of the plugin to your liking. There are comments above each one to tell you how they work.
9. Now run the plugin.
MA3 should start sending feedback for the executors you configured in the plugin file. The OSC addresses are the same as the ones you would use to send OSC into MA# (using the current page). So, for example, the feedback for fader 202 would be sent to `/Page/Fader/202`.
For faders, the plugin will send a Float value between 0.00 and 1.00. For buttons, a value of 0 or 1 will be sent.

View file

@ -1,36 +0,0 @@
---
slug: ma3-tip-conditional-recipes
title: "MA3 Tip: Customizing Shows On The Fly Using Conditional Recipes"
date: "2025-09-11"
modified: "2025-09-11"
description: "Easily adapting GrandMA3 showfiles to different situations by bulk-toggling Recipe lines based on tags."
---
Touring with a super detailed, highly programmed light show is great, until you find yourself having to adapt to more limited venues than anticipated.
I found myself facing this problem earlier this year. A band I've been working with had mostly been doing big one-off festival shows, and not a huge amount per year. With those circumstances, it wasn't a big problem for me to manually go over the showfile for every show and fixing things that didn't really work with each festival rig.
Until they booked a two week club tour through Europe, and while it was a big step for the band, the variety of venues ranged from tiny 100-capacity music places to the mainstage of a festival with 40,000 sold tickets.
Spending a couple of hours per show doing previz would be possible, but I kept making more or less the same substitutions, which left me wondering if I could lighten that workload.
## The easy option, and the engineering perspective
The first thought was to just build a second "minimal" showfile, for very small rigs. This would be a lot easier to scale up, but it would mean having two base files to keep up to date and program new tracks into. I absolutely hate doing repetitive work though, so keeping two separate showfiles up to date sounds like a pain.
DRY (don't repeat yourself) is one of the first things hammered into you when you're learning computer programming. If you notice you're writing the same code multiple times, it means you can probably simplify something, or extract it into a reusable bit of code, so that when you change some part of it, it updates anywhere. A great example of DRY in lighting programming would be using presets in your show, instead of hardcoding values into every cue. So I started thinking if I could come up with a more elegant solution for my situation.
## The elegant solution
The entire show has been programmed using recipes, and when I was thinking this problem through, tags were recently added into the MA3 software. I noticed that a Tag field was also added to the recipe lines I started wondering if I could bulk edit recipe lines that have a tag. And as basically any question about doing things in MA using commands, the answer was "of course!"
I ended up with the following syntax:
`
Set Sequence 1 Thru Cue 1 Thru Part Thru.Thru Property "enabled" 0 if #[Tag 'No Sides']
`
This disables any recipe line in any cue in any sequence as long as it has a certain tag. change the 0 for a 1 and it enables it. So I created a few tags ("No Sides", "No Floor Spots", "No Floor Washes", and so on), then went through the show, adding additional programming for these situations. Then I just had to create a couple of simple macros to toggle the recipe lines on and off, and I was left with an on-the-fly configurable showfile to adapt to wildly differing show scenarios.
## Takeaways and other uses
Being able to mix and match multiple options also lets me make sure to still maximize what I'm doing with the parts of a rig that are there. Had I chosen to go with a "minimal" showfile, using it when I don't have washes on the floor would also mean losing any cool stuff I was doing with the side lights, or having to manually program it back.
This technique has saved me several hours per gig, most of which wouldn't have been paid either.
This trick can be very useful when you're not touring too. I've also started using the `If Tag` technique in my busking showfile. For example for enabling/disabling certain groups in my LOS-inspired system.

View file

@ -1,46 +0,0 @@
---
slug: "grandma3-osc-keys"
title: "GrandMA3 OSC Hardkeys Plugin"
date: "2025-12-05"
modified: "2025-12-05"
description: "A free MA3 LUA plugin to emulate key presses as if they were entered on a console or command wing"
---
Back when I decided to invest in some MA hardware of my own, I only had budget for a command wing at most. At the time MA2 was already more or less discontinued, and MA3 wasn't really ready to be used on shows yet. So, instead of a command wing, which would lock me in MA2 or MA3, I decided to buy a GrandMA3 OnPC 2port node to unlock my parameters, and build my setup around that.
That setup started out with a little midi controller for faders, and using the keyboard of my laptop to do my programming using keyboard shortcuts. Shortly after, I custom-built a keyboard to enter MA's specific keyboard shortcuts with single key presses. This was a big improvement, but working through keyboard shortcuts had it's problems. One big nuisance was constantly having to switch keyboard shortcuts on and off if I wanted to do different things, and they buttons would still do random other actions if programs other than MA3 OnPC were currently highlighted.
I figured out pretty early on that it would be aMAzing to be able to trigger MA's specific programming keys through OSC, but I never figured out a way to do so, until now!
I present to you: the MA3 OSC Keys plugin.
It works quite simply. First, it creates a block of 10 blank quickeys, generally somewhere out of the way. It then assigns these 10 quickeys to 10 executor buttons (also somewhere out of the way, and configurable). When the plugin is called with a command, such as "STORE press", it figures out the first available quickey slot. It then sets it's keycode to STORE, and "presses" it's corresponding executor button. When the plugin then receives a "STORE release" command, the executor button is "released" and the quickey slot is marked as free. This makes it so you can press and hold a number of keys in various overlapping sequences without any collisions or needing a separate quickey and executor for each possible keycode.
You can download the plugin (and any other ones i've made) [over here](https://git.riksolo.com/RikSolo/GrandMA3-Plugins/releases/tag/latest).
> **Note:** This is the very first iteration of the plugin, and it's not been tested very thoroughly yet. Things are bound to change or need fixing, so keep an eye on this page for updates.
# Installation & Usage
1. Download the plugin from the link above.
2. Take both of the files of the "grandma3-plugins/OSC Keys" folder and put them where you normally put your MA3 plugins
- If you're not sure where that is, your best choice is probably on whichever USB stick you also keep your showfiles, the folder will be `/ma/ma3_library/datapools/plugins`
3. Open up MA3
4. Edit an empty slot in your Plugins pool in MA3, hit the "import" button on the bottom of the dialogue, and find the plugin.
5. If you haven't gotten an OSC input set up yet, create one:
- In the MA3 menu, go to "In & Out", then into the OSC tab
- Create a new OSC entry with the following settings:
- Port: What port to listen on.
- Receive: Yes
- Receive Command: Yes
6. Open the plugin back up, select the first (and only) line in the table, and hit the Edit button on the bottom of the window.
7. Change the variables at the top of the plugin to your liking. There are comments above each one to tell you how they work.
8. Run the plugin once to initialize it.
9. From your OSC software, send a "String" type message to the IP of your machine, at the port you set in your OSC configuration earlier. The address should be `/cmd`, and the data should be something like `Plugin "RBOSCKeys" "STORE press"` or `Plugin "RBOSCKeys" "MA1 release"`.
- If you change the name of the plugin, you should rename the first value after the "Plugin" keyword.
- `STORE` can be replaced with any valid MA3 keycode. This list is the same of codes that are available for use in Quickeys
- the last word can be "press" or "release". For proper functionality of the plugin, it's very important that whenever you send a "press" event for a keycode, you also send a "release" event afterwards. The reason there aren't just one single action is for keys which also have functionality when held, such as the MA key.
# Support
I maintain this plugin in my free time. This plugin is available free, and the code is free for you to edit. If you have any issues with the plugin, feel free to contact me through the contact info on this website, but please don't expect me to respond right away.
If this plugin makes your life better, you can consider buying me a beer through [ko-fi](https://ko-fi.com/riksolo)

View file

@ -1,5 +1,5 @@
const conf = {
tags: "blogpost",
tags: "blogposts",
layout: "blogpost.njk",
eleventyComputed: {
permalink(data) {

View file

@ -1,11 +0,0 @@
<ul>
<li><a href="https://www.sowulo.nl">Sowulo</a> - Lighting design & international touring since 2023</li>
<li><a href="https://aitum.tv">Aitum</a> - React & Electron development + MIDI and OSC integration</li>
<li><a href="https://twitch.tv/mrgregles">MrGregles</a> - Fully remote, real-time live show lighting control</li>
<li>RN7 - Custom digital signage with radio playout data integration</li>
<li>Doornroosje / TivoliVredenburg / Luxor Live / Musis Sacrum - House LD / System Technician</li>
<li>ShowLine / Hoevenaars / Ecolicht - Lighting Operator / System Technician</li>
<li>DG Producties / Theater Terra / Ellen ten Damme - Theatre Touring</li>
<li>Deyval - Last-minute work for a wide range of customers</li>
<small><a href="/portfolio">See More -></a></small>
</ul>

View file

@ -1,29 +0,0 @@
{% macro navItem(title, url, hyphen=true, target='_self') %}
<span>
<a href="{{url}}" target="{{target}}">{{title}}</a>
{% if hyphen %} - {% endif %}
</span>
{% endmacro %}
<div class="container">
<div class="nav">
<a class="d-inline-block main-logo" href="/">
<img src="/img/RB-w.png" alt="RB logo" eleventy:widths="100" />
Rik Berkelder
</a>
<div class="nav-links">
<div class="d-inline-block">
{{navItem("Home", "/")}}
{{navItem("Blog", "/blog")}}
{{navItem("Portfolio", "/portfolio", false)}}
</div>
<div class="d-inline-block">
<span> | </span>
{% if site.site != "rblicht" %}
{{navItem("Mastodon", "https://dook.business/@RikSolo")}}
{% endif %}
{{navItem("Instagram", "https://instagram.com/RikBerkelder", false)}}
</div>
</div>
</div>
</div>

View file

@ -1,20 +0,0 @@
<div class="flex">
<div class="col-half">
<b>Lighting</b>
<ul>
<li>GrandMA2/3, Avolites, Obsidian Onyx</li>
<li>ATEM, Resolume, VMix, OBS</li>
<li>Timecode, Remote Production, System Integration</li>
<li>Capture</li>
</ul>
</div>
<div class="col-half">
<b>Software</b>
<ul>
<li>Typescript, Rust</li>
<li>React, Angular, Node, Electron, Embedded</li>
<li>Git, Docker</li>
<li>GitHub Actions, GitLab CI, DroneCI</li>
</ul>
</div>
</div>

View file

@ -1,55 +0,0 @@
<!doctype html>
<html>
<head>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/style.css" />
<link href="https://unpkg.com/prism-themes@1.9.0/themes/prism-nord.css" rel="stylesheet" media="print" onload="this.media='all'" />
<link rel="stylesheet" href="https://unpkg.com/simplelightbox@2.14.3/dist/simple-lightbox.min.css" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="index, follow" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="language" content="English" />
<meta name="google-site-verification" content="x17arJy33V33DYnmMYybZciXngFd8R8xn1UZRdp7qxo" />
<link rel="canonical" href="{{site.url}}{{page.url | url}}" />
{%if tags.includes("blogpost")%}
<meta property="og:type" content="article" />
{%if description %}
<meta property="description" content="{{description}}" />
<meta property="og:description" content="{{description}}" />
{% endif %}
<meta property="og:title" content="{{title}}" />
<meta property="og:url" content="{{site.url}}{{page.url | url}}" />
<meta property="og:sitename" content="{{site.title}}" />
<meta property="og:image" content="{{site.url}}/img/RB-w.png" />
{%endif%}
<title>{% if title %}{{title}} | {% endif %}{{site.title}}</title>
</head>
<body>
{{content | safe}}
<script src="//instant.page/5.2.0" type="module" integrity="sha384-jnZyxPjiipYXnSU0ygqeac2q7CVYMbh84q0uHVRRxEtvFPiQYbXWUorga2aqZJ0z"></script>
<script data-goatcounter="https://goatcounter.riksolo.com/count" async src="//goatcounter.riksolo.com/count.js"></script>
<script src="//unpkg.com/simplelightbox@2.14.3/dist/simple-lightbox.min.js"></script>
<script>
new SimpleLightbox('.gallery a', {
widthRatio: 0.9,
heightRatio: 0.95,
captionSelector: '.gallery-caption',
captionType: 'text',
});
</script>
</body>
</html>

View file

@ -1,7 +1,82 @@
---
layout: 'base-nonav.njk'
---
{% macro navItem(title, url, hyphen=true, target='_self') %}
<span>
<a href="{{url}}" target="{{target}}">{{title}}</a>
{% if hyphen %} - {% endif %}
</span>
{% endmacro %}
{%include "navbar.njk"%}
<!doctype html>
<html>
{{content | safe}}
<head>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/style.css" />
<link href="https://unpkg.com/prism-themes@1.9.0/themes/prism-nord.css" rel="stylesheet" />
<link rel="stylesheet" href="https://unpkg.com/simplelightbox@2.14.3/dist/simple-lightbox.min.css" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="index, follow" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="language" content="English" />
<meta name="google-site-verification" content="x17arJy33V33DYnmMYybZciXngFd8R8xn1UZRdp7qxo" />
<link rel="canonical" href="{{site.url}}{{page.url | url}}" />
{%if tags.includes("blogpost")%}
<meta property="og:type" content="article" />
{%if description %}
<meta property="description" content="{{description}}" />
<meta property="og:description" content="{{description}}" />
{% endif %}
<meta property="og:title" content="{{title}}" />
<meta property="og:url" content="{{site.url}}{{page.url | url}}" />
<meta property="og:sitename" content="{{site.title}}" />
<meta property="og:image" content="{{site.url}}/img/RB-w.png" />
{%endif%}
<title>{% if title %}{{title}} | {% endif %}{{site.title}}</title>
</head>
<body>
<div class="container">
<div class="nav">
<a class="d-inline-block main-logo" href="/">
<img src="/img/RB-w.png" alt="RB logo" eleventy:widths="100" />
Rik Berkelder
</a>
<div class="nav-links">
<div class="d-inline-block">
{{navItem("Home", "/")}}
{{navItem("Blog", "/blog")}}
{{navItem("Portfolio", "/portfolio", false)}}
</div>
<div class="d-inline-block">
<span> | </span>
{{navItem("Mastodon", "https://dook.business/@RikSolo")}}
{{navItem("Instagram", "https://instagram.com/RikBerkelder", false)}}
</div>
</div>
</div>
</div>
{{content | safe}}
<script src="//instant.page/5.2.0" type="module"
integrity="sha384-jnZyxPjiipYXnSU0ygqeac2q7CVYMbh84q0uHVRRxEtvFPiQYbXWUorga2aqZJ0z"></script>
<script data-goatcounter="https://goatcounter.riksolo.com/count" async
src="//goatcounter.riksolo.com/count.js"></script>
<script src="//unpkg.com/simplelightbox@2.14.3/dist/simple-lightbox.min.js"></script>
<script>
new SimpleLightbox('.gallery a', {
widthRatio: 0.9,
heightRatio: 0.95,
captionSelector: '.gallery-caption',
captionType: 'text',
});
</script>
</body>
</html>

View file

@ -14,7 +14,7 @@ layout: base.njk
<div class="portfolio-detail-images gallery">
{% for image in data.images %}
<a href="{% imageUrl image.url %}">
<img src="{{image.url}}" alt="" loading="lazy" />
<img src="{{image.url}}" alt="" loading="lazy" width="600" />
{% if image.caption %}
<div class="gallery-caption">
{{image.caption}}

View file

@ -4,7 +4,7 @@ permalink: "/blog/"
---
<h1>Blog</h1>
{% for post in collections.blogpost | reverse %}
{% for post in collections.blogposts | reverse %}
<div>
{{post.data.date | dateLocale}} - <a href="{{ post.data.permalink | safe }}">{{post.data.title}}</a>
</div>

View file

@ -1,43 +0,0 @@
---
title: CV
permalink: "/cv/"
layout: 'base-nonav.njk'
draft: true
---
<div class="container">
<h1>Rik Berkelder</h1>
Lighting Designer/Technician | Software Engineer | Nerd
<h2>About</h2>
<p>
I am a freelance lighting designer, technician, and systems specialist with a focus on touring productions and live
performance. Since 2018, I have worked freelance, initially alongside a career in IT and software engineering and
full time since 2022, bringing together technical precision, creative design, and a strong respect for the craft and
crew.
</p>
<p>
I have designed lighting for touring shows that require both creative adaptability and practical problem solving on
the road. As a house and systems technician in a variety of venues, I regularly support international acts and
crews, adapting to varied
setups and workflows. My theatre and festival touring experience has also strengthened my ability to communicate
clearly with local teams and deliver consistent, high quality results in dynamic environments.
</p>
<p>
A perfectionist by nature, I value preparation, attention to detail, and reliability while staying flexible and
collaborative to meet the demands of live production. My background in IT and network management supports
increasingly complex lighting and control systems, ensuring stable and efficient operation across all types of
venues.
</p>
<h2>Skills</h2>
{%include "skills.njk" %}
<h2>Highlighted work</h2>
{%include "highlights.njk" %}
<h2>Contact</h2>
rik@rblicht.nl / +31 6 37 27 17 91
</div>

View file

@ -1,94 +1,51 @@
---
title: Home
permalink: "/"
layout: 'base.njk'
---
<div class="container">
<h1>Rik Berkelder</h1>
Lighting Designer | Software Engineer | Nerd
<h1>Rik Berkelder</h1>
Lighting Designer | Software Engineer | Nerd
<h2>Skills</h2>
<div class="flex">
<div class="col-half">
<b>Lighting & AV</b>
<ul>
<li>GrandMA2/3, Avolites, Hog4, Obsidian Onyx</li>
<li>Capture, Vectorworks</li>
<li>ATEM, Resolume, VMix, OBS</li>
<li>Timecode, Remote Production, System Integration</li>
</ul>
</div>
<div class="col-half">
<b>Software</b>
<ul>
<li>Typescript, GraphQL</li>
<li>React (Native), Angular, NodeJS, Electron</li>
<li>Git, Docker, Gitlab CI, GitHub Actions, DroneCI</li>
<li>Sass/SCSS, Tailwind, Bootstrap</li>
</ul>
</div>
</div>
<div class="homepage-images">
<a href="/portfolio/tivolivredenburg">
<img src="/portfolio/tivolivredenburg/001.jpg" width="750" alt="" />
</a>
<h2>Highlighted Projects/Clients</h2>
<ul>
<li><a href="https://www.sowulo.nl">Sowulo</a> - Lighting design & touring since 2023</li>
<li><a href="https://aitum.tv">Aitum</a> - React & Electron development</li>
<li><a href="https://twitch.tv/mrgregles">MrGregles</a> - Fully remote, real-time live show lighting control</li>
<li><a href="https://rn7.nl">RN7</a> - Custom digital signage with radio playout data integration</li>
<li>Doornroosje / TivoliVredenburg / Luxor Live - House LD</li>
<small><a href="/portfolio">See More -></a></small>
</ul>
<a href="/portfolio/doornroosje">
<img src="/portfolio/doornroosje/03.jpg" width="750" alt="" />
</a>
<h2>Contact</h2>
mail@riksolo.com / rik@rblicht.nl
<a href="/portfolio/sowulo">
<img src="/portfolio/sowulo/33.jpg" width="750" alt="" />
</a>
</div>
<div class="container">
<h2>About</h2>
<p>
I am a freelance lighting designer/technician with a passion for the intersection of technical problem-solving with creative expression. My journey in lighting began in primary school, where I didn't want to perform in the school play and got put behind the technical desk instead. At that point, something clicked in me, and I've found a drive to pass that feeling of magic along to audiences through creating unique live experiences. I grew to greatly appreciate how light can affect mood and atmosphere, and I've found it fascinating to explore these relationships through technology.
</p>
<p>
This passion for stagecraft is contrasted by a long-running interest in computers, and a solid background in software development. Aside from working in software for a living before transitioning into lighting full-time, I still program for clients on occasion. The software projects I take on now usually involve some blend of art and technology. Such projects have included custom integrations with external tools for live show concepts, automation tools for solo live-streaming and remote production tools that have helped enable remotely-produced events during social distancing.
</p>
<p>
A perfectionist by nature, I deeply value preparation, attention to detail and reliability without losing sight of the spontaneity that fuels the creative process. I always aim to bring professionalism and technical precision to the table, blending it with a love for creative problem-solving and, in the end, a never-ending drive to make any project the best version of itself it can possibly be.
</p>
<p>
I strongly believe that, in this highly specific and inseparable mix of art and technology, a new kind of magic is to be explored.
</p>
</div>
<div class="homepage-images">
<a href="/portfolio/tivolivredenburg">
<img src="/portfolio/tivolivredenburg/007.jpg" width="750" alt="" />
</a>
<a href="/portfolio/sowulo">
<img src="/portfolio/sowulo/3.jpg" width="750" alt="" />
</a>
<a href="/portfolio/luxorlive">
<img src="/portfolio/luxorlive/91.jpg" width="750" alt="" />
</a>
</div>
<div class="container">
<h2>Skills</h2>
{%include "skills.njk" %}
<h2>Highlighted Projects/Clients</h2>
{%include "highlights.njk" %}
<h2>Contact</h2>
{% if site.site != "rblicht" %}mail@riksolo.com / {% endif %}rik@rblicht.nl
<h3>Find me elsewhere</h3>
<ul>
{% if site.site != "rblicht" %}
<li><a href="https://dook.business/@RikSolo">Mastodon</a> <small>(dook.business)</small></li>
{%endif%}
<li><a href="https://instagram.com/RikBerkelder">Instagram</a></li>
<li><a href="https://github.com/rikberkelder">GitHub</a></li>
<li><a href="https://git.riksolo.com">Gitea</a></li>
</ul>
</div>
<div class="homepage-images">
<a href="/portfolio/femina">
<img src="/portfolio/femina/02.jpg" width="750" alt="" />
</a>
<a href="/portfolio/luxorlive">
<img src="/portfolio/luxorlive/32.jpg" width="750" alt="" />
</a>
<a href="/portfolio/musis">
<img src="/portfolio/musis/1.jpg" width="750" alt="" />
</a>
</div>
<h3>Find me elsewhere</h3>
<ul>
<li><a href="https://dook.business/@RikSolo">Mastodon</a> <small>(dook.business)</small></li>
<li><a href="https://instagram.com/RikBerkelder">Instagram</a></li>
<li><a href="https://github.com/rikberkelder">GitHub</a></li>
<li><a href="https://git.riksolo.com">Gitea</a></li>
</ul>

Binary file not shown.

View file

@ -1,6 +0,0 @@
---
order: 4
title: DG Theater
description: "National theatre tours with Cirque en Afrique: Kalabante (2024) and African Mama's: The Great Five (2025). Bringing the show's designs to life in varying conditions, and making sure all of the technical lighting aspects of the show are maintained properly and function perfectly every performance."
timeframe: 2024 - now
---

Binary file not shown.

Binary file not shown.

BIN
content/portfolio/doornroosje/001.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/doornroosje/002.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/doornroosje/01.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/doornroosje/03.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/doornroosje/1.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/doornroosje/2.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/doornroosje/3.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/doornroosje/4.jpg (Stored with Git LFS)

Binary file not shown.

View file

@ -1,6 +0,0 @@
---
order: 5
title: Doornroosje
description: Making sure visiting technicians have a smooth experience at the iconic Nijmegen venue, and providing fitting lighting on the fly for any act not travelling with their own lighting designer and a variety of dance events.
timeframe: 2024 - now
---

BIN
content/portfolio/koenjesse/01.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/koenjesse/02.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/koenjesse/03.png (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/koenjesse/04.png (Stored with Git LFS)

Binary file not shown.

View file

@ -1,6 +0,0 @@
---
order: 5
title: Wedding Koen & Jesse
description: Complete technical production transforming a classical church to provide an elegant look for the wedding itself, a cozy space for the reception and a night club for the party going on into the small hours.
timeframe: may 2025
---

BIN
content/portfolio/luxorlive/01.jpg (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

View file

@ -1,6 +1,15 @@
---
order: 2
title: Luxor Live
description: Delivering dynamic, on-the-spot lighting for visiting acts without their own lighting designer, and ensuring the house system is in perfect shape for visiting technicians.
description: Delivering dynamic, on-the-spot lighting for visiting acts without their own lighting designer, and ensuring a smooth experience with the house rig for visiting technicians.
timeframe: 2022 - now
---
---
## Notable shows
(without touring LD)
- GZA
- Vandenberg
- Go_A
- Lucky Chops
- Robin Borneman
- Julian Sas

View file

@ -17,7 +17,8 @@ const conf = {
const images = await Promise.all(files.map(async (image) => {
const imagePath = path.resolve(dir + '/' + image);
const exif = await exifr.parse(imagePath, { pick: ['XPComment', 'DateTimeOriginal'] });
//const exif = await exifr.parse(imagePath, { pick: ['XPComment', 'DateTimeOriginal'] });
const exif = {};
return {
url: data.page.url + image,

BIN
content/portfolio/sowulo/1.JPG (Stored with Git LFS) Normal file

Binary file not shown.

BIN
content/portfolio/sowulo/1.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/sowulo/2.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/sowulo/3.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/sowulo/32.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/sowulo/33.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/sowulo/43.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/sowulo/5.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/sowulo/51.jpg (Stored with Git LFS)

Binary file not shown.

View file

@ -1,30 +1,19 @@
---
order: 1
title: Sowulo
description: Designing a theatrical, atmospheric and detailed show while and bringing it to a variety venues and festivals of varying sizes with very short on-site preparation times. Highlights include Hellfest, Motocultor, Castlefest and a 2025 EU Headline Tour
description: Designing a theatrical, atmospheric and detailed show while and bringing it to a variety venues and festivals of varying sizes with very short on-site preparation times.
timeframe: 2023 - now
---
## Notable shows
<div class="list-no-newline">
- Patronaat, Haarlem (NL)
- Midgardsblod 2025 (NO), mainstage
- Castlefest 2025 (NL), mainstage
- Hellfest 2025 (FR), temple stage
- Echos & Merveilles 2025 (FR), mainstage
- Doornroosje, Nijmegen (NL)
- Clubtour 2025 (NL, DE, FR)
- P60, Amstelveen (NL)
- Motocultor 2024 (FR)
- Sint Stevenskerk, 4daagsefeesten, Nijmegen (NL)
- Opera Leśna (PL), support Heilung
- Wave Gothik Treffen 2024 (DE)
- Echos & Merveilles 2024 (FR)
- Trolls & Legends 2024 (BE)
- TivoliVredenburg (NL), pandora
- Menuo Juodoragis 2023 (LT), mainstage
- Midgardsblot 2023 (NO), mainstage
- Castlefest 2023 (NL), mainstage
</div>
- Castlefest (mainstage) 2023
- Midgardsblot (mainstage) 2023
- Menuo Juodoragis (mainstage) 2023
- TivoliVredenburg (Pandora)
- Trolls & Legends 2024
- Echos & Merveilles 2024
- Wave Gothik Treffen 2024
- Opera Leśna (support Heilung)
- Sint Stevenskerk Nijmegen
- Motocultor 2024
- P60 amstelveen

BIN
content/portfolio/tivolivredenburg/001.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/tivolivredenburg/005.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/tivolivredenburg/007.jpg (Stored with Git LFS)

Binary file not shown.

BIN
content/portfolio/tivolivredenburg/017.jpg (Stored with Git LFS)

Binary file not shown.

View file

@ -1,6 +1,6 @@
---
order: 3
title: TivoliVredenburg
description: Creative and fitting lighting for a wide variety of productions. From sales to classical to jazz to metal, across 5 stages in the venue. As well as making sure the house systems function and adapt perfectly to visiting tours and complex international productions, including regular maintenance and show-specific adaptations.
description: Creative and fitting lighting for a wide variety of productions. From sales to classical to jazz to metal, across 5 stages in the venue.
timeframe: 2023 - now
---

View file

@ -30,34 +30,10 @@ body {
color: $white-vdark;
}
.homepage-images {
display: flex;
max-height: 30vh;
width: 100%;
margin: 1rem 0;
img {
object-fit: cover;
height: 100% !important;
width: 100% !important;
}
@media screen and (max-width:750px) {
a:nth-child(3) {
display: none;
}
}
}
.container {
max-width: 900px;
margin-left: auto;
margin-right: auto;
padding: 0 1rem;
display: block;
}
@ -65,7 +41,6 @@ body {
max-width: 700px;
margin-left: auto;
margin-right: auto;
padding: 0 1rem;
&-header {
&>* {
@ -112,9 +87,11 @@ body {
flex-wrap: wrap !important;
}
picture {
picture,
img {
display: block;
height: 15rem;
height: 15rem !important;
max-width: 33.33%;
flex-grow: 1;
img {
@ -256,29 +233,15 @@ body {
pre[class*="language-"] {
max-width: 100%;
box-sizing: border-box;
background: $grey-dark !important;
border-radius: 0;
padding: 0.5rem;
}
blockquote {
background-color: $grey-dark;
box-sizing: border-box;
padding: 1rem;
padding-bottom: 0.5rem;
margin: 0;
margin-bottom: 1rem;
p {
margin-bottom: 1rem;
}
}
.nav {
width: 100%;
padding-top: 0.6rem;
padding-top: 0.2rem;
padding-bottom: 0.9em;
margin-bottom: 0.6em;
border-bottom: 1px $grey-dark solid;
@ -406,22 +369,5 @@ body {
width: 100%;
padding: 0.3rem 0.4rem;
}
}
.list-no-newline {
& ul {
text-align: left;
margin: 0;
padding: 0;
}
& li {
display: inline-block;
&::before {
content: '';
}
}
}

View file

@ -31,7 +31,13 @@ export default async function (eleventyConfig) {
//Images
eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
widths: ["700"]
widths: ["700"],
formats: ["jpeg", "webp", "gif"],
useCache: true,
sharpOptions: {
animated: true,
limitInputPixels: false
}
});
eleventyConfig.addShortcode("figure", (url, alt, caption, width) => {
return `
@ -45,10 +51,15 @@ export default async function (eleventyConfig) {
eleventyConfig.addShortcode("imageUrl", async (image, width) => {
const img = await Image(`./content${image}`, {
outputDir: 'dist/img/',
useCache: true
useCache: true,
sharpOptions: {
animated: true,
limitInputPixels: false
}
});
return img.jpeg[0].url;
const files = img.jpeg ?? img.webp;
return files[0].url;
});
//Markdown