diff --git a/.distignore b/.distignore
new file mode 100644
index 0000000..19f14f4
--- /dev/null
+++ b/.distignore
@@ -0,0 +1,19 @@
+# Specify which files should not be included in the push to WordPress.org.
+# These are all development files and directories.
+# The deploy Action will use rsync + .distignore if the .distignore exists,
+# so it doesn't care what may or may not be ignored via .gitignore.
+
+/.github/
+/bin/
+/tests/
+/.distignore
+/.editorconfig
+/.gitattributes
+/.gitignore
+/.phpcs.xml.dist
+/CHANGELOG.md
+/composer.json
+/mixtape.json
+/package.json
+/package-lock.json
+/phpunit.xml.dist
diff --git a/.gitattributes b/.gitattributes
index 6ca46ab..3f5c93d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,14 +1,33 @@
-/.editorconfig export-ignore
-/.gitattributes export-ignore
-/.github/ export-ignore
-/.gitignore export-ignore
-/.phpcs.xml.dist export-ignore
-/bin/ export-ignore
-/mixtape.json export-ignore
-/package.json export-ignore
-/phpunit.xml.dist export-ignore
-/screenshot-1.png export-ignore
-/tests/ export-ignore
-/zone-display.png export-ignore
-/zone-widget.png export-ignore
-/zones.png export-ignore
+# Exclude these files from GitHub release archives.
+# This will also make them unavailable when using Composer with `--prefer-dist`.
+# If you develop for this plugin using Composer, use `--prefer-source`.
+# https://blog.madewithlove.be/post/gitattributes/
+
+/.github/ export-ignore
+/.wordpress-org/ export-ignore
+/node_modules/ export-ignore
+/bin/ export-ignore
+/tests/ export-ignore
+
+/.distignore export-ignore
+/.editorconfig export-ignore
+/.gitattributes export-ignore
+/.gitignore export-ignore
+/.phpcs.xml.dist export-ignore
+/CHANGELOG.md export-ignore
+/composer.json export-ignore
+/mixtape.json export-ignore
+/package.json export-ignore
+/package-lock.json export-ignore
+/phpunit.xml.dist export-ignore
+
+# Auto detect text files and perform LF normalization
+# https://pablorsk.medium.com/be-a-git-ninja-the-gitattributes-file-e58c07c9e915
+
+* text=auto
+
+# The above will handle all files NOT found below
+
+*.md text
+*.php text
+*.inc text
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000..bc0afb4
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,19 @@
+name: Deploy to WordPress.org
+on:
+ release:
+ types: [ released ]
+ # Allow manual triggering of the workflow.
+ workflow_dispatch:
+jobs:
+ release:
+ name: New release to WordPress.org
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Push to WordPress.org
+ uses: 10up/action-wordpress-plugin-deploy@stable
+ env:
+ SLUG: zoninator
+ SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
+ SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
diff --git a/.gitignore b/.gitignore
index 6003eee..6fc9e4a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,198 +1,7 @@
-tests/vendor
-/nbproject/private/
-nbproject
-
-#
-
-# Windows thumbnail cache files
-Thumbs.db
-ehthumbs.db
-ehthumbs_vista.db
-
-# Folder config file
-Desktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Windows Installer files
-*.cab
-*.msi
-*.msm
-*.msp
-
-# Windows shortcuts
-*.lnk
-
-#
-
-#
-
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# Runtime data
-pids
-*.pid
-*.seed
-*.pid.lock
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-
-# nyc test coverage
-.nyc_output
-
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# Bower dependency directory (https://bower.io/)
-bower_components
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (http://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directories
-node_modules/
-jspm_packages/
-
-# Typescript v1 declaration files
-typings/
-
-# Optional npm cache directory
-.npm
-
-# Optional eslint cache
-.eslintcache
-
-# Optional REPL history
-.node_repl_history
-
-# Output of 'npm pack'
-*.tgz
-
-# Yarn Integrity file
-.yarn-integrity
-
-# dotenv environment variables file
-.env
-
-#
-
-#
-
-*.DS_Store
-.AppleDouble
-.LSOverride
-
-# Icon must end with two \r
-Icon
-
-# Thumbnails
-._*
-
-# Files that might appear in the root of a volume
-.DocumentRevisions-V100
-.fseventsd
-.Spotlight-V100
-.TemporaryItems
-.Trashes
-.VolumeIcon.icns
-.com.apple.timemachine.donotpresent
-
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
-
-#
-
-#
-
-# Prerequisites
-*.d
-
-# Object files
-*.o
-*.ko
-*.obj
-*.elf
-
-# Linker output
-*.ilk
-*.map
-*.exp
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Libraries
-*.lib
-*.a
-*.la
-*.lo
-
-# Shared objects (inc. Windows DLLs)
-*.dll
-*.so
-*.so.*
-*.dylib
-
-# Executables
-*.exe
-*.out
-*.app
-*.i*86
-*.x86_64
-*.hex
-
-# Debug files
-*.dSYM/
-*.su
-*.idb
-*.pdb
-
-# Kernel Module Compile Results
-*.mod*
-*.cmd
-modules.order
-Module.symvers
-Mkfile.old
-dkms.conf
-
-#
-
-#
-
-*~
-
-# temporary files which can be created if a process still has a handle open of a deleted file
-.fuse_hidden*
-
-# KDE directory preferences
-.directory
-
-# Linux trash folder which might appear on any partition or disk
-.Trash-*
-
-# .nfs files are created when an open file is removed but is still being accessed
-.nfs*
-
-#
-
-tmp
-composer.lock
-/vendor
+/.phpunit.cache/
+/node_modules/
+/vendor/
+/.phpcs.xml
+/composer.lock
+/phpcs.xml
+/phpunit.xml