A native macOS presentation app for churches: lyrics, slides, media, timers, stage displays, multitrack stems, timecode, NDI and DeckLink output, and live streaming. Everything runs on this Mac: no account, no server.
MxU Slides is source-available under the PolyForm Shield License 1.0.0. See LICENSE.md.
What the license allows:
- Use it for any purpose, including commercially and in production, at a church, a venue, or a business
- Read, modify, and build on the source
- Fork it and distribute copies or modified versions, as long as the license and its notice travel with them
- Contribute changes back
What it does not allow:
- Providing a product that competes with MxU Slides, or with any product MxU provides using it, even if that product is free, uses a different interface or platform, or is written in another language
- Removing or altering the license text or the required notice
The full terms, including what happens if MxU later ships a product that competes with yours, are in LICENSE.md.
Requirements:
- macOS 14 or newer, Xcode 26 (Swift 6 toolchain)
- XcodeGen:
brew install xcodegen - Node 24 (
.tool-versions) for the schema codegen and the drive scripts - Optional, for NDI inputs and outputs: install the NDI SDK for Apple at
/Library/NDI SDK for Apple. Without itNDIKitbuilds a stub and NDI is unavailable in the app. After installing or removing the SDK, delete~/Library/Caches/org.swift.swiftpm/manifestsand use Product › Clean Build Folder.apps/mac/scripts/release-dmg.shstill requires it. - Optional, for ProPresenter import:
brew install protobuf swift-protobuf, then runapps/mac/scripts/generate-propresenter-proto.sh. Without the generated typesProImportbuilds a stub and the import menu reports that it is unavailable.apps/mac/scripts/release-dmg.shstill requires them.
The Blackmagic DeckLink SDK headers are vendored, so DeckLink output needs no install to build.
Build and run:
cd apps/mac
xcodegen generate
xcodebuild -project MxUSlides.xcodeproj -scheme MxUSlides -configuration Debug -disableAutomaticPackageResolution -onlyUsePackageVersionsFromResolvedFile build
open "$(xcodebuild -project MxUSlides.xcodeproj -scheme MxUSlides -configuration Debug -disableAutomaticPackageResolution -onlyUsePackageVersionsFromResolvedFile -showBuildSettings 2>/dev/null | awk '/TARGET_BUILD_DIR/{print $3; exit}')/MxU Slides.app"Or open MxUSlides.xcodeproj in Xcode after xcodegen generate and run the MxUSlides scheme. Re-run xcodegen generate whenever you add or remove source files; the project file is generated and not checked in.
Dependency versions are pinned in the checked-in Package.resolved files for LocalAPI, StreamEngine, and ProImport. XcodeGen combines those pins into the app's generated lockfile, including SwiftProtobuf only when the ProPresenter sources are present. Re-run xcodegen generate after generating or removing those sources; when switching configurations, also clear SwiftPM's manifest cache as described above and clean the build. Every app build verifies the generated lock against the package pins, and the commands above and the release script disable automatic dependency updates. For an intentional dependency update, update the affected package's lockfile, regenerate the project, and test both the package and app.
Each package builds and tests on its own with SwiftPM. None of them needs the NDI SDK (NDIKit builds a stub without it):
cd apps/mac/Packages
swift test --package-path PresenterCore
swift test --package-path SlideScene
swift test --package-path RenderEngine
swift test --package-path OutputEngine
swift test --package-path LocalAPI --force-resolved-versions
swift test --package-path ProImport --force-resolved-versions --manifest-cache none --disable-build-manifest-cachingRun node apps/mac/scripts/test-dependency-locking.mjs from the repository root to check lock generation and rejection of missing, conflicting, or changed pins.
Debug builds are ad-hoc signed (CODE_SIGN_IDENTITY: "-" in apps/mac/project.yml), so a fresh clone builds and runs without an Apple developer account. Set bundleIdPrefix, DEVELOPMENT_TEAM, and a signing identity there before archiving or distributing.
Edit packages/schema/documents.json, then regenerate:
node packages/schema/codegen.mjsThat rewrites PresenterCore/Sources/PresenterCore/Generated/Models.swift and LocalAPI/Sources/LocalAPI/Resources/document-schemas.json. Fields added after a type ships must be optional so existing libraries keep decoding.
apps/mac/scripts/release-dmg.sh builds, Developer ID-signs, notarizes, and staples a DMG. It expects a notarization-profile entry in your Keychain (xcrun notarytool store-credentials), the NDI SDK's redistributable license file, and the ProPresenter types from apps/mac/scripts/generate-propresenter-proto.sh.
With Settings › Local API enabled, the app serves a REST and WebSocket API on port 6980, authenticated by scoped bearer tokens created in the same pane. GET /v1/status returns the live slide; scripts/*.mjs show it driving a show. The route table and OpenAPI document live in apps/mac/Packages/LocalAPI.
apps/mac/scripts/perf/run.shruns the scripted editor and animation perf check against a staged build and compares withbaseline.json.apps/mac/scripts/hitch-report.pysummarizes the main-thread hitches recorded in the app's breadcrumb logs (Help › Report a Problem saves them as a zip).apps/mac/scripts/hls-sink.mjs/hls-replay.mjsstand in for an HLS ingest endpoint when testing streaming.
Pull requests are welcome. By submitting one you agree that your contribution is licensed to MxU under the terms in LICENSE.md. The MxU name and logos are trademarks and are not covered by the license.