Stable interface policy/Frontend

The stable interface policy for MediaWiki frontend code (CSS, JavaScript and HTML) defines what parts of the software are considered stable and safe for use by other components (gadgets that are following Wikimedia recommendations, MediaWiki extensions and skins). For guidelines on PHP, see stable interface policy. The frontend stable interface policy is maintained separately from the PHP stable interface policy due to the difference in audience and to this policy's focus on gadget developers. The eventual goal is to move this to Stable interface policy/Frontend.

While this documentation is in draft please feel free to dive into the talk page to debate any aspect of the text.

This document applies to MediaWiki developers. It is complemented and supported by a set of recommendations for developers of on-wiki code. Any changes here must be made with consideration to that document.

Terminology

 * See RFC 2119 to understand the language used in this policy to indicate requirement levels ("MAY", "MUST", "SHOULD").
 * "Wiki-hosted code" is defined as code that executes on Wikimedia projects, whose source code lives inside a page that is editable on wiki.
 * A "MediaWiki developer" is defined as someone who contributes code to the MediaWiki core code repository or one of its extensions or skins.
 * "Frontend code" is defined as any code that is written in JavaScript and CSS - this includes on-wiki scripts, and code in Wikimedia repositories (extensions, skins and core) unless stated.
 * The "codesearch tool" refers to codesearch.wmcloud.org.
 * The "global search tool" refers to global-search.toolforge.org.
 * "Caching implications" is used to describe the situation on Wikimedia production sites where old HTML markup is served to users alongside new styles. We cache HTML for a longer period than JavaScript and CSS assets. Caching implications apply to any page that is cached on the edge layer (typically any page that can be rendered by anonymous users excluding the special namespace). Explaining this in detail is out of scope for the document; for more information, see Readers/Web/Building features with cached HTML in mind.

Motivation
This policy is designed to make extensions more robust against changes in MediaWiki core, and provide more freedom for MediaWiki core code to evolve.

The motivation for this policy is twofold:


 * Offer guarantees to gadget developers and extension developers, providing guidance on what frontend code that they can safely rely upon.
 * Provide guarantees to developers working on MediaWiki core, telling them what aspects of the code they can safely change without having to worry about breaking extensions.

Ecosystem
Gadgets and user scripts (which will be referred to as wiki-hosted code) are key components of MediaWiki projects. However, up until now, frontend APIs (such as how wiki-hosted code should interact with source control provided code) have been ill-defined, leading to misunderstandings between developers when wiki-hosted code breaks. This situation also leads to code rot, and developers do not feel empowered to make changes as it's unclear how their changes will impact wiki-hosted code.

In addition, when wiki-hosted code breaks, it's not clear who can and will fix it.

This document aims to build agreements between Wikimedia staff, volunteer contributors (on Gerrit, GitHub and GitLab) and wiki-hosted code developers to lead to a better experience for all groups and to build trust and good faith between the groups.

History

 * [June 2023] Folding feedback from outside wiki into document
 * [May 2023] Targeted MediaWiki.org developers https://www.mediawiki.org/w/index.php?title=MediaWiki:Editpage-code-message
 * [March 2023] Revised format of document
 * [January 2023] Document was separated into User:Jdlrobson/Stable_interface_policy/frontend and Recommendations for gadget developers
 * [May 2022] Emailed engineering-all@wikimedia.org to request feedback
 * [Feb 2022] Emailed wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/hyperkitty/list/wikitech-l@lists.wikimedia.org/message/HLQSR7NCYJFKDBITBYSF2RRQJUEOP6PC/
 * [August 2021] This document began life in User:Jdlrobson/Extension:Gadget/Policy.

Guidelines around HTML markup
HTML markup is not a stable interface (unless explicitly stated). However, historically, gadget developers have been led to believe this, so MediaWiki developers have a responsibility to respect gadget developers' existing work by over-communicating any changes to HTML markup while this policy is rolled out. Making changes to HTML structure, or renaming classes and IDs as part of active development is to be expected, however MediaWiki developers are encouraged to over-communicate any changes to gadget developers and peers, particularly in projects which have high visibility or operate in the article namespace.

Wiki-hosted code MUST NOT reuse class names defined by MediaWiki developers for styling purposes as this can lead to misuse, misunderstandings and breakage (T213239, T287997) and instead should make use of their own class and styling rules using Extension:TemplateStyles.

