diff --git a/macos/Info.plist b/macos/Info.plist
new file mode 100644
index 00000000..835ea503
--- /dev/null
+++ b/macos/Info.plist
@@ -0,0 +1,60 @@
+
+
+
+
+ NSPrincipalClass
+ NSApplication
+ NSHighResolutionCapable
+ True
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ novelwriter
+ CFBundleGetInfoString
+ novelWriter: A markdown-like text editor for planning and writing novels.
+ CFBundleIconFile
+ novelwriter.icns
+ CFBundleIdentifier
+ io.novelwriter.novelWriter
+ CFBundleName
+ novelWriter
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleShortVersionString
+ 2.0.1
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 2.0.1
+ CFBundlePackageType
+ APPL
+ NSHumanReadableCopyright
+ © 2018–2022, Veronica Berglyd Olsen
+ IFMajorVersion
+ 0
+ IFMinorVersion
+ 1
+ CFBundleDocumentTypes
+
+
+ CFBundleTypeExtensions
+
+ nwx
+
+ CFBundleTypeName
+ novelWriter Project
+ CFBundleTypeOSTypes
+
+ TEXT
+ utxt
+ TUTX
+ ****
+
+ CFBundleTypeRole
+ Viewer
+ LSHandlerRank
+ Alternate
+
+
+
+
\ No newline at end of file
diff --git a/macos/Info.plist.in b/macos/Info.plist.in
new file mode 100644
index 00000000..f5ab4d2c
--- /dev/null
+++ b/macos/Info.plist.in
@@ -0,0 +1,60 @@
+
+
+
+
+ NSPrincipalClass
+ NSApplication
+ NSHighResolutionCapable
+ True
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ {MACOSX_BUNDLE_EXACUTABLE_NAME}
+ CFBundleGetInfoString
+ {MACOSX_BUNDLE_INFO_STRING}
+ CFBundleIconFile
+ {MACOSX_BUNDLE_ICON_FILE}
+ CFBundleIdentifier
+ {MACOSX_BUNDLE_IDENTIFIER}
+ CFBundleName
+ {MACOSX_BUNDLE_NAME}
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleShortVersionString
+ {MACOSX_BUNDLE_SHORT_VERSION}
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ {MACOSX_BUNDLE_VERSION}
+ CFBundlePackageType
+ APPL
+ NSHumanReadableCopyright
+ {MACOSX_BUNDLE_COPYRIGHT}
+ IFMajorVersion
+ 0
+ IFMinorVersion
+ 1
+ CFBundleDocumentTypes
+
+
+ CFBundleTypeExtensions
+
+ nwx
+
+ CFBundleTypeName
+ novelWriter Project
+ CFBundleTypeOSTypes
+
+ TEXT
+ utxt
+ TUTX
+ ****
+
+ CFBundleTypeRole
+ Viewer
+ LSHandlerRank
+ Alternate
+
+
+
+
\ No newline at end of file
diff --git a/macos/build.sh b/macos/build.sh
new file mode 100644
index 00000000..9259d3a7
--- /dev/null
+++ b/macos/build.sh
@@ -0,0 +1,92 @@
+#! /bin/bash
+
+# use RAM disk if possible
+if [ -d /dev/shm ]; then
+ TEMP_BASE=/dev/shm
+else
+ TEMP_BASE=/tmp
+fi
+
+BUILD_DIR=$(mktemp -d "$TEMP_BASE/novelWriter-build-XXXXXX")
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+
+cleanup () {
+ if [ -d "$BUILD_DIR" ]; then
+ rm -rf "$BUILD_DIR"
+ fi
+}
+
+trap cleanup EXIT
+
+OLD_CWD="$(pwd)"
+
+VERSION="$(awk '/^__version__/{print substr($NF,2,length($NF)-2)}' $SCRIPT_DIR/../novelwriter/__init__.py)"
+
+
+pushd "$BUILD_DIR"/ || exit 1
+
+# install Miniconda, a self-contained Python distribution
+wget https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
+bash Miniconda3-latest-MacOSX-x86_64.sh -b -p ~/miniconda -f
+rm Miniconda3-latest-MacOSX-x86_64.sh
+export PATH="$HOME/miniconda/bin:$PATH"
+
+# create conda env
+conda create -n novelWriter python --yes
+source activate novelWriter
+
+# install dependencies
+pip install -r "$SCRIPT_DIR/../requirements.txt"
+
+# leave conda env
+source deactivate
+
+# create .app Framework
+mkdir -p novelWriter.app/Contents/
+mkdir novelWriter.app/Contents/MacOS novelWriter.app/Contents/Resources novelWriter.app/Contents/Resources/novelWriter
+mv $SCRIPT_DIR/../macos/Info.plist novelWriter.app/Contents/Info.plist
+
+# copy Miniconda env
+cp -R ~/miniconda/envs/novelWriter/* novelWriter.app/Contents/Resources/
+
+# copy Pext
+cp -R $SCRIPT_DIR/../* novelWriter.app/Contents/Resources/novelWriter/
+
+
+# create entry script
+cat > novelWriter.app/Contents/MacOS/novelWriter <<\EOF
+#!/bin/bash
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+$DIR/../Resources/bin/python -sE $DIR/../Resources/novelWriter/novelwriter $@
+EOF
+
+# make executable
+chmod a+x novelWriter.app/Contents/MacOS/novelWriter
+
+# remove bloat
+pushd novelWriter.app/Contents/Resources || exit 1
+
+# cleanup commands HERE
+find . -type d -iname '__pycache__' -print0 | xargs -0 rm -r
+
+#remove web engine
+rm lib/python3.7/site-packages/PyQt5/QtWebEngine* || true
+rm -r lib/python3.7/site-packages/PyQt5/Qt/translations/qtwebengine* || true
+rm lib/python3.7/site-packages/PyQt5/Qt/resources/qtwebengine* || true
+rm -r lib/python3.7/site-packages/PyQt5/Qt/qml/QtWebEngine* || true
+rm -r lib/python3.7/site-packages/PyQt5/Qt/plugins/webview/libqtwebview* || true
+rm lib/python3.7/site-packages/PyQt5/Qt/libexec/QtWebEngineProcess* || true
+rm lib/python3.7/site-packages/PyQt5/Qt/lib/libQt5WebEngine* || true
+
+popd || exit 1
+popd || exit 1
+
+
+# generate .dmg
+
+brew install create-dmg
+# "--skip-jenkins" is a temporary workaround for https://github.com/create-dmg/create-dmg/issues/72
+create-dmg --skip-jenkins --volname "novelWriter $VERSION" --volicon $SCRIPT_DIR/../macos/novelwriter.icns \
+ --window-pos 200 120 --window-size 800 400 --icon-size 100 --icon novelWriter.app 200 190 --hide-extension novelWriter.app \
+ --app-drop-link 600 185 novelWriter-"${VERSION}".dmg "$BUILD_DIR"/
diff --git a/macos/generate_icns.sh b/macos/generate_icns.sh
new file mode 100755
index 00000000..ef4747dc
--- /dev/null
+++ b/macos/generate_icns.sh
@@ -0,0 +1,19 @@
+#! /usr/bin/env bash
+
+if ! command -v png2icns &> /dev/null
+then
+ echo "png2icns cound not be found, it is required. Please install a package like icnsutils or libicns."
+ exit
+fi
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+
+mkdir -p $SCRIPT_DIR/icons
+
+for size in 16x16 32x32 48x48 128x128 256x256; do
+ cp $SCRIPT_DIR/../setup/data/hicolor/$size/apps/novelwriter.png $SCRIPT_DIR/icons/icon_${size}px.png
+done
+
+png2icns $SCRIPT_DIR/novelwriter.icns $SCRIPT_DIR/icons/icon_*px.png
+
+rm -r $SCRIPT_DIR/icons
\ No newline at end of file
diff --git a/macos/generate_plist.py b/macos/generate_plist.py
new file mode 100644
index 00000000..2f6e3c26
--- /dev/null
+++ b/macos/generate_plist.py
@@ -0,0 +1,26 @@
+import os
+
+SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
+
+SETTINGS = {
+ "MACOSX_BUNDLE_COPYRIGHT": "© 2018–2022, Veronica Berglyd Olsen ",
+ "MACOSX_BUNDLE_IDENTIFIER": "io.novelwriter.novelWriter",
+ "MACOSX_BUNDLE_NAME": "novelWriter",
+ "MACOSX_BUNDLE_EXACUTABLE_NAME": "novelwriter",
+ "MACOSX_BUNDLE_ICON_FILE": "novelwriter.icns",
+ "MACOSX_BUNDLE_INFO_STRING": "novelWriter: A markdown-like text editor for planning and writing novels.",
+ "MACOSX_BUNDLE_SHORT_VERSION": "2.0.1", # Must be purely numerical
+ "MACOSX_BUNDLE_VERSION": "2.0.1", # Must be purely numerical
+}
+
+if __name__ == "__main__":
+
+ template_filename = os.path.join(SCRIPT_DIR, "Info.plist.in")
+ with open(template_filename, "r") as tmfile:
+ template = tmfile.read()
+
+ plist = template.format(**SETTINGS)
+
+ plist_filename = os.path.join(SCRIPT_DIR, "Info.plist")
+ with open(plist_filename, "w") as plistfile:
+ plistfile.write(plist)
diff --git a/macos/novelwriter.icns b/macos/novelwriter.icns
new file mode 100644
index 00000000..8a05c8e9
Binary files /dev/null and b/macos/novelwriter.icns differ