diff --git a/changes/changelog.d/1285.bugfix b/changes/changelog.d/1285.bugfix
new file mode 100644
index 0000000000000000000000000000000000000000..68fe52174c11a069b775c9b2032d563e2815b339
--- /dev/null
+++ b/changes/changelog.d/1285.bugfix
@@ -0,0 +1 @@
+Frontend build tooling is less dependent on `npm` or `yarn` being used (!1285)
diff --git a/front/scripts/fix-fomantic-css.sh b/front/scripts/fix-fomantic-css.sh
index 0cb6268ef15b27e97ac599718dce1b82dd28e8c6..bbb7b85088fdf66a97965c17b32d9d19ed07abfd 100755
--- a/front/scripts/fix-fomantic-css.sh
+++ b/front/scripts/fix-fomantic-css.sh
@@ -1,4 +1,6 @@
-#!/bin/bash -eux
+#!/usr/bin/env -S bash -eux
+
+cd "$(dirname $0)/.." # change into base directory
 
 find node_modules/fomantic-ui-css/components -name "*.min.css" -delete
 mkdir -p node_modules/fomantic-ui-css/tweaked
diff --git a/front/scripts/i18n-compile.sh b/front/scripts/i18n-compile.sh
index eb4e9970aade5e7efe27594ca4bcbbf93ddb159c..0b90bfd4279b1d4517d4ce56c4aa99a928f1f425 100755
--- a/front/scripts/i18n-compile.sh
+++ b/front/scripts/i18n-compile.sh
@@ -1,9 +1,13 @@
-#!/bin/bash -eux
+#!/usr/bin/env -S bash -eux
+
+cd "$(dirname $0)/.." # change into base directory
+source scripts/utils.sh
+
 locales=$(tail -n +2 src/locales.js | sed -e 's/export default //' | jq '.locales[].code' | grep -v 'en_US' | xargs echo)
 mkdir -p src/translations
 
 for locale in $locales; do
-    $(yarn bin)/gettext-compile locales/$locale/LC_MESSAGES/app.po --output src/translations/$locale.json
+  $(npm_binaries)/gettext-compile locales/$locale/LC_MESSAGES/app.po --output src/translations/$locale.json
 done
 
-# find locales -name '*.po' | xargs $(yarn bin)/gettext-compile --output src/translations.json
+# find locales -name '*.po' | xargs $(npm_binaries)/.bin/gettext-compile --output src/translations.json
diff --git a/front/scripts/i18n-extract.sh b/front/scripts/i18n-extract.sh
index df2c37ea523c066da48e145b14f5149479af8278..63b79b164f87203651ca3f04206653406bd06599 100755
--- a/front/scripts/i18n-extract.sh
+++ b/front/scripts/i18n-extract.sh
@@ -1,4 +1,8 @@
-#!/bin/bash -eux
+#!/usr/bin/env -S bash -eux
+
+cd "$(dirname $0)/.." # change into base directory
+source scripts/utils.sh
+
 locales=$(tail -n +2 src/locales.js | sed -e 's/export default //' | jq '.locales[].code' | xargs echo)
 locales_dir="locales"
 sources=$(find src -name '*.vue' -o -name '*.html' 2> /dev/null)
@@ -7,7 +11,7 @@ touch $locales_dir/app.pot
 GENERATE=${GENERATE-true}
 # Create a main .pot template, then generate .po files for each available language.
 # Extract gettext strings from templates files and create a POT dictionary template.
-$(yarn bin)/gettext-extract --attribute v-translate --quiet --output $locales_dir/app.pot $sources
+$(npm_binaries)/gettext-extract --attribute v-translate --quiet --output $locales_dir/app.pot $sources
 xgettext --language=JavaScript --keyword=npgettext:1c,2,3 \
     --from-code=utf-8 --join-existing --no-wrap \
     --package-name=$(node -e "console.log(require('./package.json').name);") \
diff --git a/front/scripts/i18n-populate-contextualized-strings.sh b/front/scripts/i18n-populate-contextualized-strings.sh
index fa47eb4d6f4b2757bbf608b317a0ecba25f1dd63..37f0b1871d659f27a463e0cb4ad5fcc176a04434 100755
--- a/front/scripts/i18n-populate-contextualized-strings.sh
+++ b/front/scripts/i18n-populate-contextualized-strings.sh
@@ -1,4 +1,4 @@
-#!/bin/bash -eu
+#!/usr/bin/env -S bash -eux
 
 # Typical use:
 # cp -r locales old_locales
@@ -6,6 +6,8 @@
 # ./scripts/i18n-populate-contextualized-strings.sh old_locales locales
 # Then review/commit the changes
 
+cd "$(dirname $0)/.." # change into base directory
+
 old_locales_dir=$1
 new_locales_dir=$2
 
diff --git a/front/scripts/i18n-weblate-to-origin.sh b/front/scripts/i18n-weblate-to-origin.sh
index 7edd4ad9c1e82140543b1d632726cded7a70e24c..e7d98f48ba7f1c2588c25a6d7d4ffe5799214e52 100755
--- a/front/scripts/i18n-weblate-to-origin.sh
+++ b/front/scripts/i18n-weblate-to-origin.sh
@@ -1,4 +1,4 @@
-#!/bin/bash -eux
+#!/usr/bin/env -S bash -eux
 integration_branch="translations-integration"
 git remote add weblate https://translate.funkwhale.audio/git/funkwhale/front/ || echo "remote already exists"
 git fetch weblate
diff --git a/front/scripts/utils.sh b/front/scripts/utils.sh
new file mode 100644
index 0000000000000000000000000000000000000000..2c8fd476a3f8299f481cf26f190b76b3b8199be5
--- /dev/null
+++ b/front/scripts/utils.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash -S -eux
+
+npm_binaries () {
+  command -v yarn > /dev/null && yarn bin || npm bin
+}