In cases where it might be mutually beneficial for wiki-hosted code developers and MediaWiki developers to share code, for example for performance reasons, this MUST be documented in the source-controlled code using the  and   keywords and linking to the on-wiki discussion. HTML classes that do wish to be considered stable MUST add an inline comment indicating in which MediaWiki version they were introduced using the  annotation and must follow the deprecation process in the relevant section below.

Guidelines for changing HTML markup

 * MediaWiki developers MUST consider caching implications, namely that HTML from a previous deploy may be served to users alongside newer CSS. For pages subject to cache, MediaWiki developers MUST consider how HTML that is less than or greater to a week old (such as HTML generated during the last train cycle) will be styled.
 * MediaWiki developers SHOULD assess the impact of their change to HTML markup based on the popularity of the gadget (for example, using Special:GadgetUsage and en:User scripts/Most imported scripts) using the global search tool to decide whether communication is advisable and what a suitable timeframe for the change might be. As a general rule, popularity can be judged by 50+ scripts in MediaWiki namespace or more than 1000 scripts across the user and MediaWiki namespace. The timeframe should be at least one month, but may warrant longer in some cases. This can be skipped if MediaWiki developers are confident that gadgets will not be severely impacted (for example if the gadget is still functional after the change but stylistically different).
 * For now, use your best judgement on determining usage and popularity. For example the Twinkle gadget is widely used, so an issue that impacts the Twinkle gadget may be more significant than the impact to 100 user scripts.
 * Particular care MUST be taken when changing any element using a class or ID prefixed with  as traditionally this has been viewed as a stable interface or when changing any class that is provided by the MediaWiki wikitext parser (for example,   and  ).
 * In the case of renaming IDs where the class might be mistakenly considered stable per definition of the stable interface (such as due to historic association with the  prefix), developers SHOULD consider a longer grace period.
 * In the case of renaming classes, it is recommended that the new class SHOULD be added along with the removed class for at least one MediaWiki release cycle. An inline comment should indicate in which release the old class was deprecated.

Guidelines for naming

 * All HTML classes prefixed with  generated by MediaWiki core. Note: code outside MediaWiki core SHOULD NOT use the   prefix as it can confuse gadget developers by suggesting a stable API.
 * Extension/skin developers MUST prefix their CSS classes to avoid namespace clashes with wiki-hosted code. Extension/skin developers MUST use a unique prefix other than  (for example, Skin:Vector uses , and Extension:AbuseFilter uses  ). Extension/skin developers are free to use the prefix that makes sense to them. The benefits of this are twofold:
 * 1) Developers can use the codesearch tool to look up where classes originate.
 * 2) Gadget developers will often rely on the   prefixed selectors, and assume they are stable and not prone to change.

Guidelines for changes to HTML structure
All frontend code (including wiki-hosted code, extensions and skins) relying on HTML structure does so at its own risk. MediaWiki developers SHOULD provide and request APIs to access elements or extend existing elements.

Examples:


 * For adding items to menus, the  method is encouraged rather than relying on jQuery.
 * For adding subtitles, use  rather than appending to   or   elements.

Guidelines around modifying default styles
MediaWiki developers MAY change default CSS for content generated by wikitext (such as changing the default link colors or changing typography). While rare, developers should consult the global search tool to inform themselves about potential local overrides made by editors in MediaWiki:Common.css and should follow the communication guidelines in communicating changes to gadget developers when the change may be controversial.

It is generally recommended that, when redesigning styles, MediaWiki developers SHOULD use new classes/IDs where possible, to avoid caching implications (see terminology).

What to do for breaking changes to JavaScript interfaces

 * Code that MUST follow the deprecation policy:
 * Code that is defined on the public  object, regardless of where it is added even if it has not been marked as.
 * Share code between modules privately, using  and   to circumvent this. See mediawiki.String (and mediawiki.Title) as an example of how to share code privately using   and.
 * Hooks fired using the  object in MediaWiki core code.
 * Code that has indicated it is stable in its JavaScript documentation, preferably using the  tag.

See these examples:


 * When deprecating code in this form, method  MUST be used to signal the deprecation of the API. The deprecation message should state the release in which the deprecation happened.
 * When deprecating in this manner, the software MUST log hard deprecation warnings to the JavaScript developer console for at least one MediaWiki release. See example below.
 * MediaWiki developers MUST follow guidelines around communicating changes to gadget developers.

