Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0a6a420
build(ts): bootstrap strict TypeScript toolchain (stage 0)
pierre-jochem Jun 4, 2026
765420b
refactor(ts): migrate CJS server leaves to TypeScript (stage 1)
pierre-jochem Jun 4, 2026
74cad32
refactor(ts): migrate weather/calendar leaves to TypeScript (stage 2)
pierre-jochem Jun 4, 2026
55e62f9
refactor(ts): migrate default-module node_helpers to TypeScript (stag…
pierre-jochem Jun 4, 2026
80dc3cd
refactor(ts): migrate browser leaf globals to TypeScript (stage 4)
pierre-jochem Jun 4, 2026
d6edf84
refactor(ts): migrate browser core module.js + loader.js (stage 5)
pierre-jochem Jun 4, 2026
702a612
refactor(ts): migrate default-module browser entries to TypeScript (s…
pierre-jochem Jun 4, 2026
7462cd1
refactor(ts): migrate roots, entries + alias-resolver (stage 7)
pierre-jochem Jun 4, 2026
8fd1609
build(ts): finalize strict TypeScript migration (stage 8)
pierre-jochem Jun 4, 2026
d3e9589
build(ts): enable noUncheckedIndexedAccess + exactOptionalPropertyTypes
pierre-jochem Jun 4, 2026
f530cf3
docs(ts): note ultra-strict flags are enabled in src/README
pierre-jochem Jun 4, 2026
63ee8b1
refactor(ts): replace Class.extend with a real TypeScript class in mo…
pierre-jochem Jun 4, 2026
2585d20
refactor(ts): replace Class.extend with a real TypeScript class in no…
pierre-jochem Jun 4, 2026
8fc0de3
refactor(ts): shrink class.js to cloneObject after retiring the Class…
pierre-jochem Jun 4, 2026
69da932
refactor(ts): replace require() with ES imports across server sources
pierre-jochem Jun 4, 2026
ecc9eb8
refactor(ts): re-enable no-require-imports + no-empty-function lint r…
pierre-jochem Jun 4, 2026
9bba3e1
types(ts): add MMConfig interface for the global config object
pierre-jochem Jun 4, 2026
507543f
types(ts): type the weather subsystem (WeatherDataPoint / WeatherConf…
pierre-jochem Jun 4, 2026
c97eb4b
types(ts): type the calendar subsystem (CalendarEvent / CalendarConfig)
pierre-jochem Jun 4, 2026
be08bbe
types(ts): type the newsfeed subsystem (NewsItem / NewsfeedConfig)
pierre-jochem Jun 4, 2026
32b8bb3
types(ts): type Module instances + DOM in the browser core (main/load…
pierre-jochem Jun 4, 2026
90d989e
types(ts): type the alert/NotificationFx boundary + tidy remaining mo…
pierre-jochem Jun 4, 2026
a8622e9
deps: update package.json and lockfile
pierre-jochem Jun 4, 2026
5fe61de
fix(ts): type require.cache/require.resolve in the browser-shims requ…
pierre-jochem Jun 4, 2026
8be412b
chore(ts): remove unused code; enforce noUnusedLocals/noUnusedParameters
pierre-jochem Jun 4, 2026
c71e41e
refactor(ts): group src/ by concern (server/client/modules/...)
pierre-jochem Jun 4, 2026
160b9f8
build: switch package manager from npm to Yarn 4 (Corepack)
pierre-jochem Jun 4, 2026
613035f
docs: add CLAUDE.md, document TypeScript + Yarn in READMEs
pierre-jochem Jun 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ insert_final_newline = true
max_line_length = 250
trim_trailing_whitespace = true

[*.{js,json}]
[*.{js,ts,json}]
indent_size = 4
indent_style = tab
4 changes: 3 additions & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,6 @@ The `package.json` scripts expose finer-grained test commands:
- `test:calendar` – run the legacy calendar debug helper
- `test:css`, `test:markdown`, `test:prettier`, `test:spelling`, `test:js` – lint-only scripts that enforce formatting, spelling, markdown style, and ESLint.

You can invoke any script with `node --run <script>` (or `npm run <script>`). Individual files can still be targeted directly, e.g. `npx vitest run tests/e2e/env_spec.js`.
You can invoke any script with `node --run <script>` (or `yarn <script>`). Individual files can still be targeted directly, e.g. `yarn vitest run tests/e2e/env_spec.js`.

This project uses [Yarn](https://yarnpkg.com) (pinned via the `packageManager` field and Corepack). Run `corepack enable` once, then `node --run install-mm:dev` to install dependencies.
8 changes: 4 additions & 4 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ body:
If you can't provide this information, please provide the following:
- MagicMirror² version: Can be found in the `package.json` file. Please use the latest version before reporting a bug.
- Node version: Run `node -v` to find out. Make sure it's version 20 or later (recommended is 22).
- npm version: Run `npm -v` to find out.
- Yarn version: Run `yarn -v` to find out.
- Platform: Are you using a Raspberry Pi (2/3/4/5), Windows, Mac, Linux, Docker, or something else?
value: |
MagicMirror² version:
Node version:
npm version:
MagicMirror² version:
Node version:
Yarn version:
Platform:
validations:
required: true
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/automated-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: lts/*
cache: "npm"
- name: "Enable Corepack"
run: corepack enable
- name: "Install dependencies"
run: |
node --run install-mm:dev
Expand Down Expand Up @@ -55,13 +56,14 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
check-latest: true
cache: "npm"
- name: "Enable Corepack"
run: corepack enable
- name: "Install MagicMirror²"
run: |
node --run install-mm:dev
- name: "Install Playwright browsers"
run: |
npx playwright install --with-deps chromium
yarn playwright install --with-deps chromium
- name: "Prepare environment for tests"
run: |
# Fix chrome-sandbox permissions:
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/electron-rebuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
check-latest: true
- name: Enable Corepack
run: corepack enable
- name: Install MagicMirror
run: node --run install-mm
- name: Install @electron/rebuild
run: npm install @electron/rebuild
run: yarn add @electron/rebuild
- name: Install test library (serialport) to be rebuilt
run: npm install serialport
run: yarn add serialport
- name: Run electron-rebuild
run: npx electron-rebuild
run: yarn electron-rebuild
continue-on-error: false
1 change: 0 additions & 1 deletion .github/workflows/release-notes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: lts/*
cache: "npm"
- name: "Create Markdown content"
run: |
export GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/spellcheck.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ jobs:
with:
node-version: lts/*
check-latest: true
cache: "npm"
- name: Enable Corepack
run: corepack enable
- name: Install dependencies
run: |
node --run install-mm:dev
Expand Down
74 changes: 72 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,79 @@ config
# Ignore positions file (#3518)
js/positions.js

# Ignore lock files other than package-lock.json
# TypeScript build output (compiled from src/*.ts by `npm run build`).
# Source of truth lives in src/; never edit or commit these compiled artifacts.
*.tsbuildinfo
/js/**/*.js.map
/defaultmodules/**/*.js.map
/serveronly/**/*.js.map
/clientonly/**/*.js.map
/translations/**/*.js.map
# Compiled outputs, listed per migrated file as each source moves to src/:
/js/deprecated.js
/js/http_fetcher.js
/js/server_functions.js
/js/utils.js
/defaultmodules/utils.js
/defaultmodules/weather/provider-utils.js
/defaultmodules/weather/providers/*.js
/defaultmodules/weather/weatherobject.js
/defaultmodules/weather/weatherutils.js
/defaultmodules/calendar/calendarfetcherutils.js
/defaultmodules/calendar/calendarutils.js
/defaultmodules/calendar/calendarfetcher.js
/defaultmodules/calendar/node_helper.js
/defaultmodules/newsfeed/newsfeedfetcher.js
/defaultmodules/newsfeed/node_helper.js
/defaultmodules/weather/node_helper.js
/defaultmodules/updatenotification/git_helper.js
/defaultmodules/updatenotification/update_helper.js
/defaultmodules/updatenotification/node_helper.js
/js/class.js
/js/logger.js
/js/defaults.js
/js/animateCSS.js
/js/socketclient.js
/js/translator.js
/translations/translations.js
/defaultmodules/defaultmodules.js
/js/module.js
/js/loader.js
/defaultmodules/alert/alert.js
/defaultmodules/alert/notificationFx.js
/defaultmodules/calendar/calendar.js
/defaultmodules/clock/clock.js
/defaultmodules/compliments/compliments.js
/defaultmodules/helloworld/helloworld.js
/defaultmodules/newsfeed/newsfeed.js
/defaultmodules/updatenotification/updatenotification.js
/defaultmodules/weather/weather.js
/js/main.js
/js/vendor.js
/js/app.js
/js/server.js
/js/electron.js
/js/node_helper.js
/js/releasenotes.js
/js/ip_access_control.js
/js/check_config.js
/js/systeminformation.js
/js/alias-resolver.js
/clientonly/index.js
/serveronly/index.js
/serveronly/watcher.js
/defaultmodules/calendar/debug.js

# Ignore lock files other than yarn.lock
pnpm-lock.yaml
yarn.lock
package-lock.json

# Yarn (node-modules linker; release/cache not committed, plugins are)
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/sdks
.pnp.*

# Vitest temporary test files
tests/**/.tmp/
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
*.js
*.mjs
*.ts
.husky/pre-commit
.prettierignore
.claude
/config
/coverage
package-lock.json
Expand Down
3 changes: 3 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
nodeLinker: node-modules

enableTelemetry: false
106 changes: 106 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# CLAUDE.md

Guidance for working in this repository. MagicMirror² is a modular smart-mirror
platform. This copy is a **fork** that diverges from upstream in two big ways:
all source is **TypeScript**, and the package manager is **Yarn 4**.

## Source lives in `src/` — never edit the output

Every source file is authored as `.ts` under `src/` and compiled **in place** back
into the legacy runtime directories. The emitted `.js`/`.js.map` are **git-ignored**.

| Edit here (source) | Do NOT edit (generated) |
| ---------------------------- | ------------------------ |
| `src/server/*.ts` | `js/*.js` |
| `src/client/*.ts` | `js/*.js` |
| `src/modules/<feature>/*.ts` | `defaultmodules/**/*.js` |
| `src/serveronly/*.ts` | `serveronly/*.js` |
| `src/clientonly/*.ts` | `clientonly/*.js` |
| `src/translations/*.ts` | `translations/*.js` |
| `src/types/*.d.ts` | — |

The build is seven per-concern `tsc -b` projects (DOM vs Node lib split, one
`rootDir → outDir` mapping each). Full details, the cross-project ambient-declaration
seams, and the editing rules are in **[`src/README.md`](src/README.md)** — read it
before touching `src/` or the tsconfigs.

Exception: `js/positions.js` is a hand-maintained tracked `.js` file (not compiled
from TS, intentionally eslint-ignored). Leave it as JS.

### Hard runtime invariants (breaking these breaks the mirror silently)

- **Browser `<script>` files must never gain a top-level `import`/`export`.** That
would turn them into modules and break global `<script>` loading. They share state
via globals typed in `src/types/*.d.ts`. eslint + the JSDOM specs guard this.
- **Runtime assets stay in `defaultmodules/`, not `src/`.** Templates (`.njk`), CSS,
translation JSON, SVG faces, etc. are not compiled — they are tracked in the output
dir. Moving them into `src/` deletes them from the runtime and modules render empty.
- **Community modules under `modules/` are forever plain JS.** The
`Module.register(...)` contract, runtime `<script>` injection, and dynamic
`require()` of a module's `node_helper.js` must keep working byte-for-behavior.
- Keep dual-world files' `if (typeof module !== "undefined") module.exports = X` guard.
- Filenames in the output dirs are contractual (`index.html` `<script src>`,
`package.json` `main`, dynamic `require`). Don't rename emitted files.

## Package manager: Yarn 4 (Corepack), not npm

Pinned via the `packageManager` field; run `corepack enable` once. `nodeLinker:
node-modules` (flat node_modules, no PnP). `yarn.lock` is committed; there is no
package-lock.json.

Two gotchas when editing `package.json` or CI:

- **Yarn does not run npm-style `pre*`/`post*` user scripts** (and neither does
`node --run`). The "build before X" step is therefore **inlined** as
`node --run build && ...` into `config:check`, `server`, `start`, `start:dev`, and
the `test:*` scripts. Do **not** reintroduce the old `pre*` hooks — they silently
won't run. Yarn does honor `postinstall`, `prepare`, `prepack`.
- **Yarn does not auto-install peer dependencies** (npm did). A missing peer surfaces
as `ERR_MODULE_NOT_FOUND`; add it explicitly to `devDependencies`.

## Commands

Scripts are package-manager-agnostic; use `yarn <script>` or `node --run <script>`.

```sh
corepack enable # one-time: activate the pinned Yarn
node --run install-mm:dev # install deps + Playwright chromium + build
node --run install-mm # production install (yarn workspaces focus --production)

node --run build # compile src/ (tsc -b, seven projects)
node --run test # build + full vitest suite
node --run test:unit # build + unit tests only
node --run test:e2e # build + Playwright e2e
node --run test:js # eslint
node --run test:prettier # prettier --check
node --run typecheck # tsc against the combined editor tsconfig.json

node --run server # build + server-only mode
node --run start # build + electron (use start:wayland/x11/windows variants)
```

## Verify before declaring done

Run, in order: `node --run build` → `node --run test:js` → `node --run test:prettier`
→ `node --run test:unit` → `node --run test:e2e`. All must pass.

Known pre-existing failures (NOT regressions you introduced):

- `tests/unit/classes/systeminformation_spec.js` fails on macOS — it asserts
`platform: linux`. Passes on the Linux CI runners.
- `node --run test:spelling` reports ~24 unknown words that are legitimate source
vocabulary (British `-ise` spellings, locale display names, and the `yr` provider's
concatenated weather-code identifiers). Spellcheck runs only quarterly in CI.

## Code style

TypeScript is linted/formatted by **eslint** (`@stylistic`): **tabs**, **double
quotes**, **semicolons**. `.ts` is prettier-ignored (eslint owns it); other files use
prettier. `@typescript-eslint/no-explicit-any` is intentionally off — dynamic external
boundaries (config, API payloads, DOM, cross-project seams) are typed `any`.

## Upstream merges

Upstream ships `.js`; this fork ships `src/*.ts`. When pulling an upstream change to a
file, apply the diff to the corresponding `src/**/*.ts` source, not the generated
output. Keeping `src/` 1:1 with upstream paths keeps three-way merges tractable.
7 changes: 3 additions & 4 deletions Collaboration.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ Are done by
- [ ] use a clean environment (e.g. container)
- [ ] clone this repository with the new `master` branch and `cd` into the local repository directory
- [ ] **Method 1 (recommended): With browser and 2FA**
- [ ] execute `npm login` which will open a browser window
- [ ] execute `yarn npm login` which will open a browser window
- [ ] log in with your npm credentials and enter your 2FA code
- [ ] execute `npm publish`
- [ ] execute `yarn npm publish`
- [ ] **Method 2 (fallback for headless environments): With token (bypasses 2FA)**
- [ ] ⚠️ Note: This method bypasses 2FA and should only be used when a browser is not available
- [ ] goto `https://www.npmjs.com/settings/<username>/tokens/` and click `generate new token`
Expand All @@ -80,6 +80,5 @@ Are done by

```bash
NPM_TOKEN="npm_xxxxxx"
npm set "//registry.npmjs.org/:_authToken=$NPM_TOKEN"
npm publish
YARN_NPM_AUTH_TOKEN="$NPM_TOKEN" yarn npm publish
```
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,30 @@ MagicMirror² focuses on a modular plugin system and uses [Electron](https://www

For the full documentation including **[installation instructions](https://docs.magicmirror.builders/getting-started/installation.html)**, please visit our dedicated documentation website: [https://docs.magicmirror.builders](https://docs.magicmirror.builders).

## This fork: TypeScript + Yarn

This fork differs from upstream in two ways that matter for development:

- **All source is authored in TypeScript** under [`src/`](src/README.md) and compiled
**in place** back into the runtime directories (`js/`, `defaultmodules/`, …); the
emitted `.js` is git-ignored. The runtime behaviour is unchanged — see
[`src/README.md`](src/README.md) for the layout and build model.
- **The package manager is [Yarn](https://yarnpkg.com) 4** (pinned via `packageManager`
and Corepack), not npm.

Quick start for development:

```sh
corepack enable # activate the pinned Yarn
node --run install-mm:dev # install deps, Playwright chromium, and build
node --run test # build + run the full test suite
node --run server # build + start in server-only mode
```

Any script runs with `yarn <script>` or `node --run <script>`. See
[`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md) and [`CLAUDE.md`](CLAUDE.md) for
more. Production installs use `node --run install-mm`.

## Links

- Website: [https://magicmirror.builders](https://magicmirror.builders)
Expand Down
Loading
Loading