# How to Package Modly for Apple Silicon macOS: 7 Core Requirements Explained

> Learn the 7 core requirements for packaging Modly for Apple Silicon macOS, including ARM64, Electron-builder config, and embedded Python for DMG installers.

- Repository: [lightningpixel/modly](https://github.com/lightningpixel/modly)
- Tags: how-to-guide
- Published: 2026-08-20

---

**Modly requires an Apple Silicon Mac (`darwin/arm64`), a specific Electron-builder configuration, and an embedded Python runtime to produce a signed or unsigned DMG installer.**

Packaging Modly for Apple Silicon macOS follows a precise workflow defined in the `lightningpixel/modly` repository. The project explicitly targets `arm64` only, with Intel and universal builds intentionally excluded from scope. This guide covers every requirement based on the source code and architectural decisions documented in the repository.

## Target Architecture: Apple Silicon (arm64) Only

Modly's macOS support is strictly limited to Apple Silicon. The architectural decision record at [`arch/decisions/APPLE-SILICON-SUPPORT.md`](https://github.com/lightningpixel/modly/blob/main/arch/decisions/APPLE-SILICON-SUPPORT.md) explicitly states that Intel-based Macs and universal binaries are out of scope.

This constraint simplifies the build pipeline and reduces maintenance overhead. You must run the packaging process on an `arm64` host—either a physical Apple Silicon Mac or the `macos-latest` GitHub Actions runner used in CI.

## Build the JavaScript Front-End

Before packaging, compile the Electron UI using the standard build script. The [`package.json`](https://github.com/lightningpixel/modly/blob/main/package.json) defines:

```bash
npm run build

```

This step generates the production-ready front-end assets that `electron-builder` will bundle into the final application. The build command is invoked automatically by the packaging script, but running it separately helps verify the UI compiles without errors.

## Prepare the Embedded Python Runtime

Modly bundles a Python runtime rather than requiring system Python. The `prepare-resources` script handles this:

```bash
npm run prepare-resources

```

Under the hood, this executes [`scripts/download-python-embed.js`](https://github.com/lightningpixel/modly/blob/main/scripts/download-python-embed.js), which fetches pre-built Python binaries and places them in `resources/python-embed/`. These files are marked as **extra resources** in the macOS build configuration, ensuring they ship inside the `.app` bundle.

## Configure Electron-Builder for Apple Silicon

The [`package.json`](https://github.com/lightningpixel/modly/blob/main/package.json) contains the macOS-specific build configuration at lines 108-119:

```json
"mac": {
  "target": "dmg",
  "icon": "assets/icon.icns",
  "identity": null,
  "extraResources": [
    {
      "from": "resources/python-embed",
      "to": "python-embed",
      "filter": ["**/*"]
    }
  ]
}

```

Key settings:

- **`target: "dmg"`** – Produces a disk image installer
- **`icon`** – Custom macOS icon in `.icns` format
- **`identity: null`** – Defaults to unsigned builds
- **`extraResources`** – Embeds the Python runtime into `Modly.app/Contents/resources/`

## Run the Packaging Script

The consolidated command for Apple Silicon packaging is:

```bash
npm run package:mac

```

This expands to:

```bash
cross-env CSC_IDENTITY_AUTO_DISCOVERY=false \
  npm run build && \
  npm run prepare-resources && \
  electron-builder --mac --arm64

```

The `CSC_IDENTITY_AUTO_DISCOVERY=false` environment variable prevents `electron-builder` from attempting automatic code signing discovery, keeping builds reproducible across environments.

## Host Requirements: ARM64 Native Execution

You cannot cross-compile Modly for Apple Silicon from an Intel Mac. The build must execute on:

- A physical Apple Silicon Mac (M1/M2/M3/M4)
- GitHub Actions `macos-latest` runner (already ARM64 as of the CI definition)

The workflow at [`.github/workflows/ci.yml`](https://github.com/lightningpixel/modly/blob/main/.github/workflows/ci.yml) (lines 44-56) demonstrates the official build environment.

## Optional Code Signing

For distribution outside the App Store, provide a valid **Apple Developer ID**:

| Signing Approach | Configuration |
|----------------|---------------|
| **Unsigned (default)** | Leave `mac.identity: null` in [`package.json`](https://github.com/lightningpixel/modly/blob/main/package.json) |
| **Signed** | Set `mac.identity` to your Developer ID or export `CSC_NAME` |

Set the `CSC_NAME` environment variable before packaging, or modify [`package.json`](https://github.com/lightningpixel/modly/blob/main/package.json) directly:

```json
"mac": {
  "identity": "Developer ID Application: Your Name (TEAM_ID)"
}

```

Unsigned builds are suitable for personal use or internal distribution. Signed builds avoid Gatekeeper warnings for end users.

## Complete Packaging Workflow

Execute these commands in sequence on an Apple Silicon Mac:

```bash

# Install dependencies

npm install

# Build the Electron front-end

npm run build

# Download and embed Python runtime

npm run prepare-resources

# Package Apple Silicon DMG (unsigned by default)

npm run package:mac

```

After completion, find the installer at:

```

dist/Modly-<version>-arm64.dmg

```

## File Reference Guide

| File Path | Purpose |
|-----------|---------|
| [`package.json`](https://github.com/lightningpixel/modly/blob/main/package.json) | Defines `package:mac` script, DMG target, extra resources, signing options |
| [`arch/decisions/APPLE-SILICON-SUPPORT.md`](https://github.com/lightningpixel/modly/blob/main/arch/decisions/APPLE-SILICON-SUPPORT.md) | Architectural decision record limiting support to Apple Silicon |
| [`scripts/download-python-embed.js`](https://github.com/lightningpixel/modly/blob/main/scripts/download-python-embed.js) | Fetches pre-built Python binaries for bundling |
| `resources/python-embed/` | Local destination for embedded Python runtime |
| [`.github/workflows/ci.yml`](https://github.com/lightningpixel/modly/blob/main/.github/workflows/ci.yml) | CI pipeline validating Apple Silicon builds |

## Summary

- **Architecture**: Apple Silicon (`arm64`) only—no Intel or universal builds
- **Front-end**: `npm run build` compiles the Electron UI
- **Python runtime**: `npm run prepare-resources` embeds pre-built binaries
- **Packaging**: `npm run package:mac` invokes `electron-builder --mac --arm64`
- **Host**: Must run on ARM64 macOS hardware or CI runner
- **Signing**: Optional; defaults to unsigned with `identity: null`

## Frequently Asked Questions

### Can I build Modly for Intel Macs or create a universal binary?

No. The project explicitly excludes Intel and universal builds per the architectural decision record at [`arch/decisions/APPLE-SILICON-SUPPORT.md`](https://github.com/lightningpixel/modly/blob/main/arch/decisions/APPLE-SILICON-SUPPORT.md). Supporting only Apple Silicon simplifies the build system and reduces binary size.

### Where does the embedded Python runtime come from?

The [`scripts/download-python-embed.js`](https://github.com/lightningpixel/modly/blob/main/scripts/download-python-embed.js) script downloads pre-built Python binaries when you run `npm run prepare-resources`. These are copied into `resources/python-embed/` and bundled as extra resources in the final `.app`.

### Why is my build failing with code signing errors?

The `package:mac` script sets `CSC_IDENTITY_AUTO_DISCOVERY=false` to prevent automatic signing attempts. Either leave `mac.identity` as `null` for unsigned builds, or provide a valid Apple Developer ID in the configuration.

### Can I run the packaging process on GitHub Actions?

Yes. The repository's CI workflow at [`.github/workflows/ci.yml`](https://github.com/lightningpixel/modly/blob/main/.github/workflows/ci.yml) builds on `macos-latest`, which provides native Apple Silicon runners. This validates that the packaging process works without local hardware.