What to do when removing ResourceLoader modules

 * All ResourceLoader modules inside MediaWiki core MUST be considered stable unless marked as deprecated. For modules outside MediaWiki core, there is no need to follow the deprecation policy, unless you have explicitly designed the module for consumption by other extensions/skins.
 * Code that was never part of a public MediaWiki release, and never consumed according to codesearch and global search MAY be changed or removed without deprecation, since it has never become part of the stable interface or used.
 * Before removing a module, the module MUST be deprecated so that using the module logs warnings for at least one MediaWiki release prior to removal. This is to support third party developers who need to be notified and respond to any upstream changes.
 * When deprecating a ResourceLoader module, set the deprecated key on the associated ResourceLoader. When deprecating in this manner, the developer MUST document the deprecation in RELEASE_NOTES and mention the release number in which it was deprecated.
 * Developers MAY fix consumers of a module prior to deprecation, but it is not required as a precursor to deprecation.
 * The software MUST log hard-deprecation warnings in this manner for at least one MediaWiki release. When removed, this should also be documented in RELEASE_NOTES.
 * Communicate the change to gadget developers (see communicating changes to gadget developers).

Maintaining existing features

 * MediaWiki developers SHOULD regularly check the JavaScript console for deprecation notices and warnings and engage with them within one release cycle, by either fixing the issue or making clear why that is not possible.
 * MediaWiki developers MUST pay attention to Phabricator tickets with requests for code maintenance and communicate any challenges they see with resolving them.
 * Code creating complex UIs MUST use Vue.js and MUST follow any guidance that appears in the JavaScript console to maintain compatibility.
 * Code written in OOUI MUST follow any deprecation warnings shown in the JavaScript developer console.

Developing new features

 * All new MediaWiki code deployed to Wikimedia wikis SHOULD consider providing a stable way for on-wiki code to access its most important elements.
 * Newly written code SHOULD NOT use deprecated ResourceLoader modules (such as jQuery.UI).
 * MediaWiki developers MUST regularly review popular gadgets to evaluate code that makes assumptions about the HTML structure or to flag potential APIs using the global-search tool. MediaWiki developers MAY do this as part of their planning process, and MUST evaluate the use case in situations where a gadget developer raises a Phabricator ticket after an incident has occurred (for example, in a situation where a popular gadget breaks).
 * MediaWiki developers SHOULD use feature flagging (such as Extension:BetaFeatures or user preferences) in deployments to allow editors to test interfaces prior to development and SHOULD advertise their availability via m:Tech/News.

Handling breaking changes in widely used but non-maintained gadgets
When making breaking changes, despite good intentions it is inevitable even with good communication that some on-wiki scripts will not be updated by their maintainers and the change will lead to production errors and/or disruption to editor workflows.

Client side errors occurring in wiki-hosted code are tracked alongside errors in Wikimedia code on Grafana and can be explored further inside our logstash instance.

When making breaking changes, MediaWiki developers have a responsibility to fix or disable certain gadgets in the following scenarios:


 * MediaWiki developers MUST fix or disable error logging for any wiki-hosted code and/or user script errors with error volumes that trigger alerts via Wikimedia alerting systems. Having healthy metrics helps us have more confidence when we deploy code. Ideally the fix SHOULD be made by the maintainer of the code after discussion on the script's talk page, however in time sensitive situations MediaWiki developers MAY take action themselves if they feel comfortable doing so.
 * MediaWiki developers MAY fix or disable wiki-hosted code and/or user script errors that undermine user privacy. For example, if an active user is triggering an error on every page load, which reveals their page history, fixing it is encouraged.
 * MediaWiki developers MAY fix or disable wiki-hosted code that is broken, provided the edit summary or the talk page documents how the issue can be fixed.
 * MediaWiki developers MAY run bots to automate fixing wiki-hosted code where resolution is straightforward. Example: a method is renamed.

Communicating changes to gadget developers

 * The scope of this policy regards gadget code that runs on one of the Wikimedia projects. It does not apply to gadgets running on third party instances.
 * If any gadgets/scripts are impacted, then MediaWiki developers SHOULD notify m:Tech/News. For changes that impact more than 10 gadgets (MediaWiki namespace) and/or 1000+ user scripts (user namespace), MediaWiki developers MUST do so.
 * The Tech News entry MUST mention "BREAKING CHANGE" in the title and provide steps to resolve the problem inside the description.
 * A period of at least one month MUST be given for wiki-hosted code developers to respond and raise any concerns relating to the change regardless of MediaWiki release.
 * MediaWiki developers MUST consider any feedback from gadget developers to minimize disruption (for example create tickets around introducing APIs where missing).
 * When learning about the breakage of gadgets on wiki that are not covered by the wiki-hosted code policy, MediaWiki developers MUST assess the inclusion of a new API to reduce future breakage.