Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 22 additions & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
# Contributing to Blockly

Want to contribute? Great! Head over to the [Blockly Developers site](https://developers.google.com/blockly/guides/modify/contributing) for information on how to contribute.
Want to contribute? Great! The full contributor documentation lives on the
[Blockly docs site](https://docs.blockly.com/guides/contribute/).

That documentation is generated from this repository, so you can also read the source
directly under [`packages/docs/docs/guides/contribute/`](../packages/docs/docs/guides/contribute/).
The pages you are most likely to need:

| Topic | Source file |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| Style guide | [`core/style_guide.mdx`](../packages/docs/docs/guides/contribute/core/style_guide.mdx) |
| Commit messages | [`get-started/commits.mdx`](../packages/docs/docs/guides/contribute/get-started/commits.mdx) |
| Writing a good PR | [`get-started/write_a_good_pr.mdx`](../packages/docs/docs/guides/contribute/get-started/write_a_good_pr.mdx) |
| Writing a good issue | [`get-started/write_a_good_issue.mdx`](../packages/docs/docs/guides/contribute/get-started/write_a_good_issue.mdx) |
| Building and compiling | [`core/building_and_compilation/building.mdx`](../packages/docs/docs/guides/contribute/core/building_and_compilation/building.mdx) |
| Unit testing | [`core/testing/unit_testing.mdx`](../packages/docs/docs/guides/contribute/core/testing/unit_testing.mdx) |
| Localization | [`core/localization_and_translation.mdx`](../packages/docs/docs/guides/contribute/core/localization_and_translation.mdx) |
| A tour of core | [`core/core-architecture/core-tour.mdx`](../packages/docs/docs/guides/contribute/core/core-architecture/core-tour.mdx) |
| Adding a plugin | [`core/plugins/add_a_plugin.mdx`](../packages/docs/docs/guides/contribute/core/plugins/add_a_plugin.mdx) |
| Plugin naming | [`core/plugins/naming.mdx`](../packages/docs/docs/guides/contribute/core/plugins/naming.mdx) |

For a short orientation to the repository layout, commands, and conventions, see
[`AGENTS.md`](../AGENTS.md).
154 changes: 127 additions & 27 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,138 @@
# Code review guidelines

Repository layout, commands, and coding conventions are documented in
[`AGENTS.md`](../AGENTS.md) and the per-package `AGENTS.md` files under `packages/`.
Read those for context; this file covers only what is specific to reviewing a pull
request.

Note that this is a monorepo. Paths below are given in full, because the same filename
can exist in more than one package.

## General principles
- **Style:** Suggest `npm run format` or `npm run lint:fix` for formatting issues; do not comment on individual style nits.

- **Style:** Suggest `npm run format` (from the repo root) or `npm run lint:fix` for
formatting issues; do not comment on individual style nits.
- **Patterns:** Enforce existing Blockly patterns and official docs over new conventions.
- **Documentation:** Prefer linking to [Blockly Dev Docs](https://developers.google.com/blockly) over duplicating content in comments.
- **TSDoc:** Public APIs require TSDoc for behavior, params, and returns. Do not include implementation details or historical context unless essential.
- **Documentation:** Prefer linking to the [Blockly docs](https://docs.blockly.com) over
duplicating content in comments. Flag any **new** link to
`developers.google.com/blockly`; that site is stale. Existing ones are legacy and
can be left alone unless the PR is already touching them.
- **TSDoc:** Public APIs require TSDoc for behavior, params, and returns. Do not include
implementation details or historical context unless essential.

## Project ownership

This repository is the canonical upstream, maintained by the Raspberry Pi Foundation. It

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe specify "RaspberryPiFoundation/blockly" so that "this repository" doesn't carry over to forks

is not a fork of `google/blockly`. Do not suggest changes on the basis that this is a
fork, that upstream should be consulted, or that a change belongs in a Google-maintained
repository.

`Copyright <year> Google LLC` headers on existing files are correct and historical —
never ask for them to be changed. Only new files use the Raspberry Pi Foundation
copyright. See [`AGENTS.md`](../AGENTS.md#project-ownership).

## Pull request descriptions

The description should be concise: what changed, why, and anything a reviewer genuinely
needs, such as breaking changes or how to verify non-obvious behavior.

Do not ask authors to expand a description that already covers those things. A short,
complete description is correct and preferable. In particular, do not request a
rationale narrative, a file-by-file walkthrough, or a restatement of the diff.

Do flag a description that is genuinely missing the *why*, or one that omits a breaking
change.

## Generated files

None of these are hand-written, so do not review their contents line by line or ask for
edits to them directly. If one looks wrong, the fix belongs in its source.

The question to ask is not "is this file generated?" but **"should this file be in this
pull request at all, and does it look regenerated rather than hand-edited?"**

### Expected to appear — review the source, not the file

| File | Regenerated by |
| ----------------------------- | ------------------- |
| `packages/blockly/msg/json/*` | `npm run messages` |
| `package-lock.json` | npm |

Do not nitpick their contents. **Do** flag them if they look hand-edited rather than
regenerated — for example `msg/json/en.json` changing without a corresponding change to
`packages/blockly/msg/messages.js`, an edit to a non-English locale file (those come from
TranslateWiki), or a lockfile change in a PR that touches no dependencies. In those cases
ask for the file to be regenerated, not patched.

### Should not appear at all — flag if present

| File | Why |
| ------------------------------- | ------------------------------------------------------- |
| `**/CHANGELOG.md` | Written by Lerna at release time, not in feature PRs |
| `packages/docs/docs/reference/**` | Generated from core TSDoc; gitignored |
| `**/dist/**`, `**/build/**` | Build output; gitignored |

A change to any of these in a normal pull request means something has gone wrong, and is
worth a comment. A hand-written `CHANGELOG.md` entry in particular should be flagged:
release notes come from conventional commit messages, so the fix is to write a good
commit message rather than to edit the changelog. The last three are gitignored
entirely, so their presence means they were force-added.

The exception is a release pull request, where these files changing is the whole point.

## Localization

- All user-visible strings must use `Blockly.Msg`.
- New strings must be added to `msg/messages.js`, `msg/json/qqq.json`, and `msg/json/en.json`.
- Link [this guide](https://developers.google.com/blockly/guides/contribute/core/add_localization_token) if strings are missing or misplaced.
- PRs that attempt to add translations for non-English strings should be redirected to TranslateWiki via the ([translation guide](hhttps://developers.google.com/blockly/guides/contribute/core/translating)).
- New strings are hand-written **only** in `packages/blockly/msg/messages.js`.
`packages/blockly/msg/json/en.json` and `packages/blockly/msg/json/qqq.json` are then
regenerated by `npm run messages`.
- A pull request that adds a string should therefore contain changes to all three files.
If `en.json` or `qqq.json` is missing, the author likely forgot to run
`npm run messages`; if they were edited by hand, ask for them to be regenerated
instead.
- Link the
[localization guide](../packages/docs/docs/guides/contribute/core/localization_and_translation.mdx)
if strings are missing or misplaced.
- PRs that attempt to add translations for non-English strings should be redirected to
TranslateWiki, using the same guide.

## Plugins (`packages/plugins/*`)

- **Test files must be named `*.mocha.js`.** The plugin test runner silently finds no
tests and exits successfully if they are named anything else, so a green CI run does
not prove the tests ran. Flag any new plugin test file that does not use this suffix.
- **New plugins must be TypeScript.** Flag a newly added plugin written in JavaScript;
the scaffolding generator defaults to JS, so this is an easy one to miss
(`npx @blockly/create-package plugin <name> --typescript`). Existing JavaScript plugins
are legacy — do not ask for them to be converted.
- `blockly` must be a **peer** dependency, never a direct dependency. Flag imports that
reach into deep paths inside the core package rather than its public entry points.
- Package names follow the type-based convention in
[the plugin naming guide](../packages/docs/docs/guides/contribute/core/plugins/naming.mdx). Flag new packages that do not
follow it.
- Hand-edited `version` fields or `CHANGELOG.md` entries should be flagged; both are
managed by Lerna.

## Breaking changes

### Policy
- A breaking change is any non-backwards-compatible change to public APIs, behavior, UI, or browser requirements.
- **Avoid:** Prefer deprecation with migration paths over removal.

- The definition of a breaking change, and the full list of what does and does not count,
is in
[`packages/blockly/AGENTS.md`](../packages/blockly/AGENTS.md#breaking-changes).
Use that list rather than a separate one here, so the two cannot drift apart.
- **Avoid:** Prefer deprecation with migration paths over removal.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd drop the "avoid" here, as it kind of counteracts the "prefer"

- **Compatibility:** Must support Safari 15.4+, latest Chrome, and latest Firefox.
Comment thread
gonfunko marked this conversation as resolved.
- **Identification:** Flag breaking changes unless all of the following are true:
1. PR description explicitly notes it.
2. Commit type includes `!` (e.g., `feat!:`).
3. Target branch is not `main`.

### Breaking
- Removing/renaming public methods, properties, or classes.
- Changing signatures or behavior of existing public methods.
- Adding required methods to public interfaces.
- New keyboard shortcuts or context menu items (potential developer conflicts).
- DOM restructures affecting external CSS/JS.
- Changes to build output/consumption (e.g., ESM-only).
- Changes that affect the output of serialization.

### Non-breaking (do not flag)
- Additive changes (new methods/properties).
- Internal refactoring (including items marked `@internal`).
- Tooling/workflow changes.
- Changes to unreleased code (non-`main` feature branches).

### Identification

Flag breaking changes unless **all** of the following are true:

1. The PR description explicitly notes it.
2. The commit type includes `!` (e.g., `feat!:`).
3. The target branch is not `main`.

All three are required. Breaking changes are never merged straight to `main`: they land
on a version branch (for example `v14`) and are merged to `main` together when that
version is released. So a properly labelled breaking change that still targets `main` is
worth flagging — it is almost always aimed at the wrong branch.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ build-debug.log
/nbproject/private/
tsdoc-metadata.json
.vscode
.claude/

# All packages
build/
Expand Down
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
.prettierrc.js
eslint.config.mjs
package.json
.claude/

# Symlinks to AGENTS.md. Formatting these in place would replace the symlink
# with a regular file.
**/CLAUDE.md

# Package build aritifacts, etc.
**/dist/*
Expand Down
173 changes: 173 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# AGENTS.md

## Project ownership

Blockly is maintained by the **Raspberry Pi Foundation**. This repository,
`RaspberryPiFoundation/blockly`, is the canonical upstream. It is **not** a fork of
`google/blockly`, and there is no separate Google-maintained version that this one tracks
or defers to.

Blockly was originally developed at Google, so a lot of legacy remains and it is easy to
conclude otherwise. Two things in particular are not evidence of ownership:

- Most existing files carry a `Copyright <year> Google LLC` header. **Leave them alone.**
Only new files get the Raspberry Pi Foundation copyright.
- Several hundred links to `developers.google.com/blockly` are still embedded in TSDoc
and comments. They are stale. Do not add new ones.

When adding a reference or link, use the current locations:

| For | Use |
| ----------------- | --------------------------------------------------------- |
| Source repository | `https://github.com/RaspberryPiFoundation/blockly` |
| Issues | `https://github.com/RaspberryPiFoundation/blockly/issues` |
| Documentation | `https://docs.blockly.com` |
| Project home | `https://blockly.com` |

The npm package name is unchanged: the core library is still published as `blockly`.

## Repository structure

This is an npm + Nx monorepo. Workspaces are `packages/*` and `packages/plugins/*`.

| Path | Package name | What it is |
| -------------------- | -------------- | ------------------------------------------------------------------------------- |
| `packages/blockly/` | `blockly` | The core library |
| `packages/plugins/*` | `@blockly/*` | First-party plugins (fields, themes, workspace add-ons) and their build tooling |
| `packages/docs/` | `blockly-docs` | The Docusaurus developer documentation site |

Detailed guidance lives next to the code it describes. Read the relevant one before working in that area, rather than loading all of them:

- [`packages/blockly/AGENTS.md`](packages/blockly/AGENTS.md) — core library
- [`packages/plugins/AGENTS.md`](packages/plugins/AGENTS.md) — plugins
- [`packages/docs/AGENTS.md`](packages/docs/AGENTS.md) — documentation site

## Commands

Run these from the repo root. Root scripts fan out across workspaces via Nx.

```bash
npm ci # Install. Re-run after any pull that changes package-lock.json.

npm run build # Build every package except the docs site
npm run build:all # Build everything, including the docs site
npm run build:docs # Docs site only

npm run test # Full test suite across all packages. Slow.

npm run lint # ESLint across all workspaces
npm run lint:fix
npm run format # Prettier write, whole repo
npm run format:check

npm run clean # Reset the Nx cache and clean every package
```

To work on a single package, either `cd` into it and use its own scripts, or target it
with Nx from the root. The Nx project name is the package's `name` field, which for
plugins is often not the same as the directory name — run `npx nx show projects` to list
them rather than guessing.

```bash
npx nx show projects
npx nx run blockly:test
npx nx run @blockly/field-slider:test
npx nx run-many -t build --projects=@blockly/field-slider
```

Two things to watch out for:

- `format` and `format:check` exist **only** at the root. Prettier is configured once
for the whole repo, so there is no per-package equivalent.
- `build`, `test`, `clean`, `lint`, and `start` exist at both levels and mean different
things. At the root they fan out through Nx; inside a package they run that package's
own tooling.

## Shared configuration

Tooling is configured once at the root and covers every package. Do not add per-package
copies of these:

- `eslint.config.mjs` — a single flat config with per-package `files` sections
- `.prettierrc.js` — shared base plus `overrides` for core, plugins, and docs, which
each use different settings
- `nx.json` — target defaults and caching
- `lerna.json` — versioning and publishing
- `commitlint.config.mjs` — conventional commit rules

## Commits and pull requests

Commits follow the conventional commit spec, enforced by commitlint. The type should be
one of `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `refactor`, `release`, `revert`,
or `test`.

Breaking changes must append `!` to the type (for example `feat!:`) **and** be called out
in the pull request description. See [`packages/blockly/AGENTS.md`](packages/blockly/AGENTS.md)
for what counts as a breaking change.

## Pull request descriptions

Keep them short. A reviewer should be able to read the description in well under a
minute. The template in `.github/PULL_REQUEST_TEMPLATE.md` asks for the right things —
fill it in briefly rather than expanding it.

Cover:

- **What changed** — a short summary of the change.
- **Why** — the problem it solves. Link the issue rather than restating it.
- Anything a reviewer genuinely needs: breaking changes, migration notes, or how to
verify behavior that isn't obvious from the diff.

Do not write a narrative. Leave out the story of how you arrived at the solution, the
approaches you tried and rejected, a file-by-file walkthrough of the diff, and any
restatement of what the code already says. Where the reasoning behind a non-obvious
decision matters, a sentence or two is enough — and it often belongs in a code comment
instead, where it will still be there in a year.

## Versioning and publishing

All packages share a single version line, managed by Lerna from the root
(`.github/workflows/publish.yml`). A release bumps only the packages that actually
changed, but they all move to the same version number. Git tags use the `blockly-v`
prefix.

Never hand-edit a `version` field in a `package.json`.

## Code conventions

These apply to every package. The code style has changed over time; use these
conventions even where the surrounding code does not.

- **New files** get the Apache-2.0 header with a Raspberry Pi Foundation copyright:

```ts
/**
* @license
* Copyright 2026 Raspberry Pi Foundation
* SPDX-License-Identifier: Apache-2.0
*/
```

Leave the copyright line alone on existing files.

- **Optional parameters** take plain names — `workspace`, not `opt_workspace`. The
linter still permits the `opt_` prefix so that legacy code keeps passing, but do not
add new uses of it.
- **Test-only exports** should be avoided. Where they are unavoidable, prefix them with
`testOnly_`.
- **Private and internal methods** do not take a trailing `_` suffix.
- **TSDoc** is required on all public APIs, covering behavior, params, and returns.
Implementation details belong in inline comments, not in TSDoc.
- **Inline comments** explain complex implementation details or gotchas. They are not a
changelog: do not record how the code used to work unless it explains a
backwards-compatibility workaround.

## Further reading

The contributor documentation is in this repository under
[`packages/docs/docs/guides/contribute/`](packages/docs/docs/guides/contribute/). Read
those files directly rather than following links out to the published site. Most useful:

- [Style guide](packages/docs/docs/guides/contribute/core/style_guide.mdx)
- [Commit messages](packages/docs/docs/guides/contribute/get-started/commits.mdx)
- [Writing a good PR](packages/docs/docs/guides/contribute/get-started/write_a_good_pr.mdx)
1 change: 1 addition & 0 deletions CLAUDE.md
Loading
Loading